From: Mathieu Desnoyers Date: Thu, 30 May 2013 20:34:59 +0000 (-0400) Subject: rcuja: implement add unique X-Git-Url: http://git.liburcu.org/?p=userspace-rcu.git;a=commitdiff_plain;h=75d573aa7d4609a0845220527665aba86d9c32dc rcuja: implement add unique Signed-off-by: Mathieu Desnoyers --- diff --git a/rcuja/rcuja.c b/rcuja/rcuja.c index e5145ea..84c1fb7 100644 --- a/rcuja/rcuja.c +++ b/rcuja/rcuja.c @@ -1793,8 +1793,10 @@ end: return ret; } -int cds_ja_add(struct cds_ja *ja, uint64_t key, - struct cds_ja_node *new_node) +static +int _cds_ja_add(struct cds_ja *ja, uint64_t key, + struct cds_ja_node *new_node, + struct cds_ja_node **unique_node_ret) { unsigned int tree_depth, i; struct cds_ja_inode_flag *attach_node_flag, @@ -1847,6 +1849,7 @@ retry: if (!ja_node_ptr(node_flag)) { dbg_printf("cds_ja_add NULL parent2_node_flag %p parent_node_flag %p node_flag_ptr %p node_flag %p\n", parent2_node_flag, parent_node_flag, node_flag_ptr, node_flag); + attach_node_flag = parent_node_flag; attach_node_flag_ptr = parent_node_flag_ptr; parent_attach_node_flag = parent2_node_flag; @@ -1858,8 +1861,14 @@ retry: node_flag, key, i, new_node); } else { + if (unique_node_ret) { + *unique_node_ret = (struct cds_ja_node *) ja_node_ptr(node_flag); + return -EEXIST; + } + dbg_printf("cds_ja_add duplicate parent2_node_flag %p parent_node_flag %p node_flag_ptr %p node_flag %p\n", parent2_node_flag, parent_node_flag, node_flag_ptr, node_flag); + attach_node_flag = node_flag; attach_node_flag_ptr = node_flag_ptr; parent_attach_node_flag = parent_node_flag; @@ -1876,6 +1885,25 @@ retry: return ret; } +int cds_ja_add(struct cds_ja *ja, uint64_t key, + struct cds_ja_node *new_node) +{ + return _cds_ja_add(ja, key, new_node, NULL); +} + +struct cds_ja_node *cds_ja_add_unique(struct cds_ja *ja, uint64_t key, + struct cds_ja_node *new_node) +{ + int ret; + struct cds_ja_node *ret_node; + + ret = _cds_ja_add(ja, key, new_node, &ret_node); + if (ret == -EEXIST) + return ret_node; + else + return new_node; +} + /* * Note: there is no need to lookup the pointer address associated with * each node's nth item after taking the lock: it's already been done by @@ -2312,7 +2340,7 @@ void rcuja_free_all_children(struct cds_ja_shadow_node *shadow_node, struct cds_hlist_node *pos, *tmp; uint8_t v; - ja_linear_node_get_ith_pos(type, node, j, &v, &iter); + ja_linear_node_get_ith_pos(type, pool, j, &v, &iter); if (!iter) continue; head.next = (struct cds_hlist_node *) iter; diff --git a/tests/test_urcu_ja.c b/tests/test_urcu_ja.c index bad6784..af6ba08 100644 --- a/tests/test_urcu_ja.c +++ b/tests/test_urcu_ja.c @@ -666,19 +666,20 @@ void *test_ja_rw_thr_writer(void *_count) if ((addremove == AR_ADD) || (addremove == AR_RANDOM && is_add())) { struct ja_test_node *node = malloc(sizeof(*node)); + struct cds_ja_node *ret_node; /* note: only inserting ulong keys */ key = ((unsigned long) rand_r(&URCU_TLS(rand_lookup)) % write_pool_size) + write_pool_offset; key *= key_mul; ja_test_node_init(node, key); rcu_read_lock(); - ret = cds_ja_add(test_ja, key, &node->node); - URCU_TLS(nr_add)++; + ret_node = cds_ja_add_unique(test_ja, key, &node->node); rcu_read_unlock(); - if (ret) { - fprintf(stderr, "Error (%d) adding node %" PRIu64 "\n", - ret, key); - assert(0); + if (ret_node != &node->node) { + free(node); + URCU_TLS(nr_addexist)++; + } else { + URCU_TLS(nr_add)++; } } else { struct ja_test_node *node; diff --git a/urcu/rcuja.h b/urcu/rcuja.h index 9a006a3..0ab0518 100644 --- a/urcu/rcuja.h +++ b/urcu/rcuja.h @@ -62,6 +62,9 @@ struct cds_hlist_head cds_ja_lookup(struct cds_ja *ja, uint64_t key); int cds_ja_add(struct cds_ja *ja, uint64_t key, struct cds_ja_node *new_node); +struct cds_ja_node *cds_ja_add_unique(struct cds_ja *ja, uint64_t key, + struct cds_ja_node *new_node); + int cds_ja_del(struct cds_ja *ja, uint64_t key, struct cds_ja_node *node);