Implement transplant based on decay scheme
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 May 2011 21:26:41 +0000 (17:26 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 28 May 2011 21:26:41 +0000 (17:26 -0400)
Works with writer test. Concurrent RCU reader not supported yet.

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

index 489f30b9c598738503f7dfe093702030d31222cf..44132630344bfda3a1691766106c4b275ff58270 100644 (file)
@@ -74,8 +74,10 @@ struct rcu_rbtree_node *rbtree_alloc(void)
        return calloc(1, sizeof(struct rcu_rbtree_node));
 }
 
-void rbtree_free(void *node)
+void rbtree_free(struct rcu_head *head)
 {
+       struct rcu_rbtree_node *node =
+               caa_container_of(head, struct rcu_rbtree_node, head);
        free(node);
 }
 
@@ -256,7 +258,7 @@ void *thr_writer(void *_count)
 
        set_affinity();
 
-       rcu_defer_register_thread();
+       rcu_register_thread();
 
        while (!test_go)
        {
@@ -296,7 +298,7 @@ void *thr_writer(void *_count)
                        node = rcu_rbtree_search(&rbtree, rbtree.root, key[i]);
                        assert(!rcu_rbtree_is_nil(node));
                        rcu_rbtree_remove(&rbtree, node);
-                       defer_rcu((void (*)(void *))rbtree_free, node);
+                       call_rcu(&node->head, rbtree_free);
                }
 
                rcu_read_unlock();
@@ -308,7 +310,7 @@ void *thr_writer(void *_count)
                        loop_sleep(wdelay);
        }
 
-       rcu_defer_unregister_thread();
+       rcu_unregister_thread();
 
        printf_verbose("thread_end %s, thread id : %lx, tid %lu\n",
                        "writer", pthread_self(), (unsigned long)gettid());
index 0b0b380f2d3b53ecc3a47c8cabc0770bf63d5875..04851bd21735387719a095acdba83798d6b1c08c 100644 (file)
@@ -37,7 +37,7 @@
 
 #include <urcu/rcurbtree.h>
 #include <urcu-pointer.h>
-#include <urcu-defer.h>
+#include <urcu-call-rcu.h>
 
 #define DEBUG
 
@@ -80,7 +80,7 @@ struct rcu_rbtree_node *dup_decay_node(struct rcu_rbtree *rbtree,
        memcpy(xc, x, sizeof(struct rcu_rbtree_node));
        xc->decay_next = NULL;
        set_decay(x, xc);
-       defer_rcu(rbtree->rbfree, x);
+       call_rcu(&x->head, rbtree->rbfree);
        return xc;
 }
 
@@ -465,16 +465,29 @@ void rcu_rbtree_transplant(struct rcu_rbtree *rbtree,
 {
        dbg_printf("transplant %p\n", v->key);
 
-       if (rcu_rbtree_is_nil(u->p))
-               rbtree->root = v;
-       else if (u == u->p->left) {
-               u->p->left = v;
+       if (!rcu_rbtree_is_nil(v))
+               v = dup_decay_node(rbtree, v);
+
+       if (rcu_rbtree_is_nil(u->p)) {
+               v->p = u->p;
+               cmm_smp_wmb();  /* write into node before publish */
+               _CMM_STORE_SHARED(rbtree->root, v);
+       } else if (u == u->p->left) {
                v->pos = IS_LEFT;
+               v->p = u->p;
+               cmm_smp_wmb();  /* write into node before publish */
+               _CMM_STORE_SHARED(u->p->left, v);
        } else {
-               u->p->right = v;
                v->pos = IS_RIGHT;
+               v->p = u->p;
+               cmm_smp_wmb();  /* write into node before publish */
+               _CMM_STORE_SHARED(u->p->right, v);
+       }
+       /* Set children parent to new node */
+       if (!rcu_rbtree_is_nil(v)) {
+               v->right->p = v;
+               v->left->p = v;
        }
-       v->p = u->p;
        assert(!is_decay(rbtree->root));
 }
 
@@ -484,6 +497,8 @@ static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
        dbg_printf("remove fixup %p\n", x->key);
 
        while (x != rbtree->root && x->color == COLOR_BLACK) {
+               assert(!is_decay(x->p));
+               assert(!is_decay(x->p->left));
                if (x == x->p->left) {
                        struct rcu_rbtree_node *w;
 
@@ -501,11 +516,14 @@ static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
                            && w->right->color == COLOR_BLACK) {
                                w->color = COLOR_RED;
                                x = x->p;
+                               assert(!is_decay(rbtree->root));
+                               assert(!is_decay(x));
                        } else {
                                if (w->right->color == COLOR_BLACK) {
                                        w->left->color = COLOR_BLACK;
                                        w->color = COLOR_RED;
                                        right_rotate(rbtree, w);
+                                       assert(!is_decay(rbtree->root));
                                        x = get_decay(x);
                                        w = x->p->right;
                                }
@@ -525,6 +543,7 @@ static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
                                w->color = COLOR_BLACK;
                                x->p->color = COLOR_RED;
                                right_rotate(rbtree, x->p);
+                               assert(!is_decay(rbtree->root));
                                x = get_decay(x);
                                w = x->p->left;
                        }
@@ -532,6 +551,8 @@ static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
                            && w->left->color == COLOR_BLACK) {
                                w->color = COLOR_RED;
                                x = x->p;
+                               assert(!is_decay(rbtree->root));
+                               assert(!is_decay(x));
                        } else {
                                if (w->left->color == COLOR_BLACK) {
                                        w->right->color = COLOR_BLACK;
@@ -545,6 +566,7 @@ static void rcu_rbtree_remove_fixup(struct rcu_rbtree *rbtree,
                                x->p->color = COLOR_BLACK;
                                w->left->color = COLOR_BLACK;
                                right_rotate(rbtree, x->p);
+                               assert(!is_decay(rbtree->root));
                                x = rbtree->root;
                        }
                }
@@ -565,19 +587,26 @@ void rcu_rbtree_remove_nonil(struct rcu_rbtree *rbtree,
        dbg_printf("remove nonil %p\n", z->key);
        show_tree(rbtree);
 
+       assert(!is_decay(z));
+       assert(!is_decay(y));
+       assert(!is_decay(y->right));
+       assert(!is_decay(y->p));
        x = y->right;
+       assert(!is_decay(x));
        if (y->p == z)
                x->p = y;
        else {
                rcu_rbtree_transplant(rbtree, y, y->right);
                assert(!is_decay(y));
                assert(!is_decay(z));
+               assert(!is_decay(z->right));
                y->right = z->right;
                y->right->p = y;
        }
        rcu_rbtree_transplant(rbtree, z, y);
-       assert(!is_decay(y));
+       y = get_decay(y);
        assert(!is_decay(z));
+       assert(!is_decay(z->left));
        y->left = z->left;
        y->left->p = y;
        y->color = z->color;
@@ -593,25 +622,26 @@ int rcu_rbtree_remove(struct rcu_rbtree *rbtree,
        dbg_printf("remove %p\n", z->key);
        show_tree(rbtree);
 
+       assert(!is_decay(z));
        y = z;
        y_original_color = y->color;
 
        if (rcu_rbtree_is_nil(z->left)) {
                rcu_rbtree_transplant(rbtree, z, z->right);
                assert(!is_decay(z));
-               x = z->right;
+               x = get_decay(z->right);
                show_tree(rbtree);
        } else if (rcu_rbtree_is_nil(z->right)) {
                rcu_rbtree_transplant(rbtree, z, z->left);
                assert(!is_decay(z));
-               x = z->left;
+               x = get_decay(z->left);
                show_tree(rbtree);
        } else {
                y = rcu_rbtree_min(rbtree, z->right);
+               assert(!is_decay(y));
                y_original_color = y->color;
                rcu_rbtree_remove_nonil(rbtree, z, y);
-               assert(!is_decay(y));
-               x = y->right;
+               x = get_decay(y->right);
                show_tree(rbtree);
        }
        if (y_original_color == COLOR_BLACK)
index 9c4f0ea3ca3f34a21bcdae9059a9b283a2295832..bb6f3d82d5203589f04eec17bfa2037627a278ec 100644 (file)
@@ -31,6 +31,7 @@
  */
 
 #include <pthread.h>
+#include <urcu-call-rcu.h>
 
 #define COLOR_BLACK    0
 #define COLOR_RED      1
@@ -50,7 +51,7 @@ typedef int (*rcu_rbtree_comp)(void *a, void *b);
  * Node allocation and deletion functions.
  */
 typedef struct rcu_rbtree_node *(*rcu_rbtree_alloc)(void);
-typedef void (*rcu_rbtree_free)(void *node);
+typedef void (*rcu_rbtree_free)(struct rcu_head *head);
 
 struct rcu_rbtree_node {
        /* must be set upon insertion */
@@ -59,6 +60,7 @@ struct rcu_rbtree_node {
        /* internally reserved */
        struct rcu_rbtree_node *p, *left, *right;
        struct rcu_rbtree_node *decay_next;
+       struct rcu_head head;           /* For delayed free */
        unsigned int color:1;
        unsigned int pos:1;
        unsigned int nil:1;
This page took 0.029524 seconds and 4 git commands to generate.