From: Mathieu Desnoyers Date: Sat, 28 May 2011 23:20:59 +0000 (-0400) Subject: Use decay for rotate and transplant X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=dbe4ae98200cd53fe08992057a9cf55a5638e267;p=urcu.git Use decay for rotate and transplant Handles assumptions about shared nil node more gracefully. Signed-off-by: Mathieu Desnoyers --- diff --git a/tests/test_urcu_rbtree.c b/tests/test_urcu_rbtree.c index 1f61779..9c59726 100644 --- a/tests/test_urcu_rbtree.c +++ b/tests/test_urcu_rbtree.c @@ -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) diff --git a/urcu-rbtree.c b/urcu-rbtree.c index 976af39..d612045 100644 --- a/urcu-rbtree.c +++ b/urcu-rbtree.c @@ -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)); }