4 * Userspace RCU library - Red-Black Tree
6 * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Implementation of RCU-adapted data structures and operations based on the RB
23 * tree algorithms found in chapter 12 of:
25 * Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and
26 * Clifford Stein. Introduction to Algorithms, Third Edition. The MIT
27 * Press, September 2009.
39 #include <urcu/rcurbtree.h>
40 #include <urcu-pointer.h>
41 #include <urcu-call-rcu.h>
42 #include <urcu/compiler.h>
45 #define dbg_printf(args...) printf(args)
47 #define dbg_printf(args...)
51 * Undefine this to enable the non-RCU rotate and transplant functions
54 #define RBTREE_RCU_SUPPORT_ROTATE_LEFT
55 #define RBTREE_RCU_SUPPORT_ROTATE_RIGHT
56 #define RBTREE_RCU_SUPPORT_TRANSPLANT
59 static pthread_mutex_t test_mutex
= PTHREAD_MUTEX_INITIALIZER
;
60 static pthread_mutex_t outer_mutex
= PTHREAD_MUTEX_INITIALIZER
;
63 void lock_outer_mutex(void)
65 pthread_mutex_lock(&outer_mutex
);
69 void unlock_outer_mutex(void)
71 pthread_mutex_unlock(&outer_mutex
);
75 void lock_test_mutex(void)
77 pthread_mutex_lock(&test_mutex
);
81 void unlock_test_mutex(void)
83 pthread_mutex_unlock(&test_mutex
);
88 void set_parent(struct rcu_rbtree_node
*node
,
89 struct rcu_rbtree_node
*parent
,
92 _CMM_STORE_SHARED(node
->parent
, ((unsigned long) parent
) | pos
);
96 struct rcu_rbtree_node
*get_parent(struct rcu_rbtree_node
*node
)
98 return (struct rcu_rbtree_node
*) (node
->parent
& ~1UL);
102 unsigned int get_pos(struct rcu_rbtree_node
*node
)
104 return (unsigned int) (node
->parent
& 1UL);
108 struct rcu_rbtree_node
*get_parent_and_pos(struct rcu_rbtree_node
*node
,
111 unsigned long parent_pos
= rcu_dereference(node
->parent
);
113 *pos
= (unsigned int) (parent_pos
& 1UL);
114 return (struct rcu_rbtree_node
*) (parent_pos
& ~1UL);
118 void set_decay(struct rcu_rbtree_node
*x
, struct rcu_rbtree_node
*xc
)
124 struct rcu_rbtree_node
*get_decay(struct rcu_rbtree_node
*x
)
128 while (x
->decay_next
)
134 struct rcu_rbtree_node
*is_decay(struct rcu_rbtree_node
*x
)
136 return x
->decay_next
;
140 struct rcu_rbtree_node
*dup_decay_node(struct rcu_rbtree
*rbtree
,
141 struct rcu_rbtree_node
*x
)
143 struct rcu_rbtree_node
*xc
;
145 if (rcu_rbtree_is_nil(x
))
148 xc
= rbtree
->rballoc();
149 memcpy(xc
, x
, sizeof(struct rcu_rbtree_node
));
150 xc
->decay_next
= NULL
;
152 call_rcu(&x
->head
, rbtree
->rbfree
);
157 * Info for range lookups:
158 * Range lookup information is only valid when used when searching for
159 * ranges. It should never be used in next/prev traversal because the
160 * pointers to parents are not in sync with the parent vision of the
164 void _set_left_dup_decay(struct rcu_rbtree
*rbtree
,
165 struct rcu_rbtree_node
*node
,
166 struct rcu_rbtree_node
*left
,
167 struct rcu_rbtree_node
**top
,
168 struct rcu_rbtree_node
**top_child
,
169 unsigned int *top_child_pos
, int copy
)
171 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
177 if (rcu_rbtree_is_nil(left
)) {
178 min_child_key
= node
->key
;
180 min_child_key
= left
->min_child_key
;
181 assert(rbtree
->comp(left
->key
, left
->min_child_key
) >= 0);
182 assert(rbtree
->comp(node
->key
, left
->min_child_key
) >= 0);
184 if (min_child_key
!= node
->min_child_key
) {
185 if (node
!= first_node
) {
187 node
= dup_decay_node(rbtree
, node
);
189 set_parent(left
, node
, IS_LEFT
);
192 node
->min_child_key
= min_child_key
;
194 if (node
!= first_node
) {
200 *top_child_pos
= get_pos(left
);
203 *top
= get_parent(node
);
207 *top_child_pos
= get_pos(node
);
212 } while (get_pos(node
) == IS_LEFT
213 && !rcu_rbtree_is_nil(node
= get_parent(node
)));
215 if (rcu_rbtree_is_nil(node
)) {
221 *top_child_pos
= IS_LEFT
; /* arbitrary */
223 assert(get_pos(node
) == IS_RIGHT
);
225 *top
= get_parent(node
);
229 *top_child_pos
= IS_RIGHT
;
234 void set_left_dup_decay(struct rcu_rbtree
*rbtree
,
235 struct rcu_rbtree_node
*node
,
236 struct rcu_rbtree_node
*left
,
237 struct rcu_rbtree_node
**top
,
238 struct rcu_rbtree_node
**top_child
,
239 unsigned int *top_child_pos
)
241 _set_left_dup_decay(rbtree
, node
, left
, top
, top_child
,
246 void set_left_update_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
247 struct rcu_rbtree_node
*left
)
249 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
252 if (node
!= first_node
) {
253 set_parent(node
->_right
,
254 get_decay(get_parent(node
->_right
)), IS_RIGHT
);
256 } while (get_pos(node
) == IS_LEFT
257 && !rcu_rbtree_is_nil(node
= get_parent(node
)));
261 void set_right_dup_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
262 struct rcu_rbtree_node
*right
,
263 struct rcu_rbtree_node
**top
,
264 struct rcu_rbtree_node
**top_child
,
265 unsigned int *top_child_pos
)
267 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
269 node
->_right
= right
;
273 if (rcu_rbtree_is_nil(right
)) {
274 max_child_key
= node
->key
;
276 max_child_key
= right
->max_child_key
;
277 assert(rbtree
->comp(right
->key
, right
->max_child_key
) <= 0);
278 assert(rbtree
->comp(node
->key
, right
->max_child_key
) <= 0);
280 if (max_child_key
!= node
->max_child_key
) {
281 if (node
!= first_node
) {
282 node
= dup_decay_node(rbtree
, node
);
283 node
->_right
= right
;
284 set_parent(right
, node
, IS_RIGHT
);
286 node
->max_child_key
= max_child_key
;
288 if (node
!= first_node
) {
294 *top_child_pos
= get_pos(right
);
297 *top
= get_parent(node
);
301 *top_child_pos
= get_pos(node
);
306 } while (get_pos(node
) == IS_RIGHT
307 && !rcu_rbtree_is_nil(node
= get_parent(node
)));
309 if (rcu_rbtree_is_nil(node
)) {
315 *top_child_pos
= IS_RIGHT
; /* arbitrary */
317 assert(get_pos(node
) == IS_LEFT
);
319 *top
= get_parent(node
);
323 *top_child_pos
= IS_LEFT
;
328 void set_right_update_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
329 struct rcu_rbtree_node
*right
)
331 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
334 if (node
!= first_node
) {
335 set_parent(node
->_left
,
336 get_decay(get_parent(node
->_left
)), IS_LEFT
);
338 } while (get_pos(node
) == IS_RIGHT
339 && !rcu_rbtree_is_nil(node
= get_parent(node
)));
344 * Deal with memory allocation errors.
345 * Can be ensured by reserving a pool of memory entries before doing the
346 * insertion, which will have to be function of number of
347 * transplantations/rotations required for the operation.
352 void show_tree(struct rcu_rbtree
*rbtree
)
354 struct rcu_rbtree_node
*node
;
356 node
= rcu_rbtree_min(rbtree
, rbtree
->root
);
357 while (!rcu_rbtree_is_nil(node
)) {
358 assert(!is_decay(node
));
359 printf("{ 0x%lX p:%lX r:%lX l:%lX %s %s %s} ",
360 (unsigned long)node
->key
,
361 (unsigned long) get_parent(node
)->key
,
362 (unsigned long) node
->_right
->key
,
363 (unsigned long) node
->_left
->key
,
364 node
->color
? "red" : "black",
365 get_pos(node
) ? "right" : "left",
366 node
->nil
? "nil" : "");
367 node
= rcu_rbtree_next(rbtree
, node
);
373 void show_tree(struct rcu_rbtree
*rbtree
)
379 struct rcu_rbtree_node
*make_nil(struct rcu_rbtree
*rbtree
)
381 return &rbtree
->nil_node
;
385 * Iterative rbtree search.
387 struct rcu_rbtree_node
* rcu_rbtree_search(struct rcu_rbtree
*rbtree
,
388 struct rcu_rbtree_node
*x
,
391 x
= rcu_dereference(x
);
393 while (!rcu_rbtree_is_nil(x
) && k
!= x
->key
) {
395 if (rbtree
->comp(k
, x
->key
) < 0)
396 x
= rcu_dereference(x
->_left
);
398 x
= rcu_dereference(x
->_right
);
404 struct rcu_rbtree_node
*rcu_rbtree_min_dup_decay(struct rcu_rbtree
*rbtree
,
405 struct rcu_rbtree_node
*x
,
406 struct rcu_rbtree_node
**zr
)
408 struct rcu_rbtree_node
*xl
;
410 x
= rcu_dereference(x
);
412 if (rcu_rbtree_is_nil(x
)) {
416 *zr
= x
= dup_decay_node(rbtree
, x
);
418 while (!rcu_rbtree_is_nil(xl
= rcu_dereference(x
->_left
))) {
419 x
= dup_decay_node(rbtree
, xl
);
420 set_parent(x
, get_decay(get_parent(x
)), get_pos(x
));
421 get_parent(x
)->_left
= get_decay(get_parent(x
)->_left
);
427 struct rcu_rbtree_node
*rcu_rbtree_min_update_decay(struct rcu_rbtree
*rbtree
,
428 struct rcu_rbtree_node
*x
)
430 struct rcu_rbtree_node
*xl
;
432 x
= rcu_dereference(x
);
434 if (rcu_rbtree_is_nil(x
))
437 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
439 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
443 while (!rcu_rbtree_is_nil(xl
= rcu_dereference(x
->_left
))) {
445 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
447 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
453 struct rcu_rbtree_node
*rcu_rbtree_min(struct rcu_rbtree
*rbtree
,
454 struct rcu_rbtree_node
*x
)
456 struct rcu_rbtree_node
*xl
;
458 x
= rcu_dereference(x
);
460 if (rcu_rbtree_is_nil(x
))
463 while (!rcu_rbtree_is_nil(xl
= rcu_dereference(x
->_left
)))
468 struct rcu_rbtree_node
*rcu_rbtree_max(struct rcu_rbtree
*rbtree
,
469 struct rcu_rbtree_node
*x
)
471 struct rcu_rbtree_node
*xr
;
473 x
= rcu_dereference(x
);
475 if (rcu_rbtree_is_nil(x
))
478 while (!rcu_rbtree_is_nil(xr
= rcu_dereference(x
->_right
)))
485 * Updates should wait for a grace period between update of the
486 * redirect pointer and update of the parent child pointer. This is to make sure
487 * that no reference to the old entry exist.
491 * RCU read lock must be held across the next/prev calls to ensure validity of
494 struct rcu_rbtree_node
*rcu_rbtree_next(struct rcu_rbtree
*rbtree
,
495 struct rcu_rbtree_node
*x
)
497 struct rcu_rbtree_node
*xr
, *y
;
500 x
= rcu_dereference(x
);
502 if (!rcu_rbtree_is_nil(xr
= rcu_dereference(x
->_right
)))
503 return rcu_rbtree_min(rbtree
, xr
);
504 y
= get_parent_and_pos(x
, &x_pos
);
505 while (!rcu_rbtree_is_nil(y
) && x_pos
== IS_RIGHT
) {
507 y
= get_parent_and_pos(y
, &x_pos
);
512 struct rcu_rbtree_node
*rcu_rbtree_prev(struct rcu_rbtree
*rbtree
,
513 struct rcu_rbtree_node
*x
)
515 struct rcu_rbtree_node
*xl
, *y
;
518 x
= rcu_dereference(x
);
520 if (!rcu_rbtree_is_nil(xl
= rcu_dereference(x
->_left
)))
521 return rcu_rbtree_max(rbtree
, xl
);
522 y
= get_parent_and_pos(x
, &x_pos
);
523 while (!rcu_rbtree_is_nil(y
) && x_pos
== IS_LEFT
) {
525 y
= get_parent_and_pos(y
, &x_pos
);
531 * We have to ensure these assumptions are correct for prev/next
534 * with x being a right child, the assumption that:
535 * get_parent(x)->_right == x
536 * or if x is a left child, the assumption that:
537 * get_parent(x)->_left == x
539 * This explains why we have to allocate a vc copy of the node for left_rotate,
540 * right_rotate and transplant operations.
542 * We always ensure that the right/left child and correct parent is set in the
543 * node copies *before* we reparent the children and make the upper-level point
547 /* RCU: copy x and y, atomically point to new versions. GC old. */
548 /* Should be eventually followed by a cmm_smp_wmc() */
550 #ifdef RBTREE_RCU_SUPPORT_ROTATE_LEFT
553 void left_rotate(struct rcu_rbtree
*rbtree
,
554 struct rcu_rbtree_node
*x
)
556 struct rcu_rbtree_node
*y
, *y_left
, *top
, *top_child
;
557 unsigned int top_child_pos
;
562 /* Now operate on new copy, decay old versions */
563 x
= dup_decay_node(rbtree
, x
);
564 y
= dup_decay_node(rbtree
, y
);
565 y_left
= dup_decay_node(rbtree
, y_left
);
567 /* Internal node modifications */
568 set_parent(y
, get_parent(x
), get_pos(x
));
569 set_parent(x
, y
, IS_LEFT
);
570 set_left_dup_decay(rbtree
, y
, x
, &top
, &top_child
, &top_child_pos
);
571 set_right_dup_decay(rbtree
, x
, y_left
, NULL
, NULL
, NULL
);
572 assert(!is_decay(top
));
573 assert(!is_decay(top_child
));
575 if (!rcu_rbtree_is_nil(y_left
))
576 set_parent(y_left
, x
, IS_RIGHT
);
578 cmm_smp_wmb(); /* write into node before publish */
580 /* External references update (visible by readers) */
581 if (rcu_rbtree_is_nil(top
))
582 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
583 else if (top_child_pos
== IS_LEFT
)
584 _CMM_STORE_SHARED(top
->_left
, top_child
);
586 _CMM_STORE_SHARED(top
->_right
, top_child
);
588 /* Point children to new copy (parent only used by updates/next/prev) */
589 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
591 set_parent(y
->_right
, get_decay(get_parent(y
->_right
)),
593 if (!rcu_rbtree_is_nil(y_left
)) {
594 set_parent(y_left
->_right
,
595 get_decay(get_parent(y_left
->_right
)),
596 get_pos(y_left
->_right
));
597 set_parent(y_left
->_left
,
598 get_decay(get_parent(y_left
->_left
)),
599 get_pos(y_left
->_left
));
601 set_left_update_decay(rbtree
, y
, x
);
604 assert(y
== rbtree
->root
|| get_parent(y
)->_left
== y
605 || get_parent(y
)->_right
== y
);
606 assert(x
== rbtree
->root
|| get_parent(x
)->_left
== x
607 || get_parent(x
)->_right
== x
);
608 assert(rcu_rbtree_is_nil(x
->_right
) || get_parent(x
->_right
) == x
);
609 assert(rcu_rbtree_is_nil(x
->_left
) || get_parent(x
->_left
) == x
);
610 assert(rcu_rbtree_is_nil(y
->_right
) || get_parent(y
->_right
) == y
);
611 assert(rcu_rbtree_is_nil(y
->_left
) || get_parent(y
->_left
) == y
);
612 assert(!is_decay(rbtree
->root
));
613 assert(!is_decay(x
));
614 assert(!is_decay(y
));
615 assert(!is_decay(x
->_right
));
616 assert(!is_decay(x
->_left
));
617 assert(!is_decay(y
->_right
));
618 assert(!is_decay(y
->_left
));
623 /* non-rcu version */
625 void left_rotate(struct rcu_rbtree
*rbtree
,
626 struct rcu_rbtree_node
*x
)
628 struct rcu_rbtree_node
*y
;
632 x
->_right
= y
->_left
;
633 if (!rcu_rbtree_is_nil(y
->_left
))
634 set_parent(y
->_left
, x
, IS_RIGHT
);
635 set_parent(y
, get_parent(x
), get_pos(x
));
636 if (rcu_rbtree_is_nil(get_parent(x
)))
638 else if (x
== get_parent(x
)->_left
) {
639 get_parent(x
)->_left
= y
;
641 get_parent(x
)->_right
= y
;
644 set_parent(x
, y
, IS_LEFT
);
650 #ifdef RBTREE_RCU_SUPPORT_ROTATE_RIGHT
652 void right_rotate(struct rcu_rbtree
*rbtree
,
653 struct rcu_rbtree_node
*x
)
655 struct rcu_rbtree_node
*y
, *y_right
, *top
, *top_child
;
656 unsigned int top_child_pos
;
661 /* Now operate on new copy, decay old versions */
662 x
= dup_decay_node(rbtree
, x
);
663 y
= dup_decay_node(rbtree
, y
);
664 y_right
= dup_decay_node(rbtree
, y_right
);
666 /* Internal node modifications */
667 set_parent(y
, get_parent(x
), get_pos(x
));
668 set_parent(x
, y
, IS_RIGHT
);
669 set_right_dup_decay(rbtree
, y
, x
, &top
, &top_child
, &top_child_pos
);
670 set_left_dup_decay(rbtree
, x
, y_right
, NULL
, NULL
, NULL
);
671 assert(!is_decay(top
));
672 assert(!is_decay(top_child
));
674 if (!rcu_rbtree_is_nil(y_right
))
675 set_parent(y_right
, x
, IS_LEFT
);
677 cmm_smp_wmb(); /* write into node before publish */
679 /* External references update (visible by readers) */
680 if (rcu_rbtree_is_nil(top
))
681 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
682 else if (top_child_pos
== IS_RIGHT
)
683 _CMM_STORE_SHARED(top
->_right
, top_child
);
685 _CMM_STORE_SHARED(top
->_left
, top_child
);
687 /* Point children to new copy (parent only used by updates/next/prev) */
688 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
690 set_parent(y
->_left
, get_decay(get_parent(y
->_left
)),
692 if (!rcu_rbtree_is_nil(y_right
)) {
693 set_parent(y_right
->_left
,
694 get_decay(get_parent(y_right
->_left
)),
695 get_pos(y_right
->_left
));
696 set_parent(y_right
->_right
,
697 get_decay(get_parent(y_right
->_right
)),
698 get_pos(y_right
->_right
));
700 set_right_update_decay(rbtree
, y
, x
);
704 assert(y
== rbtree
->root
|| get_parent(y
)->_right
== y
705 || get_parent(y
)->_left
== y
);
706 assert(x
== rbtree
->root
|| get_parent(x
)->_right
== x
707 || get_parent(x
)->_left
== x
);
708 assert(rcu_rbtree_is_nil(x
->_left
) || get_parent(x
->_left
) == x
);
709 assert(rcu_rbtree_is_nil(x
->_right
) || get_parent(x
->_right
) == x
);
710 assert(rcu_rbtree_is_nil(y
->_left
) || get_parent(y
->_left
) == y
);
711 assert(rcu_rbtree_is_nil(y
->_right
) || get_parent(y
->_right
) == y
);
712 assert(!is_decay(rbtree
->root
));
713 assert(!is_decay(x
));
714 assert(!is_decay(y
));
715 assert(!is_decay(x
->_left
));
716 assert(!is_decay(x
->_right
));
717 assert(!is_decay(y
->_left
));
718 assert(!is_decay(y
->_right
));
723 /* non-rcu version */
725 void right_rotate(struct rcu_rbtree
*rbtree
,
726 struct rcu_rbtree_node
*x
)
728 struct rcu_rbtree_node
*y
;
732 x
->_left
= y
->_right
;
733 if (!rcu_rbtree_is_nil(y
->_right
))
734 set_parent(y
->_right
, x
, IS_LEFT
);
735 set_parent(y
, get_parent(x
), get_pos(x
));
736 if (rcu_rbtree_is_nil(get_parent(x
)))
738 else if (x
== get_parent(x
)->_right
) {
739 get_parent(x
)->_right
= y
;
741 get_parent(x
)->_left
= y
;
744 set_parent(x
, y
, IS_RIGHT
);
750 static void rcu_rbtree_insert_fixup(struct rcu_rbtree
*rbtree
,
751 struct rcu_rbtree_node
*z
)
753 struct rcu_rbtree_node
*y
;
755 dbg_printf("insert fixup %p\n", z
->key
);
756 assert(!is_decay(rbtree
->root
));
758 while (get_parent(z
)->color
== COLOR_RED
) {
759 if (get_parent(z
) == get_parent(get_parent(z
))->_left
) {
760 y
= get_parent(get_parent(z
))->_right
;
761 if (y
->color
== COLOR_RED
) {
762 get_parent(z
)->color
= COLOR_BLACK
;
763 y
->color
= COLOR_BLACK
;
764 get_parent(get_parent(z
))->color
= COLOR_RED
;
765 z
= get_parent(get_parent(z
));
767 if (z
== get_parent(z
)->_right
) {
769 left_rotate(rbtree
, z
);
771 assert(!is_decay(rbtree
->root
));
773 get_parent(z
)->color
= COLOR_BLACK
;
774 get_parent(get_parent(z
))->color
= COLOR_RED
;
775 assert(!is_decay(z
));
776 assert(!is_decay(get_parent(z
)));
777 assert(!is_decay(get_parent(get_parent(z
))));
778 right_rotate(rbtree
, get_parent(get_parent(z
)));
779 assert(!is_decay(z
));
780 assert(!is_decay(rbtree
->root
));
783 y
= get_parent(get_parent(z
))->_left
;
784 if (y
->color
== COLOR_RED
) {
785 get_parent(z
)->color
= COLOR_BLACK
;
786 y
->color
= COLOR_BLACK
;
787 get_parent(get_parent(z
))->color
= COLOR_RED
;
788 z
= get_parent(get_parent(z
));
790 if (z
== get_parent(z
)->_left
) {
792 right_rotate(rbtree
, z
);
794 assert(!is_decay(rbtree
->root
));
796 get_parent(z
)->color
= COLOR_BLACK
;
797 get_parent(get_parent(z
))->color
= COLOR_RED
;
798 left_rotate(rbtree
, get_parent(get_parent(z
)));
799 assert(!is_decay(z
));
800 assert(!is_decay(rbtree
->root
));
804 rbtree
->root
->color
= COLOR_BLACK
;
808 * rcu_rbtree_insert - Insert a node in the RCU rbtree
810 * Returns 0 on success, or < 0 on error.
812 int rcu_rbtree_insert(struct rcu_rbtree
*rbtree
,
813 struct rcu_rbtree_node
*z
)
815 struct rcu_rbtree_node
*x
, *y
, *top
, *top_child
;
816 unsigned int top_child_pos
;
818 dbg_printf("insert %p\n", z
->key
);
819 assert(!is_decay(rbtree
->root
));
821 y
= make_nil(rbtree
);
823 while (!rcu_rbtree_is_nil(x
)) {
825 if (rbtree
->comp(z
->key
, x
->key
) < 0)
831 z
->_left
= make_nil(rbtree
);
832 z
->_right
= make_nil(rbtree
);
833 z
->min_child_key
= z
->key
;
834 z
->max_child_key
= z
->key
;
835 z
->color
= COLOR_RED
;
837 z
->decay_next
= NULL
;
839 if (rcu_rbtree_is_nil(y
))
840 set_parent(z
, y
, IS_RIGHT
); /* pos arbitrary for root node */
841 else if (rbtree
->comp(z
->key
, y
->key
) < 0)
842 set_parent(z
, y
, IS_LEFT
);
844 set_parent(z
, y
, IS_RIGHT
);
847 * Order stores to z (children/parents) before stores that will make it
848 * visible to the rest of the tree.
852 if (rcu_rbtree_is_nil(y
)) {
853 _CMM_STORE_SHARED(rbtree
->root
, z
);
854 } else if (rbtree
->comp(z
->key
, y
->key
) < 0) {
855 set_left_dup_decay(rbtree
, y
, z
, &top
, &top_child
,
857 if (rcu_rbtree_is_nil(top
))
858 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
859 else if (top_child_pos
== IS_LEFT
)
860 _CMM_STORE_SHARED(top
->_left
, top_child
);
862 _CMM_STORE_SHARED(top
->_right
, top_child
);
863 set_left_update_decay(rbtree
, y
, z
);
865 set_right_dup_decay(rbtree
, y
, z
, &top
, &top_child
,
867 if (rcu_rbtree_is_nil(top
))
868 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
869 else if (top_child_pos
== IS_LEFT
)
870 _CMM_STORE_SHARED(top
->_left
, top_child
);
872 _CMM_STORE_SHARED(top
->_right
, top_child
);
873 set_right_update_decay(rbtree
, y
, z
);
875 rcu_rbtree_insert_fixup(rbtree
, z
);
877 * Make sure to commit all _CMM_STORE_SHARED() for non-coherent caches.
886 * Transplant v into u position.
889 #ifdef RBTREE_RCU_SUPPORT_TRANSPLANT
892 void rcu_rbtree_transplant(struct rcu_rbtree
*rbtree
,
893 struct rcu_rbtree_node
*u
,
894 struct rcu_rbtree_node
*v
,
895 unsigned int copy_parents
)
897 struct rcu_rbtree_node
*top
, *top_child
;
898 unsigned int top_child_pos
;
900 dbg_printf("transplant %p\n", v
->key
);
902 if (!rcu_rbtree_is_nil(v
))
903 v
= dup_decay_node(rbtree
, v
);
905 if (rcu_rbtree_is_nil(get_parent(u
))) {
906 /* pos is arbitrary for root node */
907 set_parent(v
, get_parent(u
), IS_RIGHT
);
908 cmm_smp_wmb(); /* write into node before publish */
909 _CMM_STORE_SHARED(rbtree
->root
, v
);
911 set_parent(v
, get_parent(u
), get_pos(u
));
912 cmm_smp_wmb(); /* write into node before publish */
914 if (get_pos(u
) == IS_LEFT
) {
915 _set_left_dup_decay(rbtree
, get_parent(u
), v
,
916 &top
, &top_child
, &top_child_pos
,
919 assert(copy_parents
);
920 set_right_dup_decay(rbtree
, get_parent(u
), v
,
921 &top
, &top_child
, &top_child_pos
);
924 if (rcu_rbtree_is_nil(top
))
925 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
926 else if (top_child_pos
== IS_LEFT
)
927 _CMM_STORE_SHARED(top
->_left
, top_child
);
929 _CMM_STORE_SHARED(top
->_right
, top_child
);
931 /* Point children to new copy (parent only used by updates/next/prev) */
932 if (get_pos(u
) == IS_LEFT
) {
934 set_left_update_decay(rbtree
, get_parent(u
), v
);
936 assert(copy_parents
);
937 set_right_update_decay(rbtree
, get_parent(u
), v
);
941 /* Point children to new copy (parent only used by updates/next/prev) */
942 if (!rcu_rbtree_is_nil(v
)) {
943 set_parent(v
->_right
, get_decay(get_parent(v
->_right
)),
945 set_parent(v
->_left
, get_decay(get_parent(v
->_left
)),
948 assert(!is_decay(rbtree
->root
));
953 /* Non-RCU version */
955 void rcu_rbtree_transplant(struct rcu_rbtree
*rbtree
,
956 struct rcu_rbtree_node
*u
,
957 struct rcu_rbtree_node
*v
,
958 unsigned int copy_parents
)
960 dbg_printf("transplant %p\n", v
->key
);
963 if (rcu_rbtree_is_nil(get_parent(u
)))
965 else if (u
== get_parent(u
)->_left
)
966 get_parent(u
)->_left
= v
;
968 get_parent(u
)->_right
= v
;
969 set_parent(v
, get_parent(u
), get_pos(u
));
975 static void rcu_rbtree_remove_fixup(struct rcu_rbtree
*rbtree
,
976 struct rcu_rbtree_node
*x
)
978 dbg_printf("remove fixup %p\n", x
->key
);
980 while (x
!= rbtree
->root
&& x
->color
== COLOR_BLACK
) {
981 assert(!is_decay(get_parent(x
)));
982 assert(!is_decay(get_parent(x
)->_left
));
983 if (x
== get_parent(x
)->_left
) {
984 struct rcu_rbtree_node
*w
;
986 w
= get_parent(x
)->_right
;
988 if (w
->color
== COLOR_RED
) {
989 w
->color
= COLOR_BLACK
;
990 get_parent(x
)->color
= COLOR_RED
;
991 left_rotate(rbtree
, get_parent(x
));
993 assert(!is_decay(rbtree
->root
));
994 w
= get_parent(x
)->_right
;
996 if (w
->_left
->color
== COLOR_BLACK
997 && w
->_right
->color
== COLOR_BLACK
) {
998 w
->color
= COLOR_RED
;
1000 assert(!is_decay(rbtree
->root
));
1001 assert(!is_decay(x
));
1003 if (w
->_right
->color
== COLOR_BLACK
) {
1004 w
->_left
->color
= COLOR_BLACK
;
1005 w
->color
= COLOR_RED
;
1006 right_rotate(rbtree
, w
);
1007 assert(!is_decay(rbtree
->root
));
1009 w
= get_parent(x
)->_right
;
1011 w
->color
= get_parent(x
)->color
;
1012 get_parent(x
)->color
= COLOR_BLACK
;
1013 w
->_right
->color
= COLOR_BLACK
;
1014 left_rotate(rbtree
, get_parent(x
));
1015 assert(!is_decay(rbtree
->root
));
1019 struct rcu_rbtree_node
*w
;
1021 w
= get_parent(x
)->_left
;
1023 if (w
->color
== COLOR_RED
) {
1024 w
->color
= COLOR_BLACK
;
1025 get_parent(x
)->color
= COLOR_RED
;
1026 right_rotate(rbtree
, get_parent(x
));
1027 assert(!is_decay(rbtree
->root
));
1029 w
= get_parent(x
)->_left
;
1031 if (w
->_right
->color
== COLOR_BLACK
1032 && w
->_left
->color
== COLOR_BLACK
) {
1033 w
->color
= COLOR_RED
;
1035 assert(!is_decay(rbtree
->root
));
1036 assert(!is_decay(x
));
1038 if (w
->_left
->color
== COLOR_BLACK
) {
1039 w
->_right
->color
= COLOR_BLACK
;
1040 w
->color
= COLOR_RED
;
1041 left_rotate(rbtree
, w
);
1042 assert(!is_decay(rbtree
->root
));
1044 w
= get_parent(x
)->_left
;
1046 w
->color
= get_parent(x
)->color
;
1047 get_parent(x
)->color
= COLOR_BLACK
;
1048 w
->_left
->color
= COLOR_BLACK
;
1049 right_rotate(rbtree
, get_parent(x
));
1050 assert(!is_decay(rbtree
->root
));
1055 x
->color
= COLOR_BLACK
;
1059 * Delete z. All non-copied children left/right positions are unchanged.
1062 void rcu_rbtree_remove_nonil(struct rcu_rbtree
*rbtree
,
1063 struct rcu_rbtree_node
*z
,
1064 struct rcu_rbtree_node
*y
)
1066 struct rcu_rbtree_node
*x
, *top
, *top_child
;
1067 unsigned int top_child_pos
;
1069 dbg_printf("remove nonil %p\n", z
->key
);
1072 assert(!is_decay(z
));
1073 assert(!is_decay(y
));
1074 assert(!is_decay(y
->_right
));
1075 assert(!is_decay(get_parent(y
)));
1077 assert(!is_decay(x
));
1078 if (get_parent(y
) == z
) {
1079 y
= dup_decay_node(rbtree
, y
);
1080 set_parent(x
, y
, get_pos(x
)); /* parent for nil */
1081 /* y is z's right node: set left will just update y */
1082 set_left_dup_decay(rbtree
, y
, z
->_left
,
1083 &top
, &top_child
, &top_child_pos
);
1084 assert(top_child
== y
);
1085 rcu_rbtree_transplant(rbtree
, z
, y
, 1);
1087 struct rcu_rbtree_node
*oy_right
, *z_right
;
1090 * Need to make sure y is always visible by readers.
1092 y
= rcu_rbtree_min_dup_decay(rbtree
, z
->_right
, &z_right
);
1093 assert(!is_decay(y
));
1094 assert(!is_decay(z
));
1095 oy_right
= y
->_right
;
1098 * The max child key of z_right does not change, because
1099 * we're only changing its left children.
1101 y
->_right
= z_right
;
1102 set_parent(y
->_right
, y
, IS_RIGHT
);
1103 if (rcu_rbtree_is_nil(y
->_right
))
1104 y
->max_child_key
= y
->key
;
1106 y
->max_child_key
= y
->_right
->max_child_key
;
1108 assert(!is_decay(z
->_left
));
1109 y
->_left
= z
->_left
;
1110 if (rcu_rbtree_is_nil(y
->_left
))
1111 y
->min_child_key
= y
->key
;
1113 y
->min_child_key
= y
->_left
->min_child_key
;
1115 assert(!is_decay(oy_right
));
1117 * Transplant of oy_right to old y's location will only
1118 * trigger a min/max update of the already copied branch
1119 * (which is not visible yet). We are transplanting
1120 * oy_right as a left child of old y's parent, so the
1121 * min values update propagated upward necessarily stops
1124 rcu_rbtree_transplant(rbtree
, y
, oy_right
, 0);
1125 rcu_rbtree_transplant(rbtree
, z
, y
, 1);
1126 /* Update children */
1127 (void) rcu_rbtree_min_update_decay(rbtree
, y
->_right
);
1130 assert(!is_decay(z
));
1131 assert(!is_decay(z
->_left
));
1132 y
->color
= z
->color
;
1133 set_parent(y
->_left
, y
, IS_LEFT
);
1134 set_parent(y
->_right
, get_decay(get_parent(y
->_right
)), IS_RIGHT
);
1135 assert(!is_decay(y
->_left
));
1136 assert(!is_decay(y
->_right
));
1139 int rcu_rbtree_remove(struct rcu_rbtree
*rbtree
,
1140 struct rcu_rbtree_node
*z
)
1142 struct rcu_rbtree_node
*x
, *y
;
1143 unsigned int y_original_color
;
1145 assert(!is_decay(rbtree
->root
));
1146 dbg_printf("remove %p\n", z
->key
);
1149 assert(!is_decay(z
));
1151 y_original_color
= y
->color
;
1153 if (rcu_rbtree_is_nil(z
->_left
)) {
1154 rcu_rbtree_transplant(rbtree
, z
, z
->_right
, 1);
1155 assert(!is_decay(z
));
1156 x
= get_decay(z
->_right
);
1158 } else if (rcu_rbtree_is_nil(z
->_right
)) {
1159 rcu_rbtree_transplant(rbtree
, z
, z
->_left
, 1);
1160 assert(!is_decay(z
));
1161 x
= get_decay(z
->_left
);
1164 y
= rcu_rbtree_min(rbtree
, z
->_right
);
1165 assert(!is_decay(y
));
1166 y_original_color
= y
->color
;
1168 rcu_rbtree_remove_nonil(rbtree
, z
, y
);
1172 if (y_original_color
== COLOR_BLACK
)
1173 rcu_rbtree_remove_fixup(rbtree
, x
);
1176 * Commit all _CMM_STORE_SHARED().