#include <stdio.h>
#include <pthread.h>
+#include <assert.h>
#include <urcu-rbtree.h>
#include <urcu-pointer.h>
struct rcu_rbtree_node *rcu_rbtree_next(struct rcu_rbtree_node *x,
rcu_rbtree_comp comp)
{
- struct rcu_rbtree_node *xr, *y;
+ struct rcu_rbtree_node *xr, *y, *yredir;
x = rcu_dereference(x);
if ((xr = rcu_dereference(x->right)) != &rcu_rbtree_nil)
return rcu_rbtree_min(xr, comp);
y = rcu_dereference(x->p);
+ while ((yredir = rcu_dereference(y->redir)) != NULL)
+ y = yredir;
while (y != &rcu_rbtree_nil && x == rcu_dereference(y->right)) {
x = y;
y = rcu_dereference(y->p);
+ while ((yredir = rcu_dereference(y->redir)) != NULL)
+ y = yredir;
}
return y;
}
struct rcu_rbtree_node *rcu_rbtree_prev(struct rcu_rbtree_node *x,
rcu_rbtree_comp comp)
{
- struct rcu_rbtree_node *xl, *y;
+ struct rcu_rbtree_node *xl, *y, *yredir;
x = rcu_dereference(x);
if ((xl = rcu_dereference(x->left)) != &rcu_rbtree_nil)
return rcu_rbtree_max(xl, comp);
y = rcu_dereference(x->p);
+ while ((yredir = rcu_dereference(y->redir)) != NULL)
+ y = yredir;
while (y != &rcu_rbtree_nil && x == rcu_dereference(y->left)) {
x = y;
y = rcu_dereference(y->p);
+ while ((yredir = rcu_dereference(y->redir)) != NULL)
+ y = yredir;
}
return y;
}
*/
smp_wmb();
+ /*
+ * redirect old nodes to new.
+ */
+ x->redir = xc;
+ y->redir = yc;
+
+ /*
+ * Ensure that redirections are visible before updating external
+ * pointers.
+ */
+ smp_wmb();
+
/* Make parents point to the copies */
if (x->p == &rcu_rbtree_nil)
_STORE_SHARED(*root, yc);
*/
smp_wmb();
+ /*
+ * redirect old nodes to new.
+ */
+ x->redir = xc;
+ y->redir = yc;
+
+ /*
+ * Ensure that redirections are visible before updating external
+ * pointers.
+ */
+ smp_wmb();
+
/* Make parents point to the copies */
if (x->p == &rcu_rbtree_nil)
_STORE_SHARED(*root, yc);
z->left = &rcu_rbtree_nil;
z->right = &rcu_rbtree_nil;
z->color = COLOR_RED;
+ z->redir = NULL;
/*
* Order stores to z (children/parents) before stores that will make it
* that will make the copies visible to the rest of the tree.
*/
smp_wmb();
+
+ /*
+ * redirect old node to new.
+ */
+ v->redir = vc;
+
+ /*
+ * Ensure that redirections are visible before updating external
+ * pointers.
+ */
+ smp_wmb();
} else {
vc = &rcu_rbtree_nil;
}
{
while (x != *root && x->color == COLOR_BLACK) {
if (x == x->p->left) {
- struct rcu_rbtree_node *w;
+ struct rcu_rbtree_node *w, *t;
w = x->p->right;
if (w->color == COLOR_RED) {
w->color == COLOR_BLACK;
x->p->color = COLOR_RED;
- left_rotate(root, x->p, rballoc, rbfree);
+ t = left_rotate(root, x->p, rballoc, rbfree);
+ assert(x->p->left == t->left);
/* x is a left node, not copied by rotation */
w = x->p->right;
}
*/
smp_wmb();
+ /*
+ * redirect old nodes to new.
+ */
+ if (x != &rcu_rbtree_nil)
+ x->redir = xc;
+ y->redir = yc;
+
+ /*
+ * Ensure that redirections are visible before updating external
+ * pointers.
+ */
+ smp_wmb();
+
/* Update external pointers */
if (y->p != z) {