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)
46 #define dbg_usleep(usecs) usleep(usecs)
48 #define dbg_printf(args...)
49 #define dbg_usleep(usecs)
53 * Undefine this to enable the non-RCU rotate and transplant functions
56 #define RBTREE_RCU_SUPPORT_ROTATE_LEFT
57 #define RBTREE_RCU_SUPPORT_ROTATE_RIGHT
58 #define RBTREE_RCU_SUPPORT_TRANSPLANT
61 static pthread_mutex_t test_mutex
= PTHREAD_MUTEX_INITIALIZER
;
62 static pthread_mutex_t outer_mutex
= PTHREAD_MUTEX_INITIALIZER
;
65 void lock_outer_mutex(void)
67 pthread_mutex_lock(&outer_mutex
);
71 void unlock_outer_mutex(void)
73 pthread_mutex_unlock(&outer_mutex
);
77 void lock_test_mutex(void)
79 pthread_mutex_lock(&test_mutex
);
83 void unlock_test_mutex(void)
85 pthread_mutex_unlock(&test_mutex
);
90 void set_parent(struct rcu_rbtree_node
*node
,
91 struct rcu_rbtree_node
*parent
,
94 _CMM_STORE_SHARED(node
->parent
, ((unsigned long) parent
) | pos
);
98 struct rcu_rbtree_node
*get_parent(struct rcu_rbtree_node
*node
)
100 return (struct rcu_rbtree_node
*) (node
->parent
& ~1UL);
104 unsigned int get_pos(struct rcu_rbtree_node
*node
)
106 return (unsigned int) (node
->parent
& 1UL);
110 struct rcu_rbtree_node
*get_parent_and_pos(struct rcu_rbtree_node
*node
,
113 unsigned long parent_pos
= rcu_dereference(node
->parent
);
115 *pos
= (unsigned int) (parent_pos
& 1UL);
116 return (struct rcu_rbtree_node
*) (parent_pos
& ~1UL);
120 void set_decay(struct rcu_rbtree_node
*x
, struct rcu_rbtree_node
*xc
)
126 struct rcu_rbtree_node
*get_decay(struct rcu_rbtree_node
*x
)
130 while (x
->decay_next
)
136 struct rcu_rbtree_node
*is_decay(struct rcu_rbtree_node
*x
)
138 return x
->decay_next
;
142 struct rcu_rbtree_node
*dup_decay_node(struct rcu_rbtree
*rbtree
,
143 struct rcu_rbtree_node
*x
)
145 struct rcu_rbtree_node
*xc
;
147 if (rcu_rbtree_is_nil(rbtree
, x
))
150 xc
= rbtree
->rballoc();
151 memcpy(xc
, x
, sizeof(struct rcu_rbtree_node
));
152 xc
->decay_next
= NULL
;
154 call_rcu(&x
->head
, rbtree
->rbfree
);
159 * Info for range lookups:
160 * Range lookup information is only valid when used when searching for
161 * ranges. It should never be used in next/prev traversal because the
162 * pointers to parents are not in sync with the parent vision of the
166 void _set_left_dup_decay(struct rcu_rbtree
*rbtree
,
167 struct rcu_rbtree_node
*node
,
168 struct rcu_rbtree_node
*left
,
169 struct rcu_rbtree_node
**top
,
170 struct rcu_rbtree_node
**top_child
,
171 unsigned int *top_child_pos
, int copy
)
173 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
179 if (rcu_rbtree_is_nil(rbtree
, left
)) {
180 min_child_key
= node
->key
;
182 min_child_key
= left
->min_child_key
;
183 assert(rbtree
->comp(left
->key
, left
->min_child_key
) >= 0);
184 assert(rbtree
->comp(node
->key
, left
->min_child_key
) >= 0);
186 if (min_child_key
!= node
->min_child_key
) {
187 if (node
!= first_node
) {
189 node
= dup_decay_node(rbtree
, node
);
191 set_parent(left
, node
, IS_LEFT
);
194 node
->min_child_key
= min_child_key
;
196 if (node
!= first_node
) {
202 *top_child_pos
= get_pos(left
);
205 *top
= get_parent(node
);
209 *top_child_pos
= get_pos(node
);
214 } while (get_pos(node
) == IS_LEFT
215 && !rcu_rbtree_is_nil(rbtree
, node
= get_parent(node
)));
217 if (rcu_rbtree_is_nil(rbtree
, node
)) {
223 *top_child_pos
= IS_LEFT
; /* arbitrary */
225 assert(get_pos(node
) == IS_RIGHT
);
227 *top
= get_parent(node
);
231 *top_child_pos
= IS_RIGHT
;
236 void set_left_dup_decay(struct rcu_rbtree
*rbtree
,
237 struct rcu_rbtree_node
*node
,
238 struct rcu_rbtree_node
*left
,
239 struct rcu_rbtree_node
**top
,
240 struct rcu_rbtree_node
**top_child
,
241 unsigned int *top_child_pos
)
243 _set_left_dup_decay(rbtree
, node
, left
, top
, top_child
,
248 void set_left_update_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
249 struct rcu_rbtree_node
*left
)
251 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
254 if (node
!= first_node
) {
255 set_parent(node
->_right
,
256 get_decay(get_parent(node
->_right
)), IS_RIGHT
);
258 } while (get_pos(node
) == IS_LEFT
259 && !rcu_rbtree_is_nil(rbtree
, node
= get_parent(node
)));
263 void set_right_dup_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
264 struct rcu_rbtree_node
*right
,
265 struct rcu_rbtree_node
**top
,
266 struct rcu_rbtree_node
**top_child
,
267 unsigned int *top_child_pos
)
269 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
271 node
->_right
= right
;
275 if (rcu_rbtree_is_nil(rbtree
, right
)) {
276 max_child_key
= node
->key
;
278 max_child_key
= right
->max_child_key
;
279 assert(rbtree
->comp(right
->key
, right
->max_child_key
) <= 0);
280 assert(rbtree
->comp(node
->key
, right
->max_child_key
) <= 0);
282 if (max_child_key
!= node
->max_child_key
) {
283 if (node
!= first_node
) {
284 node
= dup_decay_node(rbtree
, node
);
285 node
->_right
= right
;
286 set_parent(right
, node
, IS_RIGHT
);
288 node
->max_child_key
= max_child_key
;
290 if (node
!= first_node
) {
296 *top_child_pos
= get_pos(right
);
299 *top
= get_parent(node
);
303 *top_child_pos
= get_pos(node
);
308 } while (get_pos(node
) == IS_RIGHT
309 && !rcu_rbtree_is_nil(rbtree
, node
= get_parent(node
)));
311 if (rcu_rbtree_is_nil(rbtree
, node
)) {
317 *top_child_pos
= IS_RIGHT
; /* arbitrary */
319 assert(get_pos(node
) == IS_LEFT
);
321 *top
= get_parent(node
);
325 *top_child_pos
= IS_LEFT
;
330 void set_right_update_decay(struct rcu_rbtree
*rbtree
, struct rcu_rbtree_node
*node
,
331 struct rcu_rbtree_node
*right
)
333 struct rcu_rbtree_node
*first_node
= node
; /* already a copy */
336 if (node
!= first_node
) {
337 set_parent(node
->_left
,
338 get_decay(get_parent(node
->_left
)), IS_LEFT
);
340 } while (get_pos(node
) == IS_RIGHT
341 && !rcu_rbtree_is_nil(rbtree
, node
= get_parent(node
)));
346 * Deal with memory allocation errors.
347 * Can be ensured by reserving a pool of memory entries before doing the
348 * insertion, which will have to be function of number of
349 * transplantations/rotations required for the operation.
354 void show_tree(struct rcu_rbtree
*rbtree
)
356 struct rcu_rbtree_node
*node
;
358 node
= rcu_rbtree_min(rbtree
, rbtree
->root
);
359 while (!rcu_rbtree_is_nil(rbtree
, node
)) {
360 assert(!is_decay(node
));
361 printf("{ 0x%lX p:%lX r:%lX l:%lX %s %s %s} ",
362 (unsigned long)node
->key
,
363 (unsigned long) get_parent(node
)->key
,
364 (unsigned long) node
->_right
->key
,
365 (unsigned long) node
->_left
->key
,
366 node
->color
? "red" : "black",
367 get_pos(node
) ? "right" : "left",
368 node
->nil
? "nil" : "");
369 node
= rcu_rbtree_next(rbtree
, node
);
375 void show_tree(struct rcu_rbtree
*rbtree
)
381 struct rcu_rbtree_node
*make_nil(struct rcu_rbtree
*rbtree
)
383 return &rbtree
->nil_node
;
387 * Iterative rbtree search.
389 struct rcu_rbtree_node
*rcu_rbtree_search(struct rcu_rbtree
*rbtree
,
390 struct rcu_rbtree_node
*x
,
393 x
= rcu_dereference(x
);
396 while (!rcu_rbtree_is_nil(rbtree
, x
) && (comp
= rbtree
->comp(k
, x
->key
)) != 0) {
399 x
= rcu_dereference(x
->_left
);
401 x
= rcu_dereference(x
->_right
);
406 struct rcu_rbtree_node
*rcu_rbtree_search_min(struct rcu_rbtree
*rbtree
,
407 struct rcu_rbtree_node
*x
,
408 void *range_low
, void *range_high
)
410 struct rcu_rbtree_node
*xl
;
411 x
= rcu_dereference(x
);
413 dbg_printf("start search min x %lx low %lx high %lx\n",
414 (unsigned long) x
->key
,
415 (unsigned long) range_low
, (unsigned long) range_high
);
416 while (!rcu_rbtree_is_nil(rbtree
, x
)) {
418 xl
= rcu_dereference(x
->_left
);
419 dbg_printf("search min x %lx\n", (unsigned long) x
->key
);
420 dbg_printf("search min xl %lx\n", (unsigned long) xl
->key
);
421 if (!rcu_rbtree_is_nil(rbtree
, xl
)
422 && (rbtree
->comp(xl
->max_child_key
, range_low
) >= 0
423 || rbtree
->comp(xl
->key
, range_low
) == 0)) {
424 dbg_printf("go left\n");
426 } else if (rbtree
->comp(x
->key
, range_low
) >= 0
427 && rbtree
->comp(x
->key
, range_high
) <= 0) {
428 dbg_printf("got it!\n");
430 } else if (rbtree
->comp(range_low
, x
->min_child_key
) >= 0) {
431 dbg_printf("go right\n");
432 x
= rcu_dereference(x
->_right
);
434 dbg_printf("not found!\n");
435 x
= make_nil(rbtree
);
441 struct rcu_rbtree_node
*rcu_rbtree_search_max(struct rcu_rbtree
*rbtree
,
442 struct rcu_rbtree_node
*x
,
443 void *range_low
, void *range_high
)
445 struct rcu_rbtree_node
*xr
;
446 x
= rcu_dereference(x
);
448 dbg_printf("start search max x %lx low %lx high %lx\n",
449 (unsigned long) x
->key
,
450 (unsigned long) range_low
, (unsigned long) range_high
);
451 while (!rcu_rbtree_is_nil(rbtree
, x
)) {
453 xr
= rcu_dereference(x
->_right
);
454 dbg_printf("search max x %lx\n", (unsigned long) x
->key
);
455 dbg_printf("search max xl %lx\n", (unsigned long) xr
->key
);
456 if (!rcu_rbtree_is_nil(rbtree
, xr
)
457 && (rbtree
->comp(xr
->min_child_key
, range_high
) <= 0
458 || rbtree
->comp(xr
->key
, range_high
) == 0)) {
459 dbg_printf("go right\n");
461 } else if (rbtree
->comp(x
->key
, range_low
) >= 0
462 && rbtree
->comp(x
->key
, range_high
) <= 0) {
463 dbg_printf("got it!\n");
465 } else if (rbtree
->comp(range_high
, x
->max_child_key
) <= 0) {
466 dbg_printf("go left\n");
467 x
= rcu_dereference(x
->_left
);
469 dbg_printf("not found!\n");
470 x
= make_nil(rbtree
);
477 struct rcu_rbtree_node
*rcu_rbtree_min_dup_decay(struct rcu_rbtree
*rbtree
,
478 struct rcu_rbtree_node
*x
,
479 struct rcu_rbtree_node
**zr
)
481 struct rcu_rbtree_node
*xl
;
483 x
= rcu_dereference(x
);
485 if (rcu_rbtree_is_nil(rbtree
, x
)) {
489 *zr
= x
= dup_decay_node(rbtree
, x
);
491 while (!rcu_rbtree_is_nil(rbtree
, xl
= rcu_dereference(x
->_left
))) {
492 x
= dup_decay_node(rbtree
, xl
);
493 set_parent(x
, get_decay(get_parent(x
)), get_pos(x
));
494 get_parent(x
)->_left
= get_decay(get_parent(x
)->_left
);
500 struct rcu_rbtree_node
*rcu_rbtree_min_update_decay(struct rcu_rbtree
*rbtree
,
501 struct rcu_rbtree_node
*x
)
503 struct rcu_rbtree_node
*xl
;
505 x
= rcu_dereference(x
);
507 if (rcu_rbtree_is_nil(rbtree
, x
))
510 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
512 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
516 while (!rcu_rbtree_is_nil(rbtree
, xl
= rcu_dereference(x
->_left
))) {
518 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
520 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
526 struct rcu_rbtree_node
*rcu_rbtree_min(struct rcu_rbtree
*rbtree
,
527 struct rcu_rbtree_node
*x
)
529 struct rcu_rbtree_node
*xl
;
531 x
= rcu_dereference(x
);
533 if (rcu_rbtree_is_nil(rbtree
, x
))
536 while (!rcu_rbtree_is_nil(rbtree
, xl
= rcu_dereference(x
->_left
)))
541 struct rcu_rbtree_node
*rcu_rbtree_max(struct rcu_rbtree
*rbtree
,
542 struct rcu_rbtree_node
*x
)
544 struct rcu_rbtree_node
*xr
;
546 x
= rcu_dereference(x
);
548 if (rcu_rbtree_is_nil(rbtree
, x
))
551 while (!rcu_rbtree_is_nil(rbtree
, xr
= rcu_dereference(x
->_right
)))
558 * Updates should wait for a grace period between update of the
559 * redirect pointer and update of the parent child pointer. This is to make sure
560 * that no reference to the old entry exist.
564 * RCU read lock must be held across the next/prev calls to ensure validity of
567 struct rcu_rbtree_node
*rcu_rbtree_next(struct rcu_rbtree
*rbtree
,
568 struct rcu_rbtree_node
*x
)
570 struct rcu_rbtree_node
*xr
, *y
;
573 x
= rcu_dereference(x
);
575 if (!rcu_rbtree_is_nil(rbtree
, xr
= rcu_dereference(x
->_right
)))
576 return rcu_rbtree_min(rbtree
, xr
);
577 y
= get_parent_and_pos(x
, &x_pos
);
578 while (!rcu_rbtree_is_nil(rbtree
, y
) && x_pos
== IS_RIGHT
) {
580 y
= get_parent_and_pos(y
, &x_pos
);
585 struct rcu_rbtree_node
*rcu_rbtree_prev(struct rcu_rbtree
*rbtree
,
586 struct rcu_rbtree_node
*x
)
588 struct rcu_rbtree_node
*xl
, *y
;
591 x
= rcu_dereference(x
);
593 if (!rcu_rbtree_is_nil(rbtree
, xl
= rcu_dereference(x
->_left
)))
594 return rcu_rbtree_max(rbtree
, xl
);
595 y
= get_parent_and_pos(x
, &x_pos
);
596 while (!rcu_rbtree_is_nil(rbtree
, y
) && x_pos
== IS_LEFT
) {
598 y
= get_parent_and_pos(y
, &x_pos
);
604 * We have to ensure these assumptions are correct for prev/next
607 * with x being a right child, the assumption that:
608 * get_parent(x)->_right == x
609 * or if x is a left child, the assumption that:
610 * get_parent(x)->_left == x
612 * This explains why we have to allocate a vc copy of the node for left_rotate,
613 * right_rotate and transplant operations.
615 * We always ensure that the right/left child and correct parent is set in the
616 * node copies *before* we reparent the children and make the upper-level point
620 /* RCU: copy x and y, atomically point to new versions. GC old. */
621 /* Should be eventually followed by a cmm_smp_wmc() */
623 #ifdef RBTREE_RCU_SUPPORT_ROTATE_LEFT
626 void left_rotate(struct rcu_rbtree
*rbtree
,
627 struct rcu_rbtree_node
*x
)
629 struct rcu_rbtree_node
*y
, *y_left
, *top
, *top_child
;
630 unsigned int top_child_pos
;
635 /* Now operate on new copy, decay old versions */
636 x
= dup_decay_node(rbtree
, x
);
637 y
= dup_decay_node(rbtree
, y
);
638 y_left
= dup_decay_node(rbtree
, y_left
);
640 /* Internal node modifications */
641 set_parent(y
, get_parent(x
), get_pos(x
));
642 set_parent(x
, y
, IS_LEFT
);
643 set_left_dup_decay(rbtree
, y
, x
, &top
, &top_child
, &top_child_pos
);
644 set_right_dup_decay(rbtree
, x
, y_left
, NULL
, NULL
, NULL
);
645 assert(!is_decay(top
));
646 assert(!is_decay(top_child
));
648 if (!rcu_rbtree_is_nil(rbtree
, y_left
))
649 set_parent(y_left
, x
, IS_RIGHT
);
651 cmm_smp_wmb(); /* write into node before publish */
653 /* External references update (visible by readers) */
654 if (rcu_rbtree_is_nil(rbtree
, top
))
655 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
656 else if (top_child_pos
== IS_LEFT
)
657 _CMM_STORE_SHARED(top
->_left
, top_child
);
659 _CMM_STORE_SHARED(top
->_right
, top_child
);
661 /* Point children to new copy (parent only used by updates/next/prev) */
662 set_parent(x
->_left
, get_decay(get_parent(x
->_left
)),
664 set_parent(y
->_right
, get_decay(get_parent(y
->_right
)),
666 if (!rcu_rbtree_is_nil(rbtree
, y_left
)) {
667 set_parent(y_left
->_right
,
668 get_decay(get_parent(y_left
->_right
)),
669 get_pos(y_left
->_right
));
670 set_parent(y_left
->_left
,
671 get_decay(get_parent(y_left
->_left
)),
672 get_pos(y_left
->_left
));
674 set_left_update_decay(rbtree
, y
, x
);
677 assert(y
== rbtree
->root
|| get_parent(y
)->_left
== y
678 || get_parent(y
)->_right
== y
);
679 assert(x
== rbtree
->root
|| get_parent(x
)->_left
== x
680 || get_parent(x
)->_right
== x
);
681 assert(rcu_rbtree_is_nil(rbtree
, x
->_right
) || get_parent(x
->_right
) == x
);
682 assert(rcu_rbtree_is_nil(rbtree
, x
->_left
) || get_parent(x
->_left
) == x
);
683 assert(rcu_rbtree_is_nil(rbtree
, y
->_right
) || get_parent(y
->_right
) == y
);
684 assert(rcu_rbtree_is_nil(rbtree
, y
->_left
) || get_parent(y
->_left
) == y
);
685 assert(!is_decay(rbtree
->root
));
686 assert(!is_decay(x
));
687 assert(!is_decay(y
));
688 assert(!is_decay(x
->_right
));
689 assert(!is_decay(x
->_left
));
690 assert(!is_decay(y
->_right
));
691 assert(!is_decay(y
->_left
));
696 /* non-rcu version */
698 void left_rotate(struct rcu_rbtree
*rbtree
,
699 struct rcu_rbtree_node
*x
)
701 struct rcu_rbtree_node
*y
;
705 x
->_right
= y
->_left
;
706 if (!rcu_rbtree_is_nil(rbtree
, y
->_left
))
707 set_parent(y
->_left
, x
, IS_RIGHT
);
708 set_parent(y
, get_parent(x
), get_pos(x
));
709 if (rcu_rbtree_is_nil(rbtree
, get_parent(x
)))
711 else if (x
== get_parent(x
)->_left
) {
712 get_parent(x
)->_left
= y
;
714 get_parent(x
)->_right
= y
;
717 set_parent(x
, y
, IS_LEFT
);
723 #ifdef RBTREE_RCU_SUPPORT_ROTATE_RIGHT
725 void right_rotate(struct rcu_rbtree
*rbtree
,
726 struct rcu_rbtree_node
*x
)
728 struct rcu_rbtree_node
*y
, *y_right
, *top
, *top_child
;
729 unsigned int top_child_pos
;
734 /* Now operate on new copy, decay old versions */
735 x
= dup_decay_node(rbtree
, x
);
736 y
= dup_decay_node(rbtree
, y
);
737 y_right
= dup_decay_node(rbtree
, y_right
);
739 /* Internal node modifications */
740 set_parent(y
, get_parent(x
), get_pos(x
));
741 set_parent(x
, y
, IS_RIGHT
);
742 set_right_dup_decay(rbtree
, y
, x
, &top
, &top_child
, &top_child_pos
);
743 set_left_dup_decay(rbtree
, x
, y_right
, NULL
, NULL
, NULL
);
744 assert(!is_decay(top
));
745 assert(!is_decay(top_child
));
747 if (!rcu_rbtree_is_nil(rbtree
, y_right
))
748 set_parent(y_right
, x
, IS_LEFT
);
750 cmm_smp_wmb(); /* write into node before publish */
752 /* External references update (visible by readers) */
753 if (rcu_rbtree_is_nil(rbtree
, top
))
754 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
755 else if (top_child_pos
== IS_RIGHT
)
756 _CMM_STORE_SHARED(top
->_right
, top_child
);
758 _CMM_STORE_SHARED(top
->_left
, top_child
);
760 /* Point children to new copy (parent only used by updates/next/prev) */
761 set_parent(x
->_right
, get_decay(get_parent(x
->_right
)),
763 set_parent(y
->_left
, get_decay(get_parent(y
->_left
)),
765 if (!rcu_rbtree_is_nil(rbtree
, y_right
)) {
766 set_parent(y_right
->_left
,
767 get_decay(get_parent(y_right
->_left
)),
768 get_pos(y_right
->_left
));
769 set_parent(y_right
->_right
,
770 get_decay(get_parent(y_right
->_right
)),
771 get_pos(y_right
->_right
));
773 set_right_update_decay(rbtree
, y
, x
);
777 assert(y
== rbtree
->root
|| get_parent(y
)->_right
== y
778 || get_parent(y
)->_left
== y
);
779 assert(x
== rbtree
->root
|| get_parent(x
)->_right
== x
780 || get_parent(x
)->_left
== x
);
781 assert(rcu_rbtree_is_nil(rbtree
, x
->_left
) || get_parent(x
->_left
) == x
);
782 assert(rcu_rbtree_is_nil(rbtree
, x
->_right
) || get_parent(x
->_right
) == x
);
783 assert(rcu_rbtree_is_nil(rbtree
, y
->_left
) || get_parent(y
->_left
) == y
);
784 assert(rcu_rbtree_is_nil(rbtree
, y
->_right
) || get_parent(y
->_right
) == y
);
785 assert(!is_decay(rbtree
->root
));
786 assert(!is_decay(x
));
787 assert(!is_decay(y
));
788 assert(!is_decay(x
->_left
));
789 assert(!is_decay(x
->_right
));
790 assert(!is_decay(y
->_left
));
791 assert(!is_decay(y
->_right
));
796 /* non-rcu version */
798 void right_rotate(struct rcu_rbtree
*rbtree
,
799 struct rcu_rbtree_node
*x
)
801 struct rcu_rbtree_node
*y
;
805 x
->_left
= y
->_right
;
806 if (!rcu_rbtree_is_nil(rbtree
, y
->_right
))
807 set_parent(y
->_right
, x
, IS_LEFT
);
808 set_parent(y
, get_parent(x
), get_pos(x
));
809 if (rcu_rbtree_is_nil(rbtree
, get_parent(x
)))
811 else if (x
== get_parent(x
)->_right
) {
812 get_parent(x
)->_right
= y
;
814 get_parent(x
)->_left
= y
;
817 set_parent(x
, y
, IS_RIGHT
);
823 static void rcu_rbtree_insert_fixup(struct rcu_rbtree
*rbtree
,
824 struct rcu_rbtree_node
*z
)
826 struct rcu_rbtree_node
*y
;
828 dbg_printf("insert fixup %p\n", z
->key
);
829 assert(!is_decay(rbtree
->root
));
831 while (get_parent(z
)->color
== COLOR_RED
) {
832 if (get_parent(z
) == get_parent(get_parent(z
))->_left
) {
833 y
= get_parent(get_parent(z
))->_right
;
834 if (y
->color
== COLOR_RED
) {
835 get_parent(z
)->color
= COLOR_BLACK
;
836 y
->color
= COLOR_BLACK
;
837 get_parent(get_parent(z
))->color
= COLOR_RED
;
838 z
= get_parent(get_parent(z
));
840 if (z
== get_parent(z
)->_right
) {
842 left_rotate(rbtree
, z
);
844 assert(!is_decay(rbtree
->root
));
846 get_parent(z
)->color
= COLOR_BLACK
;
847 get_parent(get_parent(z
))->color
= COLOR_RED
;
848 assert(!is_decay(z
));
849 assert(!is_decay(get_parent(z
)));
850 assert(!is_decay(get_parent(get_parent(z
))));
851 right_rotate(rbtree
, get_parent(get_parent(z
)));
852 assert(!is_decay(z
));
853 assert(!is_decay(rbtree
->root
));
856 y
= get_parent(get_parent(z
))->_left
;
857 if (y
->color
== COLOR_RED
) {
858 get_parent(z
)->color
= COLOR_BLACK
;
859 y
->color
= COLOR_BLACK
;
860 get_parent(get_parent(z
))->color
= COLOR_RED
;
861 z
= get_parent(get_parent(z
));
863 if (z
== get_parent(z
)->_left
) {
865 right_rotate(rbtree
, z
);
867 assert(!is_decay(rbtree
->root
));
869 get_parent(z
)->color
= COLOR_BLACK
;
870 get_parent(get_parent(z
))->color
= COLOR_RED
;
871 left_rotate(rbtree
, get_parent(get_parent(z
)));
872 assert(!is_decay(z
));
873 assert(!is_decay(rbtree
->root
));
877 rbtree
->root
->color
= COLOR_BLACK
;
881 * rcu_rbtree_insert - Insert a node in the RCU rbtree
883 * Returns 0 on success, or < 0 on error.
885 int rcu_rbtree_insert(struct rcu_rbtree
*rbtree
,
886 struct rcu_rbtree_node
*z
)
888 struct rcu_rbtree_node
*x
, *y
, *top
, *top_child
;
889 unsigned int top_child_pos
;
891 dbg_printf("insert %p\n", z
->key
);
892 assert(!is_decay(rbtree
->root
));
894 y
= make_nil(rbtree
);
896 while (!rcu_rbtree_is_nil(rbtree
, x
)) {
898 if (rbtree
->comp(z
->key
, x
->key
) < 0)
904 z
->_left
= make_nil(rbtree
);
905 z
->_right
= make_nil(rbtree
);
906 z
->min_child_key
= z
->key
;
907 z
->max_child_key
= z
->key
;
908 z
->color
= COLOR_RED
;
909 z
->decay_next
= NULL
;
911 if (rcu_rbtree_is_nil(rbtree
, y
))
912 set_parent(z
, y
, IS_RIGHT
); /* pos arbitrary for root node */
913 else if (rbtree
->comp(z
->key
, y
->key
) < 0)
914 set_parent(z
, y
, IS_LEFT
);
916 set_parent(z
, y
, IS_RIGHT
);
919 * Order stores to z (children/parents) before stores that will make it
920 * visible to the rest of the tree.
924 if (rcu_rbtree_is_nil(rbtree
, y
)) {
925 _CMM_STORE_SHARED(rbtree
->root
, z
);
926 } else if (rbtree
->comp(z
->key
, y
->key
) < 0) {
927 set_left_dup_decay(rbtree
, y
, z
, &top
, &top_child
,
929 if (rcu_rbtree_is_nil(rbtree
, top
))
930 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
931 else if (top_child_pos
== IS_LEFT
)
932 _CMM_STORE_SHARED(top
->_left
, top_child
);
934 _CMM_STORE_SHARED(top
->_right
, top_child
);
935 set_left_update_decay(rbtree
, y
, z
);
937 set_right_dup_decay(rbtree
, y
, z
, &top
, &top_child
,
939 if (rcu_rbtree_is_nil(rbtree
, top
))
940 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
941 else if (top_child_pos
== IS_LEFT
)
942 _CMM_STORE_SHARED(top
->_left
, top_child
);
944 _CMM_STORE_SHARED(top
->_right
, top_child
);
945 set_right_update_decay(rbtree
, y
, z
);
947 rcu_rbtree_insert_fixup(rbtree
, z
);
949 * Make sure to commit all _CMM_STORE_SHARED() for non-coherent caches.
958 * Transplant v into u position.
961 #ifdef RBTREE_RCU_SUPPORT_TRANSPLANT
964 void rcu_rbtree_transplant(struct rcu_rbtree
*rbtree
,
965 struct rcu_rbtree_node
*u
,
966 struct rcu_rbtree_node
*v
,
967 unsigned int copy_parents
)
969 struct rcu_rbtree_node
*top
, *top_child
;
970 unsigned int top_child_pos
;
972 dbg_printf("transplant %p\n", v
->key
);
974 if (!rcu_rbtree_is_nil(rbtree
, v
))
975 v
= dup_decay_node(rbtree
, v
);
977 if (rcu_rbtree_is_nil(rbtree
, get_parent(u
))) {
978 /* pos is arbitrary for root node */
979 set_parent(v
, get_parent(u
), IS_RIGHT
);
980 cmm_smp_wmb(); /* write into node before publish */
981 _CMM_STORE_SHARED(rbtree
->root
, v
);
983 set_parent(v
, get_parent(u
), get_pos(u
));
984 cmm_smp_wmb(); /* write into node before publish */
986 if (get_pos(u
) == IS_LEFT
) {
987 _set_left_dup_decay(rbtree
, get_parent(u
), v
,
988 &top
, &top_child
, &top_child_pos
,
991 assert(copy_parents
);
992 set_right_dup_decay(rbtree
, get_parent(u
), v
,
993 &top
, &top_child
, &top_child_pos
);
996 if (rcu_rbtree_is_nil(rbtree
, top
))
997 _CMM_STORE_SHARED(rbtree
->root
, top_child
);
998 else if (top_child_pos
== IS_LEFT
)
999 _CMM_STORE_SHARED(top
->_left
, top_child
);
1001 _CMM_STORE_SHARED(top
->_right
, top_child
);
1003 /* Point children to new copy (parent only used by updates/next/prev) */
1004 if (get_pos(u
) == IS_LEFT
) {
1006 set_left_update_decay(rbtree
, get_parent(u
), v
);
1008 assert(copy_parents
);
1009 set_right_update_decay(rbtree
, get_parent(u
), v
);
1013 /* Point children to new copy (parent only used by updates/next/prev) */
1014 if (!rcu_rbtree_is_nil(rbtree
, v
)) {
1015 set_parent(v
->_right
, get_decay(get_parent(v
->_right
)),
1016 get_pos(v
->_right
));
1017 set_parent(v
->_left
, get_decay(get_parent(v
->_left
)),
1020 assert(!is_decay(rbtree
->root
));
1025 /* Non-RCU version */
1027 void rcu_rbtree_transplant(struct rcu_rbtree
*rbtree
,
1028 struct rcu_rbtree_node
*u
,
1029 struct rcu_rbtree_node
*v
,
1030 unsigned int copy_parents
)
1032 dbg_printf("transplant %p\n", v
->key
);
1035 if (rcu_rbtree_is_nil(rbtree
, get_parent(u
)))
1037 else if (u
== get_parent(u
)->_left
)
1038 get_parent(u
)->_left
= v
;
1040 get_parent(u
)->_right
= v
;
1041 set_parent(v
, get_parent(u
), get_pos(u
));
1042 unlock_test_mutex();
1047 static void rcu_rbtree_remove_fixup(struct rcu_rbtree
*rbtree
,
1048 struct rcu_rbtree_node
*x
)
1050 dbg_printf("remove fixup %p\n", x
->key
);
1052 while (x
!= rbtree
->root
&& x
->color
== COLOR_BLACK
) {
1053 assert(!is_decay(get_parent(x
)));
1054 assert(!is_decay(get_parent(x
)->_left
));
1055 if (x
== get_parent(x
)->_left
) {
1056 struct rcu_rbtree_node
*w
;
1058 w
= get_parent(x
)->_right
;
1060 if (w
->color
== COLOR_RED
) {
1061 w
->color
= COLOR_BLACK
;
1062 get_parent(x
)->color
= COLOR_RED
;
1063 left_rotate(rbtree
, get_parent(x
));
1065 assert(!is_decay(rbtree
->root
));
1066 w
= get_parent(x
)->_right
;
1068 if (w
->_left
->color
== COLOR_BLACK
1069 && w
->_right
->color
== COLOR_BLACK
) {
1070 w
->color
= COLOR_RED
;
1072 assert(!is_decay(rbtree
->root
));
1073 assert(!is_decay(x
));
1075 if (w
->_right
->color
== COLOR_BLACK
) {
1076 w
->_left
->color
= COLOR_BLACK
;
1077 w
->color
= COLOR_RED
;
1078 right_rotate(rbtree
, w
);
1079 assert(!is_decay(rbtree
->root
));
1081 w
= get_parent(x
)->_right
;
1083 w
->color
= get_parent(x
)->color
;
1084 get_parent(x
)->color
= COLOR_BLACK
;
1085 w
->_right
->color
= COLOR_BLACK
;
1086 left_rotate(rbtree
, get_parent(x
));
1087 assert(!is_decay(rbtree
->root
));
1091 struct rcu_rbtree_node
*w
;
1093 w
= get_parent(x
)->_left
;
1095 if (w
->color
== COLOR_RED
) {
1096 w
->color
= COLOR_BLACK
;
1097 get_parent(x
)->color
= COLOR_RED
;
1098 right_rotate(rbtree
, get_parent(x
));
1099 assert(!is_decay(rbtree
->root
));
1101 w
= get_parent(x
)->_left
;
1103 if (w
->_right
->color
== COLOR_BLACK
1104 && w
->_left
->color
== COLOR_BLACK
) {
1105 w
->color
= COLOR_RED
;
1107 assert(!is_decay(rbtree
->root
));
1108 assert(!is_decay(x
));
1110 if (w
->_left
->color
== COLOR_BLACK
) {
1111 w
->_right
->color
= COLOR_BLACK
;
1112 w
->color
= COLOR_RED
;
1113 left_rotate(rbtree
, w
);
1114 assert(!is_decay(rbtree
->root
));
1116 w
= get_parent(x
)->_left
;
1118 w
->color
= get_parent(x
)->color
;
1119 get_parent(x
)->color
= COLOR_BLACK
;
1120 w
->_left
->color
= COLOR_BLACK
;
1121 right_rotate(rbtree
, get_parent(x
));
1122 assert(!is_decay(rbtree
->root
));
1127 x
->color
= COLOR_BLACK
;
1131 * Delete z. All non-copied children left/right positions are unchanged.
1134 void rcu_rbtree_remove_nonil(struct rcu_rbtree
*rbtree
,
1135 struct rcu_rbtree_node
*z
,
1136 struct rcu_rbtree_node
*y
)
1138 struct rcu_rbtree_node
*x
, *top
, *top_child
;
1139 unsigned int top_child_pos
;
1141 dbg_printf("remove nonil %p\n", z
->key
);
1144 assert(!is_decay(z
));
1145 assert(!is_decay(y
));
1146 assert(!is_decay(y
->_right
));
1147 assert(!is_decay(get_parent(y
)));
1149 assert(!is_decay(x
));
1150 if (get_parent(y
) == z
) {
1151 y
= dup_decay_node(rbtree
, y
);
1152 set_parent(x
, y
, get_pos(x
)); /* parent for nil */
1153 /* y is z's right node: set left will just update y */
1154 set_left_dup_decay(rbtree
, y
, z
->_left
,
1155 &top
, &top_child
, &top_child_pos
);
1156 assert(top_child
== y
);
1157 rcu_rbtree_transplant(rbtree
, z
, y
, 1);
1159 struct rcu_rbtree_node
*oy_right
, *z_right
;
1162 * Need to make sure y is always visible by readers.
1164 y
= rcu_rbtree_min_dup_decay(rbtree
, z
->_right
, &z_right
);
1165 assert(!is_decay(y
));
1166 assert(!is_decay(z
));
1167 oy_right
= y
->_right
;
1170 * The max child key of z_right does not change, because
1171 * we're only changing its left children.
1173 y
->_right
= z_right
;
1174 set_parent(y
->_right
, y
, IS_RIGHT
);
1175 if (rcu_rbtree_is_nil(rbtree
, y
->_right
))
1176 y
->max_child_key
= y
->key
;
1178 y
->max_child_key
= y
->_right
->max_child_key
;
1180 assert(!is_decay(z
->_left
));
1181 y
->_left
= z
->_left
;
1182 if (rcu_rbtree_is_nil(rbtree
, y
->_left
))
1183 y
->min_child_key
= y
->key
;
1185 y
->min_child_key
= y
->_left
->min_child_key
;
1187 assert(!is_decay(oy_right
));
1189 * Transplant of oy_right to old y's location will only
1190 * trigger a min/max update of the already copied branch
1191 * (which is not visible yet). We are transplanting
1192 * oy_right as a left child of old y's parent, so the
1193 * min values update propagated upward necessarily stops
1196 rcu_rbtree_transplant(rbtree
, y
, oy_right
, 0);
1197 rcu_rbtree_transplant(rbtree
, z
, y
, 1);
1198 /* Update children */
1199 (void) rcu_rbtree_min_update_decay(rbtree
, y
->_right
);
1202 assert(!is_decay(z
));
1203 assert(!is_decay(z
->_left
));
1204 y
->color
= z
->color
;
1205 set_parent(y
->_left
, y
, IS_LEFT
);
1206 set_parent(y
->_right
, get_decay(get_parent(y
->_right
)), IS_RIGHT
);
1207 assert(!is_decay(y
->_left
));
1208 assert(!is_decay(y
->_right
));
1211 int rcu_rbtree_remove(struct rcu_rbtree
*rbtree
,
1212 struct rcu_rbtree_node
*z
)
1214 struct rcu_rbtree_node
*x
, *y
;
1215 unsigned int y_original_color
;
1217 assert(!is_decay(rbtree
->root
));
1218 dbg_printf("remove %p\n", z
->key
);
1221 assert(!is_decay(z
));
1223 y_original_color
= y
->color
;
1225 if (rcu_rbtree_is_nil(rbtree
, z
->_left
)) {
1226 rcu_rbtree_transplant(rbtree
, z
, z
->_right
, 1);
1227 assert(!is_decay(z
));
1228 x
= get_decay(z
->_right
);
1230 } else if (rcu_rbtree_is_nil(rbtree
, z
->_right
)) {
1231 rcu_rbtree_transplant(rbtree
, z
, z
->_left
, 1);
1232 assert(!is_decay(z
));
1233 x
= get_decay(z
->_left
);
1236 y
= rcu_rbtree_min(rbtree
, z
->_right
);
1237 assert(!is_decay(y
));
1238 y_original_color
= y
->color
;
1240 rcu_rbtree_remove_nonil(rbtree
, z
, y
);
1244 if (y_original_color
== COLOR_BLACK
)
1245 rcu_rbtree_remove_fixup(rbtree
, x
);
1248 * Commit all _CMM_STORE_SHARED().