Fix search range comparison
[urcu.git] / urcu-rbtree.c
1 /*
2 * urcu-rbtree.c
3 *
4 * Userspace RCU library - Red-Black Tree
5 *
6 * Copyright (c) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
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.
12 *
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.
17 *
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
21 *
22 * Implementation of RCU-adapted data structures and operations based on the RB
23 * tree algorithms found in chapter 12 of:
24 *
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.
28 */
29
30 #define _BSD_SOURCE
31 #define _LGPL_SOURCE
32
33 #include <stdio.h>
34 #include <pthread.h>
35 #include <assert.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include <urcu/rcurbtree.h>
40 #include <urcu-pointer.h>
41 #include <urcu-call-rcu.h>
42 #include <urcu/compiler.h>
43
44 /*
45 * Explanation of next/prev walk coherency and search coherency when
46 * performed concurrently with updates.
47 *
48 * next/prev walk coherency with respect to concurrent updates:
49 *
50 * There are 3 scenarios for which we need to model and validate this:
51 * rotation, transplant and "teleportation" (the latter being a remote
52 * transplant in a remove non-nil case).
53 *
54 * - rotation left (right is symmetric)
55 * xl and yr point to the same parent nodes before/after left
56 * rotation. yll and ylr also point to the same parent node
57 * before/after left rotation.
58 * As we are copying x, y and yl (the 3 nodes which parent/child
59 * relationship are changed) to "new" version of this node cluster,
60 * all external references to the cluster either point to the old
61 * cluster or the new one. If we take this cluster as a "black box"
62 * from the point of view of next/prev traversal, all we have to
63 * ensure is that the old and the new cluster behave in the exact same
64 * way with respect to traversal order.
65 *
66 * - transplant
67 * In this operation, we transplant a copy of "v" into its parent
68 * location (u), thus replacing it. The children of "v", vl and vr,
69 * still point to v (new version) after the transplant, so it does not
70 * change the behavior when considering the next/prev traversal. "v"
71 * being copied to a new version ensures that the parent pointers of v
72 * are pointing to its new parent (parent of u) before it is published
73 * to readers (by setting the child pointer of u's parent to the new
74 * copy of v).
75 *
76 * - teleportation
77 * This one is probably the most tricky and will require some ascii
78 * art to explain.
79 *
80 * We want to remove z from this tree:
81 *
82 * zp
83 * \
84 * z
85 * / \
86 * zl zr
87 * /
88 * a
89 * / \
90 * b ar
91 * / \
92 * y br
93 * \
94 * yr
95 * / \
96 * yrl yrr
97 *
98 * What we are going to do is to "teleport" y into z's location,
99 * reparenting yr to b. We are taking care to create a new cluster
100 * copy that is isolated from any reader. We will represent the new
101 * members of the cluster with capital letters.
102 *
103 * zp
104 * \
105 * Y
106 * / \
107 * zl ZR
108 * /
109 * A
110 * / \
111 * B ar
112 * / \
113 * YR br
114 * / \
115 * yrl yrr
116 *
117 * In this transient state, we notice that the pointers within the
118 * cluster all point to the new cluster nodes, and they point to the
119 * correct external nodes. However, no external pointer point to the
120 * cluster (yet). The first pointer to point to this cluster will be
121 * "zp->right". It will therefore make the cluster visible for search.
122 *
123 * In this intermediate state, we can walk through the new cluster
124 * when coming from the top (in a next/prev traversal), but can come
125 * back to the old cluster when going back up from the children nodes.
126 * All we have to ensure is that the two clusters, taken as a black
127 * box from a next/prev traversal perspective, yield to the exact same
128 * result.
129 *
130 * Search coherency with concurrent updates:
131 *
132 * Simple "search" (only going down the tree) is also handled by this
133 * cluster scheme. The explanation is a subset of the prev/next
134 * explanation, where we don't have to care about the intermediate
135 * stages where the children point to the old cluster, because we only
136 * ever use the top level pointers to go down into the children nodes,
137 * we never go back up. So by simply making sure that all the cluster
138 * internal nodes pointers are setup correctly before making the
139 * cluster visible to the readers (by setting the parent pointer to
140 * the topmost new node in the cluster), we are sure that readers will
141 * see a coherent view of the cluster at all times.
142 */
143
144 #ifdef DEBUG
145 #define dbg_printf(args...) printf(args)
146 #define dbg_usleep(usecs) usleep(usecs)
147 #else
148 #define dbg_printf(args...)
149 #define dbg_usleep(usecs)
150 #endif
151
152 /*
153 * Undefine this to enable the non-RCU rotate and transplant functions
154 * (for debugging). Note that these versions don't support the tree
155 * max_end updates, so lookups must be performed with
156 * rcu_rbtree_search_begin_key when using this debug facility.
157 */
158 #define RBTREE_RCU_SUPPORT_ROTATE_LEFT
159 #define RBTREE_RCU_SUPPORT_ROTATE_RIGHT
160 #define RBTREE_RCU_SUPPORT_TRANSPLANT
161
162 #ifdef EXTRA_DEBUG
163 static pthread_mutex_t test_mutex = PTHREAD_MUTEX_INITIALIZER;
164 static pthread_mutex_t outer_mutex = PTHREAD_MUTEX_INITIALIZER;
165
166 static
167 void lock_outer_mutex(void)
168 {
169 pthread_mutex_lock(&outer_mutex);
170 }
171
172 static
173 void unlock_outer_mutex(void)
174 {
175 pthread_mutex_unlock(&outer_mutex);
176 }
177
178 static
179 void lock_test_mutex(void)
180 {
181 pthread_mutex_lock(&test_mutex);
182 }
183
184 static
185 void unlock_test_mutex(void)
186 {
187 pthread_mutex_unlock(&test_mutex);
188 }
189 #endif
190
191 static
192 void set_parent(struct rcu_rbtree_node *node,
193 struct rcu_rbtree_node *parent,
194 unsigned int pos)
195 {
196 _CMM_STORE_SHARED(node->parent, ((unsigned long) parent) | pos);
197 }
198
199 static
200 struct rcu_rbtree_node *get_parent(struct rcu_rbtree_node *node)
201 {
202 return (struct rcu_rbtree_node *) (node->parent & ~1UL);
203 }
204
205 static
206 unsigned int get_pos(struct rcu_rbtree_node *node)
207 {
208 return (unsigned int) (node->parent & 1UL);
209 }
210
211 static
212 struct rcu_rbtree_node *get_parent_and_pos(struct rcu_rbtree_node *node,
213 unsigned int *pos)
214 {
215 unsigned long parent_pos = rcu_dereference(node->parent);
216
217 *pos = (unsigned int) (parent_pos & 1UL);
218 return (struct rcu_rbtree_node *) (parent_pos & ~1UL);
219 }
220
221 static
222 void set_decay(struct rcu_rbtree_node *x, struct rcu_rbtree_node *xc)
223 {
224 x->decay_next = xc;
225 }
226
227 static
228 struct rcu_rbtree_node *get_decay(struct rcu_rbtree_node *x)
229 {
230 if (!x)
231 return NULL;
232 while (x->decay_next)
233 x = x->decay_next;
234 return x;
235 }
236
237 static
238 struct rcu_rbtree_node *is_decay(struct rcu_rbtree_node *x)
239 {
240 return x->decay_next;
241 }
242
243 static
244 struct rcu_rbtree_node *dup_decay_node(struct rcu_rbtree *rbtree,
245 struct rcu_rbtree_node *x)
246 {
247 struct rcu_rbtree_node *xc;
248
249 if (rcu_rbtree_is_nil(rbtree, x))
250 return x;
251
252 xc = rbtree->rballoc();
253 memcpy(xc, x, sizeof(struct rcu_rbtree_node));
254 xc->decay_next = NULL;
255 set_decay(x, xc);
256 call_rcu(&x->head, rbtree->rbfree);
257 return xc;
258 }
259
260 /*
261 * Info for range lookups:
262 * Range lookup information is only valid when used when searching for
263 * ranges. It should never be used in next/prev traversal because the
264 * pointers to parents are not in sync with the parent vision of the
265 * children range.
266 */
267 static
268 void set_left(struct rcu_rbtree *rbtree, struct rcu_rbtree_node *node,
269 struct rcu_rbtree_node *left)
270 {
271 node->_left = left;
272 }
273
274 static
275 void set_right(struct rcu_rbtree *rbtree, struct rcu_rbtree_node *node,
276 struct rcu_rbtree_node *right)
277 {
278 node->_right = right;
279 }
280
281 static
282 void *calculate_node_max_end(struct rcu_rbtree *rbtree, struct rcu_rbtree_node *node)
283 {
284 void *max_end;
285
286 max_end = node->end;
287 if (!rcu_rbtree_is_nil(rbtree, node->_right)) {
288 if (rbtree->comp(max_end, node->_right->max_end) < 0)
289 max_end = node->_right->max_end;
290 }
291 if (!rcu_rbtree_is_nil(rbtree, node->_left)) {
292 if (rbtree->comp(max_end, node->_left->max_end) < 0)
293 max_end = node->_left->max_end;
294 }
295 return max_end;
296 }
297
298 /*
299 * TODO
300 * Deal with memory allocation errors.
301 * Can be ensured by reserving a pool of memory entries before doing the
302 * insertion, which will have to be function of number of
303 * transplantations/rotations required for the operation (which is a
304 * multiple of the tree height).
305 */
306
307 #ifdef DEBUG
308 static
309 void show_tree(struct rcu_rbtree *rbtree)
310 {
311 struct rcu_rbtree_node *node;
312
313 node = rcu_rbtree_min(rbtree, rbtree->root);
314 while (!rcu_rbtree_is_nil(rbtree, node)) {
315 assert(!is_decay(node));
316 printf("{ b:%lX e:%lX pb: %lX r:%lX l:%lX %s %s %s} ",
317 (unsigned long) node->begin,
318 (unsigned long) node->end,
319 (unsigned long) get_parent(node)->begin,
320 (unsigned long) node->_right->begin,
321 (unsigned long) node->_left->begin,
322 node->color ? "red" : "black",
323 get_pos(node) ? "right" : "left",
324 rcu_rbtree_is_nil(rbtree, node) ? "nil" : "");
325 node = rcu_rbtree_next(rbtree, node);
326 }
327 printf("\n");
328 }
329
330 #define check_max_end(rbtree, x) \
331 do { \
332 if (rcu_rbtree_is_nil(rbtree, x)) \
333 break; \
334 assert(rbtree->comp(x->max_end, \
335 calculate_node_max_end(rbtree, x)) == 0); \
336 } while (0)
337
338 #else /* DEBUG */
339 static
340 void show_tree(struct rcu_rbtree *rbtree)
341 {
342 }
343
344 static
345 void check_max_end(struct rcu_rbtree *rbtree, struct rcu_rbtree_node *x)
346 {
347 }
348 #endif /* DEBUG */
349
350 static
351 struct rcu_rbtree_node *make_nil(struct rcu_rbtree *rbtree)
352 {
353 return &rbtree->nil_node;
354 }
355
356 /*
357 * Iterative rbtree search.
358 */
359 struct rcu_rbtree_node *rcu_rbtree_search(struct rcu_rbtree *rbtree,
360 struct rcu_rbtree_node *x,
361 void *point)
362 {
363 struct rcu_rbtree_node *xl;
364
365 dbg_printf("searching point 0x%lx\n", (unsigned long) point);
366 x = rcu_dereference(x);
367
368 while (!rcu_rbtree_is_nil(rbtree, x)) {
369 dbg_usleep(10);
370 xl = rcu_dereference(x->_left);
371 dbg_printf("search x %lx x_end %lx x_max_end %lx\n", (unsigned long) x->begin,
372 (unsigned long) x->end, (unsigned long) x->max_end);
373 dbg_printf("search xl %lx xl_end %lx xl_max_end %lx\n", (unsigned long) xl->begin,
374 (unsigned long) xl->end, (unsigned long) xl->max_end);
375 if (!rcu_rbtree_is_nil(rbtree, xl)
376 && (rbtree->comp(xl->max_end, point) > 0)) {
377 dbg_printf("go left\n");
378 x = xl;
379 } else if (rbtree->comp(x->begin, point) <= 0
380 && rbtree->comp(point, x->end) < 0) {
381 dbg_printf("got it!\n");
382 break;
383 } else if (rbtree->comp(point, x->begin) > 0) {
384 dbg_printf("go right\n");
385 x = rcu_dereference(x->_right);
386 } else {
387 dbg_printf("not found!\n");
388 x = make_nil(rbtree);
389 }
390 }
391 if (rcu_rbtree_is_nil(rbtree, x))
392 dbg_printf("Reached bottom of tree.\n");
393
394 return x;
395 }
396
397 struct rcu_rbtree_node *rcu_rbtree_search_range(struct rcu_rbtree *rbtree,
398 struct rcu_rbtree_node *x,
399 void *begin, void *end)
400 {
401 struct rcu_rbtree_node *node;
402
403 node = rcu_rbtree_search(rbtree, x, begin);
404 if (rcu_rbtree_is_nil(rbtree, node))
405 return node;
406 if (rbtree->comp(node->end, end) < 0)
407 return NULL; /* High is outside lookup range */
408 return node;
409 }
410
411 /*
412 * Search by exact range start value.
413 */
414 struct rcu_rbtree_node *rcu_rbtree_search_begin_key(struct rcu_rbtree *rbtree,
415 struct rcu_rbtree_node *x,
416 void *k)
417 {
418 x = rcu_dereference(x);
419 int comp;
420
421 while (!rcu_rbtree_is_nil(rbtree, x) && (comp = rbtree->comp(k, x->begin)) != 0) {
422 dbg_usleep(10);
423 if (comp < 0)
424 x = rcu_dereference(x->_left);
425 else
426 x = rcu_dereference(x->_right);
427 }
428 return x;
429 }
430
431 static
432 struct rcu_rbtree_node *rcu_rbtree_min_dup_decay(struct rcu_rbtree *rbtree,
433 struct rcu_rbtree_node *x,
434 struct rcu_rbtree_node **zr)
435 {
436 struct rcu_rbtree_node *xl;
437
438 x = rcu_dereference(x);
439
440 if (rcu_rbtree_is_nil(rbtree, x)) {
441 *zr = x;
442 return x;
443 } else
444 *zr = x = dup_decay_node(rbtree, x);
445
446 while (!rcu_rbtree_is_nil(rbtree, xl = rcu_dereference(x->_left))) {
447 x = dup_decay_node(rbtree, xl);
448 set_parent(x, get_decay(get_parent(x)), get_pos(x));
449 get_parent(x)->_left = get_decay(get_parent(x)->_left);
450 }
451 return x;
452 }
453
454 static
455 struct rcu_rbtree_node *rcu_rbtree_min_update_decay(struct rcu_rbtree *rbtree,
456 struct rcu_rbtree_node *x)
457 {
458 struct rcu_rbtree_node *xl;
459
460 x = rcu_dereference(x);
461
462 if (rcu_rbtree_is_nil(rbtree, x))
463 return x;
464 else {
465 set_parent(x->_right, get_decay(get_parent(x->_right)),
466 get_pos(x->_right));
467 set_parent(x->_left, get_decay(get_parent(x->_left)),
468 get_pos(x->_left));
469 }
470
471 while (!rcu_rbtree_is_nil(rbtree, xl = rcu_dereference(x->_left))) {
472 x = xl;
473 set_parent(x->_right, get_decay(get_parent(x->_right)),
474 get_pos(x->_right));
475 set_parent(x->_left, get_decay(get_parent(x->_left)),
476 get_pos(x->_left));
477 }
478 return x;
479 }
480
481 struct rcu_rbtree_node *rcu_rbtree_min(struct rcu_rbtree *rbtree,
482 struct rcu_rbtree_node *x)
483 {
484 struct rcu_rbtree_node *xl;
485
486 x = rcu_dereference(x);
487
488 if (rcu_rbtree_is_nil(rbtree, x))
489 return x;
490
491 while (!rcu_rbtree_is_nil(rbtree, xl = rcu_dereference(x->_left)))
492 x = xl;
493 return x;
494 }
495
496 struct rcu_rbtree_node *rcu_rbtree_max(struct rcu_rbtree *rbtree,
497 struct rcu_rbtree_node *x)
498 {
499 struct rcu_rbtree_node *xr;
500
501 x = rcu_dereference(x);
502
503 if (rcu_rbtree_is_nil(rbtree, x))
504 return x;
505
506 while (!rcu_rbtree_is_nil(rbtree, xr = rcu_dereference(x->_right)))
507 x = xr;
508 return x;
509 }
510
511 /*
512 * RCU read lock must be held across the next/prev calls to ensure validity of
513 * the returned node.
514 */
515 struct rcu_rbtree_node *rcu_rbtree_next(struct rcu_rbtree *rbtree,
516 struct rcu_rbtree_node *x)
517 {
518 struct rcu_rbtree_node *xr, *y;
519 unsigned int x_pos;
520
521 x = rcu_dereference(x);
522
523 if (!rcu_rbtree_is_nil(rbtree, xr = rcu_dereference(x->_right)))
524 return rcu_rbtree_min(rbtree, xr);
525 y = get_parent_and_pos(x, &x_pos);
526 while (!rcu_rbtree_is_nil(rbtree, y) && x_pos == IS_RIGHT) {
527 x = y;
528 y = get_parent_and_pos(y, &x_pos);
529 }
530 return y;
531 }
532
533 struct rcu_rbtree_node *rcu_rbtree_prev(struct rcu_rbtree *rbtree,
534 struct rcu_rbtree_node *x)
535 {
536 struct rcu_rbtree_node *xl, *y;
537 unsigned int x_pos;
538
539 x = rcu_dereference(x);
540
541 if (!rcu_rbtree_is_nil(rbtree, xl = rcu_dereference(x->_left)))
542 return rcu_rbtree_max(rbtree, xl);
543 y = get_parent_and_pos(x, &x_pos);
544 while (!rcu_rbtree_is_nil(rbtree, y) && x_pos == IS_LEFT) {
545 x = y;
546 y = get_parent_and_pos(y, &x_pos);
547 }
548 return y;
549 }
550
551 /*
552 * "node" needs to be non-visible by readers.
553 */
554 static
555 void populate_node_end(struct rcu_rbtree *rbtree, struct rcu_rbtree_node *node,
556 unsigned int copy_parents, struct rcu_rbtree_node *stop)
557 {
558 struct rcu_rbtree_node *prev = NULL, *orig_node = node, *top;
559
560 do {
561 void *max_end;
562
563 assert(node);
564 assert(!rcu_rbtree_is_nil(rbtree, node));
565
566 if (prev && copy_parents) {
567 node = dup_decay_node(rbtree, node);
568 if (get_pos(prev) == IS_RIGHT)
569 node->_right = prev;
570 else
571 node->_left = prev;
572 set_parent(prev, node, get_pos(prev));
573 }
574
575 max_end = calculate_node_max_end(rbtree, node);
576 /*
577 * Compare the node max_end keys to make sure we replace
578 * references to a key belonging to a node we remove
579 * from the tree. Otherwise we would still be using this
580 * pointer as an invalid reference after garbage
581 * collection of the node and of its associated
582 * begin/end pointers.
583 */
584 if (max_end != node->max_end) {
585 node->max_end = max_end;
586 } else {
587 top = get_parent(node);
588 cmm_smp_wmb(); /* write into node before publish */
589 /* make new branch visible to readers */
590 if (rcu_rbtree_is_nil(rbtree, top))
591 _CMM_STORE_SHARED(rbtree->root, node);
592 if (get_pos(node) == IS_LEFT)
593 _CMM_STORE_SHARED(top->_left, node);
594 else
595 _CMM_STORE_SHARED(top->_right, node);
596 goto end;
597 }
598
599 /* Check for propagation stop */
600 if (node == stop)
601 return;
602
603 prev = node;
604 node = get_parent(node);
605 } while (!rcu_rbtree_is_nil(rbtree, node));
606
607 top = node; /* nil */
608 cmm_smp_wmb(); /* write into node before publish */
609 /* make new branch visible to readers */
610 _CMM_STORE_SHARED(rbtree->root, prev);
611
612 end:
613 if (!copy_parents)
614 return;
615 /* update children */
616 node = orig_node;
617 do {
618 assert(!rcu_rbtree_is_nil(rbtree, node));
619 set_parent(node->_left, get_decay(get_parent(node->_left)), IS_LEFT);
620 set_parent(node->_right, get_decay(get_parent(node->_right)), IS_RIGHT);
621 } while ((node = get_parent(node)) != top);
622 }
623
624 /*
625 * We have to ensure these assumptions are correct for prev/next
626 * traversal:
627 *
628 * with x being a right child, the assumption that:
629 * get_parent(x)->_right == x
630 * or if x is a left child, the assumption that:
631 * get_parent(x)->_left == x
632 *
633 * This explains why we have to allocate a vc copy of the node for left_rotate,
634 * right_rotate and transplant operations.
635 *
636 * We always ensure that the right/left child and correct parent is set in the
637 * node copies *before* we reparent the children and make the upper-level point
638 * to the copy.
639 */
640
641 /* RCU: copy x and y, atomically point to new versions. GC old. */
642 /* Should be eventually followed by a cmm_smp_wmc() */
643
644 #ifdef RBTREE_RCU_SUPPORT_ROTATE_LEFT
645
646 static
647 void left_rotate(struct rcu_rbtree *rbtree,
648 struct rcu_rbtree_node *x)
649 {
650 struct rcu_rbtree_node *y, *y_left;
651
652 dbg_printf("left rotate %lx\n", (unsigned long) x->begin);
653
654 y = x->_right;
655 y_left = y->_left;
656
657 /* Now operate on new copy, decay old versions */
658 x = dup_decay_node(rbtree, x);
659 y = dup_decay_node(rbtree, y);
660 y_left = dup_decay_node(rbtree, y_left);
661
662 check_max_end(rbtree, get_parent(x));
663 check_max_end(rbtree, x);
664 check_max_end(rbtree, y);
665
666 /* Internal node modifications */
667 set_parent(y, get_parent(x), get_pos(x));
668 set_parent(x, y, IS_LEFT);
669 set_left(rbtree, y, x);
670 set_right(rbtree, x, y_left);
671
672 if (!rcu_rbtree_is_nil(rbtree, y_left))
673 set_parent(y_left, x, IS_RIGHT);
674
675 /*
676 * We only changed the relative position of x and y wrt their
677 * children, and reparented y (but are keeping the same nodes in
678 * place, so its parent does not need to have end value
679 * recalculated).
680 */
681 x->max_end = calculate_node_max_end(rbtree, x);
682 y->max_end = calculate_node_max_end(rbtree, y);
683
684 cmm_smp_wmb(); /* write into node before publish */
685
686 /* External references update (visible by readers) */
687 if (rcu_rbtree_is_nil(rbtree, get_parent(y)))
688 _CMM_STORE_SHARED(rbtree->root, y);
689 else if (get_pos(y) == IS_LEFT)
690 _CMM_STORE_SHARED(get_parent(y)->_left, y);
691 else
692 _CMM_STORE_SHARED(get_parent(y)->_right, y);
693
694 /* Point children to new copy (parent only used by updates/next/prev) */
695 set_parent(x->_left, get_decay(get_parent(x->_left)),
696 get_pos(x->_left));
697 set_parent(y->_right, get_decay(get_parent(y->_right)),
698 get_pos(y->_right));
699 if (!rcu_rbtree_is_nil(rbtree, y_left)) {
700 set_parent(y_left->_right,
701 get_decay(get_parent(y_left->_right)),
702 get_pos(y_left->_right));
703 set_parent(y_left->_left,
704 get_decay(get_parent(y_left->_left)),
705 get_pos(y_left->_left));
706 }
707
708 /* Sanity checks */
709 assert(y == rbtree->root || get_parent(y)->_left == y
710 || get_parent(y)->_right == y);
711 assert(x == rbtree->root || get_parent(x)->_left == x
712 || get_parent(x)->_right == x);
713 assert(rcu_rbtree_is_nil(rbtree, x->_right) || get_parent(x->_right) == x);
714 assert(rcu_rbtree_is_nil(rbtree, x->_left) || get_parent(x->_left) == x);
715 assert(rcu_rbtree_is_nil(rbtree, y->_right) || get_parent(y->_right) == y);
716 assert(rcu_rbtree_is_nil(rbtree, y->_left) || get_parent(y->_left) == y);
717 assert(!is_decay(rbtree->root));
718 assert(!is_decay(x));
719 assert(!is_decay(y));
720 assert(!is_decay(x->_right));
721 assert(!is_decay(x->_left));
722 assert(!is_decay(y->_right));
723 assert(!is_decay(y->_left));
724 check_max_end(rbtree, get_parent(y));
725 check_max_end(rbtree, x);
726 check_max_end(rbtree, y);
727 }
728
729 #else
730
731 /* non-rcu version */
732 static
733 void left_rotate(struct rcu_rbtree *rbtree,
734 struct rcu_rbtree_node *x)
735 {
736 struct rcu_rbtree_node *y;
737
738 lock_test_mutex();
739 y = x->_right;
740 x->_right = y->_left;
741 if (!rcu_rbtree_is_nil(rbtree, y->_left))
742 set_parent(y->_left, x, IS_RIGHT);
743 set_parent(y, get_parent(x), get_pos(x));
744 if (rcu_rbtree_is_nil(rbtree, get_parent(x)))
745 rbtree->root = y;
746 else if (x == get_parent(x)->_left) {
747 get_parent(x)->_left = y;
748 } else {
749 get_parent(x)->_right = y;
750 }
751 y->_left = x;
752 set_parent(x, y, IS_LEFT);
753 unlock_test_mutex();
754 }
755
756 #endif
757
758 #ifdef RBTREE_RCU_SUPPORT_ROTATE_RIGHT
759 static
760 void right_rotate(struct rcu_rbtree *rbtree,
761 struct rcu_rbtree_node *x)
762 {
763 struct rcu_rbtree_node *y, *y_right;
764
765 dbg_printf("right rotate %lx\n", (unsigned long) x->begin);
766
767 y = x->_left;
768 y_right = y->_right;
769
770 /* Now operate on new copy, decay old versions */
771 x = dup_decay_node(rbtree, x);
772 y = dup_decay_node(rbtree, y);
773 y_right = dup_decay_node(rbtree, y_right);
774
775 check_max_end(rbtree, get_parent(x));
776 check_max_end(rbtree, x);
777 check_max_end(rbtree, y);
778
779 /* Internal node modifications */
780 set_parent(y, get_parent(x), get_pos(x));
781 set_parent(x, y, IS_RIGHT);
782 set_right(rbtree, y, x);
783 set_left(rbtree, x, y_right);
784
785 if (!rcu_rbtree_is_nil(rbtree, y_right))
786 set_parent(y_right, x, IS_LEFT);
787
788 /*
789 * We only changed the relative position of x and y wrt their
790 * children, and reparented y (but are keeping the same nodes in
791 * place, so its parent does not need to have end value
792 * recalculated).
793 */
794 x->max_end = calculate_node_max_end(rbtree, x);
795 y->max_end = calculate_node_max_end(rbtree, y);
796
797 cmm_smp_wmb(); /* write into node before publish */
798
799 /* External references update (visible by readers) */
800 if (rcu_rbtree_is_nil(rbtree, get_parent(y)))
801 _CMM_STORE_SHARED(rbtree->root, y);
802 else if (get_pos(y) == IS_RIGHT)
803 _CMM_STORE_SHARED(get_parent(y)->_right, y);
804 else
805 _CMM_STORE_SHARED(get_parent(y)->_left, y);
806
807 /* Point children to new copy (parent only used by updates/next/prev) */
808 set_parent(x->_right, get_decay(get_parent(x->_right)),
809 get_pos(x->_right));
810 set_parent(y->_left, get_decay(get_parent(y->_left)),
811 get_pos(y->_left));
812 if (!rcu_rbtree_is_nil(rbtree, y_right)) {
813 set_parent(y_right->_left,
814 get_decay(get_parent(y_right->_left)),
815 get_pos(y_right->_left));
816 set_parent(y_right->_right,
817 get_decay(get_parent(y_right->_right)),
818 get_pos(y_right->_right));
819 }
820
821 /* Sanity checks */
822 assert(y == rbtree->root || get_parent(y)->_right == y
823 || get_parent(y)->_left == y);
824 assert(x == rbtree->root || get_parent(x)->_right == x
825 || get_parent(x)->_left == x);
826 assert(rcu_rbtree_is_nil(rbtree, x->_left) || get_parent(x->_left) == x);
827 assert(rcu_rbtree_is_nil(rbtree, x->_right) || get_parent(x->_right) == x);
828 assert(rcu_rbtree_is_nil(rbtree, y->_left) || get_parent(y->_left) == y);
829 assert(rcu_rbtree_is_nil(rbtree, y->_right) || get_parent(y->_right) == y);
830 assert(!is_decay(rbtree->root));
831 assert(!is_decay(x));
832 assert(!is_decay(y));
833 assert(!is_decay(x->_left));
834 assert(!is_decay(x->_right));
835 assert(!is_decay(y->_left));
836 assert(!is_decay(y->_right));
837 check_max_end(rbtree, x);
838 check_max_end(rbtree, y);
839 check_max_end(rbtree, get_parent(y));
840 }
841
842 #else
843
844 /* non-rcu version */
845 static
846 void right_rotate(struct rcu_rbtree *rbtree,
847 struct rcu_rbtree_node *x)
848 {
849 struct rcu_rbtree_node *y;
850
851 lock_test_mutex();
852 y = x->_left;
853 x->_left = y->_right;
854 if (!rcu_rbtree_is_nil(rbtree, y->_right))
855 set_parent(y->_right, x, IS_LEFT);
856 set_parent(y, get_parent(x), get_pos(x));
857 if (rcu_rbtree_is_nil(rbtree, get_parent(x)))
858 rbtree->root = y;
859 else if (x == get_parent(x)->_right) {
860 get_parent(x)->_right = y;
861 } else {
862 get_parent(x)->_left = y;
863 }
864 y->_right = x;
865 set_parent(x, y, IS_RIGHT);
866 unlock_test_mutex();
867 }
868
869 #endif
870
871 static void rcu_rbtree_insert_fixup(struct rcu_rbtree *rbtree,
872 struct rcu_rbtree_node *z)
873 {
874 struct rcu_rbtree_node *y;
875
876 dbg_printf("insert fixup %p\n", z->begin);
877 assert(!is_decay(rbtree->root));
878
879 while (get_parent(z)->color == COLOR_RED) {
880 if (get_parent(z) == get_parent(get_parent(z))->_left) {
881 y = get_parent(get_parent(z))->_right;
882 if (y->color == COLOR_RED) {
883 get_parent(z)->color = COLOR_BLACK;
884 y->color = COLOR_BLACK;
885 get_parent(get_parent(z))->color = COLOR_RED;
886 z = get_parent(get_parent(z));
887 } else {
888 if (z == get_parent(z)->_right) {
889 z = get_parent(z);
890 left_rotate(rbtree, z);
891 z = get_decay(z);
892 assert(!is_decay(rbtree->root));
893 }
894 get_parent(z)->color = COLOR_BLACK;
895 get_parent(get_parent(z))->color = COLOR_RED;
896 assert(!is_decay(z));
897 assert(!is_decay(get_parent(z)));
898 assert(!is_decay(get_parent(get_parent(z))));
899 right_rotate(rbtree, get_parent(get_parent(z)));
900 assert(!is_decay(z));
901 assert(!is_decay(rbtree->root));
902 }
903 } else {
904 y = get_parent(get_parent(z))->_left;
905 if (y->color == COLOR_RED) {
906 get_parent(z)->color = COLOR_BLACK;
907 y->color = COLOR_BLACK;
908 get_parent(get_parent(z))->color = COLOR_RED;
909 z = get_parent(get_parent(z));
910 } else {
911 if (z == get_parent(z)->_left) {
912 z = get_parent(z);
913 right_rotate(rbtree, z);
914 z = get_decay(z);
915 assert(!is_decay(rbtree->root));
916 }
917 get_parent(z)->color = COLOR_BLACK;
918 get_parent(get_parent(z))->color = COLOR_RED;
919 left_rotate(rbtree, get_parent(get_parent(z)));
920 assert(!is_decay(z));
921 assert(!is_decay(rbtree->root));
922 }
923 }
924 }
925 rbtree->root->color = COLOR_BLACK;
926 }
927
928 /*
929 * rcu_rbtree_insert - Insert a node in the RCU rbtree
930 *
931 * Returns 0 on success, or < 0 on error.
932 */
933 int rcu_rbtree_insert(struct rcu_rbtree *rbtree,
934 struct rcu_rbtree_node *z)
935 {
936 struct rcu_rbtree_node *x, *y;
937
938 dbg_printf("insert %p\n", z->begin);
939 assert(!is_decay(rbtree->root));
940
941 y = make_nil(rbtree);
942 x = rbtree->root;
943 while (!rcu_rbtree_is_nil(rbtree, x)) {
944 y = x;
945 if (rbtree->comp(z->begin, x->begin) < 0)
946 x = x->_left;
947 else
948 x = x->_right;
949 }
950
951 z->_left = make_nil(rbtree);
952 z->_right = make_nil(rbtree);
953 z->color = COLOR_RED;
954 z->decay_next = NULL;
955 z->max_end = z->end;
956
957 if (rcu_rbtree_is_nil(rbtree, y)) {
958 set_parent(z, y, IS_RIGHT); /* pos arbitrary for root node */
959 /*
960 * Order stores to z (children/parents) before stores
961 * that will make it visible to the rest of the tree.
962 */
963 cmm_smp_wmb();
964 _CMM_STORE_SHARED(rbtree->root, z);
965 } else if (rbtree->comp(z->begin, y->begin) < 0) {
966 y = dup_decay_node(rbtree, y);
967 set_parent(z, y, IS_LEFT);
968 if (get_pos(z) == IS_LEFT)
969 _CMM_STORE_SHARED(y->_left, z);
970 else
971 _CMM_STORE_SHARED(y->_right, z);
972 populate_node_end(rbtree, y, 1, NULL);
973 } else {
974 y = dup_decay_node(rbtree, y);
975 set_parent(z, y, IS_RIGHT);
976 if (get_pos(z) == IS_LEFT)
977 _CMM_STORE_SHARED(y->_left, z);
978 else
979 _CMM_STORE_SHARED(y->_right, z);
980 populate_node_end(rbtree, y, 1, NULL);
981 }
982 rcu_rbtree_insert_fixup(rbtree, z);
983 /*
984 * Make sure to commit all _CMM_STORE_SHARED() for non-coherent caches.
985 */
986 cmm_smp_wmc();
987 show_tree(rbtree);
988 check_max_end(rbtree, z);
989 check_max_end(rbtree, y);
990
991 return 0;
992 }
993
994 /*
995 * Transplant v into u position.
996 */
997
998 #ifdef RBTREE_RCU_SUPPORT_TRANSPLANT
999
1000 static
1001 void rcu_rbtree_transplant(struct rcu_rbtree *rbtree,
1002 struct rcu_rbtree_node *u,
1003 struct rcu_rbtree_node *v,
1004 unsigned int copy_parents,
1005 struct rcu_rbtree_node *stop)
1006 {
1007 dbg_printf("transplant %p\n", v->begin);
1008
1009 if (!rcu_rbtree_is_nil(rbtree, v))
1010 v = dup_decay_node(rbtree, v);
1011
1012 if (rcu_rbtree_is_nil(rbtree, get_parent(u))) {
1013 /* pos is arbitrary for root node */
1014 set_parent(v, get_parent(u), IS_RIGHT);
1015 cmm_smp_wmb(); /* write into node before publish */
1016 _CMM_STORE_SHARED(rbtree->root, v);
1017 } else {
1018 struct rcu_rbtree_node *vp;
1019
1020 vp = get_parent(u);
1021 if (copy_parents)
1022 vp = dup_decay_node(rbtree, vp);
1023 set_parent(v, vp, get_pos(u));
1024 if (get_pos(v) == IS_LEFT)
1025 _CMM_STORE_SHARED(vp->_left, v);
1026 else
1027 _CMM_STORE_SHARED(vp->_right, v);
1028 populate_node_end(rbtree, vp, copy_parents, stop);
1029 check_max_end(rbtree, vp);
1030 }
1031
1032 /* Point children to new copy (parent only used by updates/next/prev) */
1033 if (!rcu_rbtree_is_nil(rbtree, v)) {
1034 set_parent(v->_right, get_decay(get_parent(v->_right)),
1035 get_pos(v->_right));
1036 set_parent(v->_left, get_decay(get_parent(v->_left)),
1037 get_pos(v->_left));
1038 }
1039 assert(!is_decay(rbtree->root));
1040 check_max_end(rbtree, v);
1041 }
1042
1043 #else
1044
1045 /* Non-RCU version */
1046 static
1047 void rcu_rbtree_transplant(struct rcu_rbtree *rbtree,
1048 struct rcu_rbtree_node *u,
1049 struct rcu_rbtree_node *v,
1050 unsigned int copy_parents,
1051 struct rcu_rbtree_node *stop)
1052 {
1053 dbg_printf("transplant %p\n", v->begin);
1054
1055 lock_test_mutex();
1056 if (rcu_rbtree_is_nil(rbtree, get_parent(u)))
1057 rbtree->root = v;
1058 else if (u == get_parent(u)->_left)
1059 get_parent(u)->_left = v;
1060 else
1061 get_parent(u)->_right = v;
1062 set_parent(v, get_parent(u), get_pos(u));
1063 unlock_test_mutex();
1064 }
1065
1066 #endif
1067
1068 static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
1069 struct rcu_rbtree_node *x)
1070 {
1071 dbg_printf("remove fixup %p\n", x->begin);
1072
1073 while (x != rbtree->root && x->color == COLOR_BLACK) {
1074 assert(!is_decay(get_parent(x)));
1075 assert(!is_decay(get_parent(x)->_left));
1076 if (x == get_parent(x)->_left) {
1077 struct rcu_rbtree_node *w;
1078
1079 w = get_parent(x)->_right;
1080
1081 if (w->color == COLOR_RED) {
1082 w->color = COLOR_BLACK;
1083 get_parent(x)->color = COLOR_RED;
1084 left_rotate(rbtree, get_parent(x));
1085 x = get_decay(x);
1086 assert(!is_decay(rbtree->root));
1087 w = get_parent(x)->_right;
1088 }
1089 if (w->_left->color == COLOR_BLACK
1090 && w->_right->color == COLOR_BLACK) {
1091 w->color = COLOR_RED;
1092 x = get_parent(x);
1093 assert(!is_decay(rbtree->root));
1094 assert(!is_decay(x));
1095 } else {
1096 if (w->_right->color == COLOR_BLACK) {
1097 w->_left->color = COLOR_BLACK;
1098 w->color = COLOR_RED;
1099 right_rotate(rbtree, w);
1100 assert(!is_decay(rbtree->root));
1101 x = get_decay(x);
1102 w = get_parent(x)->_right;
1103 }
1104 w->color = get_parent(x)->color;
1105 get_parent(x)->color = COLOR_BLACK;
1106 w->_right->color = COLOR_BLACK;
1107 left_rotate(rbtree, get_parent(x));
1108 assert(!is_decay(rbtree->root));
1109 x = rbtree->root;
1110 }
1111 } else {
1112 struct rcu_rbtree_node *w;
1113
1114 w = get_parent(x)->_left;
1115
1116 if (w->color == COLOR_RED) {
1117 w->color = COLOR_BLACK;
1118 get_parent(x)->color = COLOR_RED;
1119 right_rotate(rbtree, get_parent(x));
1120 assert(!is_decay(rbtree->root));
1121 x = get_decay(x);
1122 w = get_parent(x)->_left;
1123 }
1124 if (w->_right->color == COLOR_BLACK
1125 && w->_left->color == COLOR_BLACK) {
1126 w->color = COLOR_RED;
1127 x = get_parent(x);
1128 assert(!is_decay(rbtree->root));
1129 assert(!is_decay(x));
1130 } else {
1131 if (w->_left->color == COLOR_BLACK) {
1132 w->_right->color = COLOR_BLACK;
1133 w->color = COLOR_RED;
1134 left_rotate(rbtree, w);
1135 assert(!is_decay(rbtree->root));
1136 x = get_decay(x);
1137 w = get_parent(x)->_left;
1138 }
1139 w->color = get_parent(x)->color;
1140 get_parent(x)->color = COLOR_BLACK;
1141 w->_left->color = COLOR_BLACK;
1142 right_rotate(rbtree, get_parent(x));
1143 assert(!is_decay(rbtree->root));
1144 x = rbtree->root;
1145 }
1146 }
1147 }
1148 x->color = COLOR_BLACK;
1149 }
1150
1151 /*
1152 * Delete z. All non-copied children left/right positions are unchanged.
1153 */
1154 static
1155 void rcu_rbtree_remove_nonil(struct rcu_rbtree *rbtree,
1156 struct rcu_rbtree_node *z,
1157 struct rcu_rbtree_node *y)
1158 {
1159 struct rcu_rbtree_node *x;
1160
1161 dbg_printf("remove nonil %p\n", z->begin);
1162 show_tree(rbtree);
1163
1164 assert(!is_decay(z));
1165 assert(!is_decay(y));
1166 assert(!is_decay(y->_right));
1167 assert(!is_decay(get_parent(y)));
1168 x = y->_right;
1169 assert(!is_decay(x));
1170 if (get_parent(y) == z) {
1171 y = dup_decay_node(rbtree, y);
1172 set_parent(x, y, get_pos(x)); /* parent for nil */
1173 /* y is z's right node */
1174 set_left(rbtree, y, z->_left);
1175 y->max_end = calculate_node_max_end(rbtree, y);
1176 rcu_rbtree_transplant(rbtree, z, y, 1, NULL);
1177 } else {
1178 struct rcu_rbtree_node *oy_right, *z_right;
1179
1180 /*
1181 * Need to make sure y is always visible by readers.
1182 */
1183 y = rcu_rbtree_min_dup_decay(rbtree, z->_right, &z_right);
1184 assert(!is_decay(y));
1185 assert(!is_decay(z));
1186 oy_right = y->_right;
1187
1188 /*
1189 * The max child begin of z_right does not change, because
1190 * we're only changing its left children.
1191 */
1192 y->_right = z_right;
1193 set_parent(y->_right, y, IS_RIGHT);
1194 assert(!is_decay(z->_left));
1195 y->_left = z->_left;
1196 assert(!is_decay(oy_right));
1197 /*
1198 * Transplant of oy_right to old y's location will only
1199 * trigger a "end" value update of the already copied branch
1200 * (which is not visible yet). We are transplanting
1201 * oy_right as a left child of old y's parent, so the
1202 * min values update propagated upward necessarily stops
1203 * at z_right.
1204 */
1205 rcu_rbtree_transplant(rbtree, y, oy_right, 0, y);
1206 y->max_end = calculate_node_max_end(rbtree, y);
1207 rcu_rbtree_transplant(rbtree, z, y, 1, NULL);
1208 /* Update children */
1209 (void) rcu_rbtree_min_update_decay(rbtree, y->_right);
1210 }
1211 y = get_decay(y);
1212 assert(!is_decay(z));
1213 assert(!is_decay(z->_left));
1214 y->color = z->color;
1215 set_parent(y->_left, y, IS_LEFT);
1216 set_parent(y->_right, get_decay(get_parent(y->_right)), IS_RIGHT);
1217 assert(!is_decay(y->_left));
1218 assert(!is_decay(y->_right));
1219 }
1220
1221 int rcu_rbtree_remove(struct rcu_rbtree *rbtree,
1222 struct rcu_rbtree_node *z)
1223 {
1224 struct rcu_rbtree_node *x, *y;
1225 unsigned int y_original_color;
1226
1227 assert(!is_decay(rbtree->root));
1228 dbg_printf("remove %p\n", z->begin);
1229 show_tree(rbtree);
1230
1231 assert(!is_decay(z));
1232 y = z;
1233 y_original_color = y->color;
1234
1235 if (rcu_rbtree_is_nil(rbtree, z->_left)) {
1236 rcu_rbtree_transplant(rbtree, z, z->_right, 1, NULL);
1237 assert(!is_decay(z));
1238 x = get_decay(z->_right);
1239 show_tree(rbtree);
1240 } else if (rcu_rbtree_is_nil(rbtree, z->_right)) {
1241 rcu_rbtree_transplant(rbtree, z, z->_left, 1, NULL);
1242 assert(!is_decay(z));
1243 x = get_decay(z->_left);
1244 show_tree(rbtree);
1245 } else {
1246 y = rcu_rbtree_min(rbtree, z->_right);
1247 assert(!is_decay(y));
1248 y_original_color = y->color;
1249 x = y->_right;
1250 rcu_rbtree_remove_nonil(rbtree, z, y);
1251 x = get_decay(x);
1252 show_tree(rbtree);
1253 }
1254 if (y_original_color == COLOR_BLACK)
1255 rcu_rbtree_remove_fixup(rbtree, x);
1256 show_tree(rbtree);
1257 check_max_end(rbtree, x);
1258 check_max_end(rbtree, get_decay(y));
1259 /*
1260 * Commit all _CMM_STORE_SHARED().
1261 */
1262 cmm_smp_wmc();
1263
1264 return 0;
1265 }
This page took 0.056196 seconds and 5 git commands to generate.