Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rbtree, sched/deadline: Use rb_add_cached()

Reduce rbtree boiler plate by using the new helpers.

Make rb_add_cached() / rb_erase_cached() return a pointer to the
leftmost node to aid in updating additional state.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Davidlohr Bueso <dbueso@suse.de>

authored by

Peter Zijlstra and committed by
Ingo Molnar
8ecca394 bf9be9a1

+42 -53
+14 -4
include/linux/rbtree.h
··· 141 141 rb_insert_color(node, &root->rb_root); 142 142 } 143 143 144 - static inline void rb_erase_cached(struct rb_node *node, 145 - struct rb_root_cached *root) 144 + 145 + static inline struct rb_node * 146 + rb_erase_cached(struct rb_node *node, struct rb_root_cached *root) 146 147 { 148 + struct rb_node *leftmost = NULL; 149 + 147 150 if (root->rb_leftmost == node) 148 - root->rb_leftmost = rb_next(node); 151 + leftmost = root->rb_leftmost = rb_next(node); 152 + 149 153 rb_erase(node, &root->rb_root); 154 + 155 + return leftmost; 150 156 } 151 157 152 158 static inline void rb_replace_node_cached(struct rb_node *victim, ··· 185 179 * @node: node to insert 186 180 * @tree: leftmost cached tree to insert @node into 187 181 * @less: operator defining the (partial) node order 182 + * 183 + * Returns @node when it is the new leftmost, or NULL. 188 184 */ 189 - static __always_inline void 185 + static __always_inline struct rb_node * 190 186 rb_add_cached(struct rb_node *node, struct rb_root_cached *tree, 191 187 bool (*less)(struct rb_node *, const struct rb_node *)) 192 188 { ··· 208 200 209 201 rb_link_node(node, parent, link); 210 202 rb_insert_color_cached(node, tree, leftmost); 203 + 204 + return leftmost ? node : NULL; 211 205 } 212 206 213 207 /**
+28 -49
kernel/sched/deadline.c
··· 517 517 update_dl_migration(dl_rq); 518 518 } 519 519 520 + #define __node_2_pdl(node) \ 521 + rb_entry((node), struct task_struct, pushable_dl_tasks) 522 + 523 + static inline bool __pushable_less(struct rb_node *a, const struct rb_node *b) 524 + { 525 + return dl_entity_preempt(&__node_2_pdl(a)->dl, &__node_2_pdl(b)->dl); 526 + } 527 + 520 528 /* 521 529 * The list of pushable -deadline task is not a plist, like in 522 530 * sched_rt.c, it is an rb-tree with tasks ordered by deadline. 523 531 */ 524 532 static void enqueue_pushable_dl_task(struct rq *rq, struct task_struct *p) 525 533 { 526 - struct dl_rq *dl_rq = &rq->dl; 527 - struct rb_node **link = &dl_rq->pushable_dl_tasks_root.rb_root.rb_node; 528 - struct rb_node *parent = NULL; 529 - struct task_struct *entry; 530 - bool leftmost = true; 534 + struct rb_node *leftmost; 531 535 532 536 BUG_ON(!RB_EMPTY_NODE(&p->pushable_dl_tasks)); 533 537 534 - while (*link) { 535 - parent = *link; 536 - entry = rb_entry(parent, struct task_struct, 537 - pushable_dl_tasks); 538 - if (dl_entity_preempt(&p->dl, &entry->dl)) 539 - link = &parent->rb_left; 540 - else { 541 - link = &parent->rb_right; 542 - leftmost = false; 543 - } 544 - } 545 - 538 + leftmost = rb_add_cached(&p->pushable_dl_tasks, 539 + &rq->dl.pushable_dl_tasks_root, 540 + __pushable_less); 546 541 if (leftmost) 547 - dl_rq->earliest_dl.next = p->dl.deadline; 548 - 549 - rb_link_node(&p->pushable_dl_tasks, parent, link); 550 - rb_insert_color_cached(&p->pushable_dl_tasks, 551 - &dl_rq->pushable_dl_tasks_root, leftmost); 542 + rq->dl.earliest_dl.next = p->dl.deadline; 552 543 } 553 544 554 545 static void dequeue_pushable_dl_task(struct rq *rq, struct task_struct *p) 555 546 { 556 547 struct dl_rq *dl_rq = &rq->dl; 548 + struct rb_root_cached *root = &dl_rq->pushable_dl_tasks_root; 549 + struct rb_node *leftmost; 557 550 558 551 if (RB_EMPTY_NODE(&p->pushable_dl_tasks)) 559 552 return; 560 553 561 - if (dl_rq->pushable_dl_tasks_root.rb_leftmost == &p->pushable_dl_tasks) { 562 - struct rb_node *next_node; 554 + leftmost = rb_erase_cached(&p->pushable_dl_tasks, root); 555 + if (leftmost) 556 + dl_rq->earliest_dl.next = __node_2_pdl(leftmost)->dl.deadline; 563 557 564 - next_node = rb_next(&p->pushable_dl_tasks); 565 - if (next_node) { 566 - dl_rq->earliest_dl.next = rb_entry(next_node, 567 - struct task_struct, pushable_dl_tasks)->dl.deadline; 568 - } 569 - } 570 - 571 - rb_erase_cached(&p->pushable_dl_tasks, &dl_rq->pushable_dl_tasks_root); 572 558 RB_CLEAR_NODE(&p->pushable_dl_tasks); 573 559 } 574 560 ··· 1464 1478 dec_dl_migration(dl_se, dl_rq); 1465 1479 } 1466 1480 1481 + #define __node_2_dle(node) \ 1482 + rb_entry((node), struct sched_dl_entity, rb_node) 1483 + 1484 + static inline bool __dl_less(struct rb_node *a, const struct rb_node *b) 1485 + { 1486 + return dl_time_before(__node_2_dle(a)->deadline, __node_2_dle(b)->deadline); 1487 + } 1488 + 1467 1489 static void __enqueue_dl_entity(struct sched_dl_entity *dl_se) 1468 1490 { 1469 1491 struct dl_rq *dl_rq = dl_rq_of_se(dl_se); 1470 - struct rb_node **link = &dl_rq->root.rb_root.rb_node; 1471 - struct rb_node *parent = NULL; 1472 - struct sched_dl_entity *entry; 1473 - int leftmost = 1; 1474 1492 1475 1493 BUG_ON(!RB_EMPTY_NODE(&dl_se->rb_node)); 1476 1494 1477 - while (*link) { 1478 - parent = *link; 1479 - entry = rb_entry(parent, struct sched_dl_entity, rb_node); 1480 - if (dl_time_before(dl_se->deadline, entry->deadline)) 1481 - link = &parent->rb_left; 1482 - else { 1483 - link = &parent->rb_right; 1484 - leftmost = 0; 1485 - } 1486 - } 1487 - 1488 - rb_link_node(&dl_se->rb_node, parent, link); 1489 - rb_insert_color_cached(&dl_se->rb_node, &dl_rq->root, leftmost); 1495 + rb_add_cached(&dl_se->rb_node, &dl_rq->root, __dl_less); 1490 1496 1491 1497 inc_dl_tasks(dl_se, dl_rq); 1492 1498 } ··· 1491 1513 return; 1492 1514 1493 1515 rb_erase_cached(&dl_se->rb_node, &dl_rq->root); 1516 + 1494 1517 RB_CLEAR_NODE(&dl_se->rb_node); 1495 1518 1496 1519 dec_dl_tasks(dl_se, dl_rq);