Use decay for rotate and transplant
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 May 2011 23:20:59 +0000 (19:20 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 May 2011 23:20:59 +0000 (19:20 -0400)
Handles assumptions about shared nil node more gracefully.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
tests/test_urcu_rbtree.c
urcu-rbtree.c

index 1f617793e4c32cdc87c4fb4125a777380bd91721..9c597266d9f6b5602e9d943066388b26fc9ff3c5 100644 (file)
@@ -47,8 +47,8 @@
 #define NR_CPUS 16384
 
 /* number of insert/delete */
-//#define NR_RAND 4
-#define NR_RAND 7
+#define NR_RAND 6
+//#define NR_RAND 7
 
 #if defined(_syscall0)
 _syscall0(pid_t, gettid)
index 976af39a7ad08a90a5a8dfb58b47b08432a56fa7..d612045ce817c38dcd0c61ca4077fe834b31d612 100644 (file)
@@ -51,7 +51,8 @@
  * Undefine this to enable the non-RCU rotate and transplant functions
  * (for debugging).
  */
-#define RBTREE_RCU_SUPPORT_ROTATE
+#define RBTREE_RCU_SUPPORT_ROTATE_LEFT
+#define RBTREE_RCU_SUPPORT_ROTATE_RIGHT
 #define RBTREE_RCU_SUPPORT_TRANSPLANT
 
 static
@@ -63,6 +64,8 @@ void set_decay(struct rcu_rbtree_node *x, struct rcu_rbtree_node *xc)
 static
 struct rcu_rbtree_node *get_decay(struct rcu_rbtree_node *x)
 {
+       if (!x)
+               return NULL;
        while (x->decay_next)
                x = x->decay_next;
        return x;
@@ -239,7 +242,8 @@ struct rcu_rbtree_node *rcu_rbtree_prev(struct rcu_rbtree *rbtree,
 /* RCU: copy x and y, atomically point to new versions. GC old. */
 /* Should be eventually followed by a cmm_smp_wmc() */
 
-#ifdef RBTREE_RCU_SUPPORT_ROTATE
+#ifdef RBTREE_RCU_SUPPORT_ROTATE_LEFT
+
 static
 void left_rotate(struct rcu_rbtree *rbtree,
                 struct rcu_rbtree_node *x)
@@ -251,9 +255,9 @@ void left_rotate(struct rcu_rbtree *rbtree,
        y_left = y->left;
 
        /* Now operate on new copy, decay old versions */
-       //x = dup_decay_node(rbtree, x);
-       //y = dup_decay_node(rbtree, y);
-       //y_left = dup_decay_node(rbtree, y_left);
+       x = dup_decay_node(rbtree, x);
+       y = dup_decay_node(rbtree, y);
+       y_left = dup_decay_node(rbtree, y_left);
 
        x_pos = x->pos;
        x_p = x->p;
@@ -280,11 +284,13 @@ void left_rotate(struct rcu_rbtree *rbtree,
        else
                _CMM_STORE_SHARED(x_p->right, y);
 
-       /* Point children to new copy (parent only used by updates) */
-       if (!rcu_rbtree_is_nil(x->left))
-               x->left->p = x;
-       if (!rcu_rbtree_is_nil(y->right))
-               y->right->p = y;
+       /* Point children to new copy (parent only used by updates/next/prev) */
+       x->left->p = get_decay(x->left->p);
+       y->right->p = get_decay(y->right->p);
+       if (!rcu_rbtree_is_nil(y_left)) {
+               y_left->right->p = get_decay(y_left->right->p);
+               y_left->left->p = get_decay(y_left->left->p);
+       }
 
        /* Sanity checks */
        assert(y == rbtree->root || y->p->left == y || y->p->right == y);
@@ -302,6 +308,39 @@ void left_rotate(struct rcu_rbtree *rbtree,
        assert(!is_decay(y->left));
 }
 
+#else
+
+/* non-rcu version */
+static
+void left_rotate(struct rcu_rbtree *rbtree,
+                struct rcu_rbtree_node *x)
+{
+       struct rcu_rbtree_node *y;
+
+       y = x->right;
+       x->right = y->left;
+       if (!rcu_rbtree_is_nil(y->left)) {
+               y->left->p = x;
+               y->left->pos = IS_RIGHT;
+       }
+       y->p = x->p;
+       if (rcu_rbtree_is_nil(x->p))
+               rbtree->root = y;
+       else if (x == x->p->left) {
+               x->p->left = y;
+               y->pos = IS_LEFT;
+       } else {
+               x->p->right = y;
+               y->pos = IS_RIGHT;
+       }
+       y->left = x;
+       x->pos = IS_LEFT;
+       x->p = y;
+}
+
+#endif
+
+#ifdef RBTREE_RCU_SUPPORT_ROTATE_RIGHT
 static
 void right_rotate(struct rcu_rbtree *rbtree,
                  struct rcu_rbtree_node *x)
@@ -313,9 +352,9 @@ void right_rotate(struct rcu_rbtree *rbtree,
        y_right = y->right;
 
        /* Now operate on new copy, decay old versions */
-       //x = dup_decay_node(rbtree, x);
-       //y = dup_decay_node(rbtree, y);
-       //y_right = dup_decay_node(rbtree, y_right);
+       x = dup_decay_node(rbtree, x);
+       y = dup_decay_node(rbtree, y);
+       y_right = dup_decay_node(rbtree, y_right);
 
        x_pos = x->pos;
        x_p = x->p;
@@ -342,11 +381,13 @@ void right_rotate(struct rcu_rbtree *rbtree,
        else
                _CMM_STORE_SHARED(x_p->left, y);
 
-       /* Point children to new copy (parent only used by updates) */
-       if (!rcu_rbtree_is_nil(x->right))
-               x->right->p = x;
-       if (!rcu_rbtree_is_nil(y->left))
-               y->left->p = y;
+       /* Point children to new copy (parent only used by updates/next/prev) */
+       x->right->p = get_decay(x->right->p);
+       y->left->p = get_decay(y->left->p);
+       if (!rcu_rbtree_is_nil(y_right)) {
+               y_right->left->p = get_decay(y_right->left->p);
+               y_right->right->p = get_decay(y_right->right->p);
+       }
 
        /* Sanity checks */
        assert(y == rbtree->root || y->p->right == y || y->p->left == y);
@@ -366,34 +407,7 @@ void right_rotate(struct rcu_rbtree *rbtree,
 
 #else
 
-/* non-rcu versions */
-static
-void left_rotate(struct rcu_rbtree *rbtree,
-                struct rcu_rbtree_node *x)
-{
-       struct rcu_rbtree_node *y;
-
-       y = x->right;
-       x->right = y->left;
-       if (!rcu_rbtree_is_nil(y->left)) {
-               y->left->p = x;
-               y->left->pos = IS_RIGHT;
-       }
-       y->p = x->p;
-       if (rcu_rbtree_is_nil(x->p))
-               rbtree->root = y;
-       else if (x == x->p->left) {
-               x->p->left = y;
-               y->pos = IS_LEFT;
-       } else {
-               x->p->right = y;
-               y->pos = IS_RIGHT;
-       }
-       y->left = x;
-       x->pos = IS_LEFT;
-       x->p = y;
-}
-
+/* non-rcu version */
 static
 void right_rotate(struct rcu_rbtree *rbtree,
                  struct rcu_rbtree_node *x)
@@ -555,8 +569,8 @@ void rcu_rbtree_transplant(struct rcu_rbtree *rbtree,
 {
        dbg_printf("transplant %p\n", v->key);
 
-       //if (!rcu_rbtree_is_nil(v))
-       //      v = dup_decay_node(rbtree, v);
+       if (!rcu_rbtree_is_nil(v))
+               v = dup_decay_node(rbtree, v);
 
        if (rcu_rbtree_is_nil(u->p)) {
                v->p = u->p;
@@ -573,12 +587,10 @@ void rcu_rbtree_transplant(struct rcu_rbtree *rbtree,
                cmm_smp_wmb();  /* write into node before publish */
                _CMM_STORE_SHARED(u->p->right, v);
        }
-       /* Set children parent to new node (only used by updates) */
+       /* Point children to new copy (parent only used by updates/next/prev) */
        if (!rcu_rbtree_is_nil(v)) {
-               if (!rcu_rbtree_is_nil(v->right))
-                       v->right->p = v;
-               if (!rcu_rbtree_is_nil(v->left))
-                       v->left->p = v;
+               v->right->p = get_decay(v->right->p);
+               v->left->p = get_decay(v->left->p);
        }
        assert(!is_decay(rbtree->root));
 }
This page took 0.028759 seconds and 4 git commands to generate.