From: Mathieu Desnoyers Date: Wed, 25 Aug 2010 15:16:34 +0000 (-0400) Subject: urcu lfstack: pop needs rcu read lock X-Git-Tag: v0.4.7~1 X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=commitdiff_plain;h=4fc06b7fbadc933271cf1b75e03a923486f7247b urcu lfstack: pop needs rcu read lock The pop side needs to hold the RCU read lock to deal with ABA problem. The push side does not need to hold the RCU read lock because even if the next item is changed to the same value initially read, the stack will still be consistent. Signed-off-by: Mathieu Desnoyers --- diff --git a/urcu/rculfstack-static.h b/urcu/rculfstack-static.h index 49e5ef4..3ce24c5 100644 --- a/urcu/rculfstack-static.h +++ b/urcu/rculfstack-static.h @@ -68,22 +68,28 @@ void _rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node) struct rcu_lfs_node * _rcu_lfs_pop(struct rcu_lfs_stack *s) { - struct rcu_lfs_node *head = NULL; - for (;;) { - struct rcu_lfs_node *old_head = head; - struct rcu_lfs_node *next; + struct rcu_lfs_node *head; - if (head) - next = head->next; - else - next = NULL; + rcu_read_lock(); + head = rcu_dereference(s->head); + if (head) { + struct rcu_lfs_node *next = rcu_dereference(head->next); - head = uatomic_cmpxchg(&s->head, old_head, next); - if (old_head == head) - break; + if (uatomic_cmpxchg(&s->head, head, next) == head) { + rcu_read_unlock(); + return head; + } else { + /* Concurrent modification. Retry. */ + rcu_read_unlock(); + continue; + } + } else { + /* Empty stack */ + rcu_read_unlock(); + return NULL; + } } - return head; } #ifdef __cplusplus