From: Mathieu Desnoyers Date: Thu, 23 May 2013 15:16:13 +0000 (-0400) Subject: rcuja fix: del wrt concurrency X-Git-Url: https://git.lttng.org./?a=commitdiff_plain;h=013a6083eb55908e91ee288b8dd4e455d17d9dec;p=urcu.git rcuja fix: del wrt concurrency testing with: test_urcu_ja 0 3 10 -v -M 1 -N 1 -O 1 Signed-off-by: Mathieu Desnoyers --- diff --git a/rcuja/rcuja.c b/rcuja/rcuja.c index e6e3a3e..d849537 100644 --- a/rcuja/rcuja.c +++ b/rcuja/rcuja.c @@ -1336,29 +1336,35 @@ static int ja_unchain_node(struct cds_ja *ja, struct cds_ja_inode_flag *parent_node_flag, struct cds_ja_inode_flag **node_flag_ptr, - struct cds_hlist_head *head, + struct cds_ja_inode_flag *node_flag, struct cds_ja_node *node) { struct cds_ja_shadow_node *shadow_node; struct cds_hlist_node *hlist_node; - int ret = 0, count = 0; + struct cds_hlist_head hlist_head; + int ret = 0, count = 0, found = 0; shadow_node = rcuja_shadow_lookup_lock(ja->ht, parent_node_flag); if (!shadow_node) return -EAGAIN; - if (!ja_node_ptr(*node_flag_ptr)) { + if (ja_node_ptr(*node_flag_ptr) != ja_node_ptr(node_flag)) { ret = -EAGAIN; goto end; } + hlist_head.next = (struct cds_hlist_node *) ja_node_ptr(node_flag); /* * Retry if another thread removed all but one of duplicates * since check (this check was performed without lock). + * Ensure that the node we are about to remove is still in the + * list (while holding lock). */ - cds_hlist_for_each_rcu(hlist_node, head, list) { + cds_hlist_for_each_rcu(hlist_node, &hlist_head) { count++; + if (hlist_node == &node->list) + found++; } - - if (count == 1) { + assert(found <= 1); + if (!found || count == 1) { ret = -EAGAIN; goto end; } @@ -1465,7 +1471,7 @@ retry: snapshot_n, nr_snapshot, key, node); } else { ret = ja_unchain_node(ja, snapshot[nr_snapshot - 1], - node_flag_ptr, &hlist_head, match); + node_flag_ptr, node_flag, match); } } /*