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.
36 #include <urcu-rbtree.h>
37 #include <urcu-pointer.h>
41 * Deal with memory allocation errors.
42 * Can be ensured by reserving a pool of memory entries before doing the
43 * insertion, which will have to be function of number of
44 * transplantations/rotations required for the operation.
47 /* Sentinel (bottom nodes). Don't care about p, left, right and key values */
48 struct rcu_rbtree_node rcu_rbtree_nil
= {
53 * Iterative rbtree search.
55 struct rcu_rbtree_node
* rcu_rbtree_search(struct rcu_rbtree_node
*x
,
56 void *k
, rcu_rbtree_comp comp
)
58 x
= rcu_dereference(x
);
60 while (x
!= &rcu_rbtree_nil
&& k
!= x
->key
) {
62 x
= rcu_dereference(x
->left
);
64 x
= rcu_dereference(x
->right
);
69 struct rcu_rbtree_node
*rcu_rbtree_min(struct rcu_rbtree_node
*x
,
72 struct rcu_rbtree_node
*xl
;
74 x
= rcu_dereference(x
);
76 while ((xl
= rcu_dereference(x
->left
)) != &rcu_rbtree_nil
)
81 struct rcu_rbtree_node
*rcu_rbtree_max(struct rcu_rbtree_node
*x
,
84 struct rcu_rbtree_node
*xr
;
86 x
= rcu_dereference(x
);
88 while ((xr
= rcu_dereference(x
->right
)) != &rcu_rbtree_nil
)
94 * next and prev need to have mutex held to ensure that parent pointer is
97 struct rcu_rbtree_node
*rcu_rbtree_next(struct rcu_rbtree_node
*x
,
100 struct rcu_rbtree_node
*xr
, *y
;
102 x
= rcu_dereference(x
);
104 if ((xr
= rcu_dereference(x
->right
)) != &rcu_rbtree_nil
)
105 return rcu_rbtree_min(xr
, comp
);
106 y
= rcu_dereference(x
->p
);
107 while (y
!= &rcu_rbtree_nil
&& x
== rcu_dereference(y
->right
)) {
109 y
= rcu_dereference(y
->p
);
114 struct rcu_rbtree_node
*rcu_rbtree_prev(struct rcu_rbtree_node
*x
,
115 rcu_rbtree_comp comp
)
117 struct rcu_rbtree_node
*xl
, *y
;
119 x
= rcu_dereference(x
);
121 if ((xl
= rcu_dereference(x
->left
)) != &rcu_rbtree_nil
)
122 return rcu_rbtree_max(xl
, comp
);
123 y
= rcu_dereference(x
->p
);
124 while (y
!= &rcu_rbtree_nil
&& x
== rcu_dereference(y
->left
)) {
126 y
= rcu_dereference(y
->p
);
132 * We have to ensure these assumptions are correct for prev/next
135 * with x being a right child, the assumption that:
137 * or if x is a left child, the assumption that:
140 * This explains why we have to allocate a vc copy of the node for left_rotate,
141 * right_rotate and transplant operations.
143 * We always ensure that the right/left child and correct parent is set in the
144 * node copies *before* we reparent the children and make the upper-level point
148 /* RCU: copy x and y, atomically point to new versions. GC old. */
149 /* Should be eventually followed by a smp_wmc() */
150 /* Returns the new x. Previous x->right references are changed to yc. */
151 static struct rcu_rbtree_node
*left_rotate(struct rcu_rbtree_node
**root
,
152 struct rcu_rbtree_node
*x
,
153 rcu_rbtree_alloc rballoc
,
154 rcu_rbtree_free rbfree
)
156 struct rcu_rbtree_node
*xc
, *y
, *yc
;
160 if (x
!= &rcu_rbtree_nil
) {
165 if (y
!= &rcu_rbtree_nil
) {
170 /* Modify children and parents in the node copies */
171 if (x
!= &rcu_rbtree_nil
) {
175 xc
= &rcu_rbtree_nil
;
177 if (y
!= &rcu_rbtree_nil
) {
181 yc
= &rcu_rbtree_nil
;
184 * Order stores to node copies (children/parents) before stores that
185 * will make the copies visible to the rest of the tree.
189 /* Make parents point to the copies */
190 if (x
->p
== &rcu_rbtree_nil
)
191 _STORE_SHARED(*root
, yc
);
192 else if (x
== x
->p
->left
)
193 _STORE_SHARED(x
->p
->left
, yc
);
195 _STORE_SHARED(x
->p
->right
, yc
);
197 /* Assign children parents to copies */
198 if (x
!= &rcu_rbtree_nil
) {
199 _STORE_SHARED(xc
->right
->p
, xc
);
200 _STORE_SHARED(xc
->left
->p
, xc
);
201 defer_rcu(rbfree
, x
);
203 if (y
!= &rcu_rbtree_nil
) {
204 _STORE_SHARED(yc
->right
->p
, yc
);
205 defer_rcu(rbfree
, y
);
206 /* yc->left is xc, its parent is already set in node copy */
212 static void left_rotate(struct rcu_rbtree_node
**root
,
213 struct rcu_rbtree_node
*x
,
214 rcu_rbtree_alloc rballoc
)
216 struct rcu_rbtree_node
*y
;
220 if (y
->left
!= &rcu_rbtree_nil
)
223 if (x
->p
== &rcu_rbtree_nil
)
225 else if (x
== x
->p
->left
)
234 /* RCU: copy x and y, atomically point to new versions. GC old. */
235 /* Should be eventually followed by a smp_wmc() */
236 /* Returns the new x. Previous x->left references are changed to yc. */
237 static struct rcu_rbtree_node
*right_rotate(struct rcu_rbtree_node
**root
,
238 struct rcu_rbtree_node
*x
,
239 rcu_rbtree_alloc rballoc
,
240 rcu_rbtree_free rbfree
)
242 struct rcu_rbtree_node
*xc
, *y
, *yc
;
246 if (x
!= &rcu_rbtree_nil
) {
251 if (y
!= &rcu_rbtree_nil
) {
256 /* Modify children and parents in the node copies */
257 if (x
!= &rcu_rbtree_nil
) {
261 xc
= &rcu_rbtree_nil
;
263 if (y
!= &rcu_rbtree_nil
) {
267 yc
= &rcu_rbtree_nil
;
270 * Order stores to node copies (children/parents) before stores that
271 * will make the copies visible to the rest of the tree.
275 /* Make parents point to the copies */
276 if (x
->p
== &rcu_rbtree_nil
)
277 _STORE_SHARED(*root
, yc
);
278 else if (x
== x
->p
->right
)
279 _STORE_SHARED(x
->p
->right
, yc
);
281 _STORE_SHARED(x
->p
->left
, yc
);
283 /* Assign children parents to copies */
284 if (x
!= &rcu_rbtree_nil
) {
285 _STORE_SHARED(xc
->left
->p
, xc
);
286 _STORE_SHARED(xc
->right
->p
, xc
);
287 defer_rcu(rbfree
, x
);
289 if (y
!= &rcu_rbtree_nil
) {
290 _STORE_SHARED(yc
->left
->p
, yc
);
291 defer_rcu(rbfree
, y
);
292 /* yc->right is xc, its parent is already set in node copy */
298 static void right_rotate(struct rcu_rbtree_node
**root
,
299 struct rcu_rbtree_node
*x
,
300 rcu_rbtree_alloc rballoc
)
302 struct rcu_rbtree_node
*y
;
306 if (y
->right
!= &rcu_rbtree_nil
)
309 if (x
->p
== &rcu_rbtree_nil
)
311 else if (x
== x
->p
->right
)
320 static void rcu_rbtree_insert_fixup(struct rcu_rbtree_node
**root
,
321 struct rcu_rbtree_node
*z
,
322 rcu_rbtree_alloc rballoc
,
323 rcu_rbtree_free rbfree
)
325 struct rcu_rbtree_node
*y
;
327 while (z
->p
->color
== COLOR_RED
) {
328 if (z
->p
== z
->p
->p
->left
) {
330 if (y
->color
== COLOR_RED
) {
331 z
->p
->color
= COLOR_BLACK
;
332 y
->color
= COLOR_BLACK
;
333 z
->p
->p
->color
= COLOR_RED
;
336 if (z
== z
->p
->right
) {
338 z
= left_rotate(root
, z
,
341 z
->p
->color
= COLOR_BLACK
;
342 z
->p
->p
->color
= COLOR_RED
;
343 right_rotate(root
, z
->p
->p
, rballoc
, rbfree
);
347 if (y
->color
== COLOR_RED
) {
348 z
->p
->color
= COLOR_BLACK
;
349 y
->color
= COLOR_BLACK
;
350 z
->p
->p
->color
= COLOR_RED
;
353 if (z
== z
->p
->left
) {
355 z
= right_rotate(root
, z
,
358 z
->p
->color
= COLOR_BLACK
;
359 z
->p
->p
->color
= COLOR_RED
;
360 left_rotate(root
, z
->p
->p
, rballoc
, rbfree
);
364 (*root
)->color
= COLOR_BLACK
;
368 * rcu_rbtree_insert - Insert a node in the RCU rbtree
370 * Returns 0 on success, or < 0 on error.
372 int rcu_rbtree_insert(struct rcu_rbtree_node
**root
,
373 struct rcu_rbtree_node
*z
,
374 rcu_rbtree_comp comp
,
375 rcu_rbtree_alloc rballoc
,
376 rcu_rbtree_free rbfree
)
378 struct rcu_rbtree_node
*x
, *y
;
383 while (x
!= &rcu_rbtree_nil
) {
385 if (comp(z
->key
, x
->key
) < 0)
392 z
->left
= &rcu_rbtree_nil
;
393 z
->right
= &rcu_rbtree_nil
;
394 z
->color
= COLOR_RED
;
397 * Order stores to z (children/parents) before stores that will make it
398 * visible to the rest of the tree.
402 if (y
== &rcu_rbtree_nil
)
403 _STORE_SHARED(*root
, z
);
404 else if (comp(z
->key
, y
->key
) < 0)
405 _STORE_SHARED(y
->left
, z
);
407 _STORE_SHARED(y
->right
, z
);
408 rcu_rbtree_insert_fixup(root
, z
, rballoc
, rbfree
);
410 * Make sure to commit all _STORE_SHARED() for non-coherent caches.
418 * Transplant v into u position.
419 * Returns new copy of v.
421 static struct rcu_rbtree_node
*
422 rcu_rbtree_transplant(struct rcu_rbtree_node
**root
,
423 struct rcu_rbtree_node
*u
,
424 struct rcu_rbtree_node
*v
,
425 rcu_rbtree_alloc rballoc
,
426 rcu_rbtree_free rbfree
)
428 struct rcu_rbtree_node
*vc
;
430 if (v
!= &rcu_rbtree_nil
) {
434 /* Change vc parent pointer */
438 * Order stores to node copies (children/parents) before stores
439 * that will make the copies visible to the rest of the tree.
443 vc
= &rcu_rbtree_nil
;
446 /* Assign upper-level pointer to vc, replacing u. */
447 if (u
->p
== &rcu_rbtree_nil
)
448 _STORE_SHARED(*root
, vc
);
449 else if (u
== u
->p
->left
)
450 _STORE_SHARED(u
->p
->left
, vc
);
452 _STORE_SHARED(u
->p
->right
, vc
);
454 if (v
!= &rcu_rbtree_nil
) {
456 * The children pointers in vc are the same as v. We can
457 * therefore reparent v's children to vc safely.
459 _STORE_SHARED(vc
->right
->p
, vc
);
460 _STORE_SHARED(vc
->left
->p
, vc
);
462 defer_rcu(rbfree
, v
);
467 static void rcu_rbtree_remove_fixup(struct rcu_rbtree_node
**root
,
468 struct rcu_rbtree_node
*x
,
469 rcu_rbtree_alloc rballoc
,
470 rcu_rbtree_free rbfree
)
472 while (x
!= *root
&& x
->color
== COLOR_BLACK
) {
473 if (x
== x
->p
->left
) {
474 struct rcu_rbtree_node
*w
;
477 if (w
->color
== COLOR_RED
) {
478 w
->color
== COLOR_BLACK
;
479 x
->p
->color
= COLOR_RED
;
480 left_rotate(root
, x
->p
, rballoc
, rbfree
);
481 /* x is a left node, not copied by rotation */
484 if (w
->left
->color
== COLOR_BLACK
485 && w
->right
->color
== COLOR_BLACK
) {
486 w
->color
= COLOR_RED
;
489 if (w
->right
->color
== COLOR_BLACK
) {
490 w
->left
->color
= COLOR_BLACK
;
491 w
->color
= COLOR_RED
;
492 right_rotate(root
, w
, rballoc
, rbfree
);
495 w
->color
= x
->p
->color
;
496 x
->p
->color
= COLOR_BLACK
;
497 w
->right
->color
= COLOR_BLACK
;
498 left_rotate(root
, x
->p
, rballoc
, rbfree
);
502 struct rcu_rbtree_node
*w
;
505 if (w
->color
== COLOR_RED
) {
506 w
->color
== COLOR_BLACK
;
507 x
->p
->color
= COLOR_RED
;
508 right_rotate(root
, x
->p
, rballoc
, rbfree
);
509 /* x is a right node, not copied by rotation */
512 if (w
->right
->color
== COLOR_BLACK
513 && w
->left
->color
== COLOR_BLACK
) {
514 w
->color
= COLOR_RED
;
517 if (w
->left
->color
== COLOR_BLACK
) {
518 w
->right
->color
= COLOR_BLACK
;
519 w
->color
= COLOR_RED
;
520 left_rotate(root
, w
, rballoc
, rbfree
);
523 w
->color
= x
->p
->color
;
524 x
->p
->color
= COLOR_BLACK
;
525 w
->left
->color
= COLOR_BLACK
;
526 right_rotate(root
, x
->p
, rballoc
, rbfree
);
531 x
->color
= COLOR_BLACK
;
534 /* Returns the new copy of y->right */
535 static struct rcu_rbtree_node
*
536 rcu_rbtree_remove_nonil(struct rcu_rbtree_node
**root
,
537 struct rcu_rbtree_node
*z
,
538 struct rcu_rbtree_node
*y
,
539 rcu_rbtree_comp comp
,
540 rcu_rbtree_alloc rballoc
,
541 rcu_rbtree_free rbfree
)
543 struct rcu_rbtree_node
*x
, *xc
, *yc
;
547 if (x
!= &rcu_rbtree_nil
) {
551 xc
= &rcu_rbtree_nil
;
556 /* Update parent and children pointers within copies */
560 /* Transplant y->right (xc) into y, within copy */
562 /* But also change the right pointer of yc */
563 yc
->right
= z
->right
;
565 /* Transplant y into z, within copy */
569 yc
->color
= z
->color
;
572 * Order stores to node copies (children/parents) before stores that
573 * will make the copies visible to the rest of the tree.
577 /* Update external pointers */
580 /* Transplant y->right into y, external parent links */
582 /* Assign upper-level pointer to xc, replacing y. */
583 if (y
->p
== &rcu_rbtree_nil
)
584 _STORE_SHARED(*root
, xc
);
585 else if (y
== y
->p
->left
)
586 _STORE_SHARED(y
->p
->left
, xc
);
588 _STORE_SHARED(y
->p
->right
, xc
);
591 /* Transplant y into z, update external parent links */
592 if (z
->p
== &rcu_rbtree_nil
)
593 _STORE_SHARED(*root
, yc
);
594 else if (z
== z
->p
->left
)
595 _STORE_SHARED(z
->p
->left
, yc
);
597 _STORE_SHARED(z
->p
->right
, yc
);
599 if (x
!= &rcu_rbtree_nil
) {
600 /* Reparent xc's children to xc. */
601 _STORE_SHARED(xc
->right
->p
, xc
);
602 _STORE_SHARED(xc
->left
->p
, xc
);
603 defer_rcu(rbfree
, x
);
606 /* Reparent yc's children to yc */
607 _STORE_SHARED(yc
->right
->p
, yc
);
608 _STORE_SHARED(yc
->left
->p
, yc
);
609 defer_rcu(rbfree
, y
);
614 int rcu_rbtree_remove(struct rcu_rbtree_node
**root
,
615 struct rcu_rbtree_node
*z
,
616 rcu_rbtree_comp comp
,
617 rcu_rbtree_alloc rballoc
,
618 rcu_rbtree_free rbfree
)
620 struct rcu_rbtree_node
*x
, *y
;
621 unsigned int y_original_color
;
624 y_original_color
= y
->color
;
626 if (z
->left
== &rcu_rbtree_nil
) {
627 x
= rcu_rbtree_transplant(root
, z
, z
->right
, rballoc
, rbfree
);
628 } else if (z
->right
== &rcu_rbtree_nil
) {
629 x
= rcu_rbtree_transplant(root
, z
, z
->left
, rballoc
, rbfree
);
631 y
= rcu_rbtree_min(z
->right
, comp
);
632 y_original_color
= y
->color
;
633 x
= rcu_rbtree_remove_nonil(root
, z
, y
, comp
, rballoc
, rbfree
);
635 if (y_original_color
== COLOR_BLACK
)
636 rcu_rbtree_remove_fixup(root
, x
, rballoc
, rbfree
);
638 * Commit all _STORE_SHARED().