RCU lock-free queue: don't hold RCU read lock across retry
[urcu.git] / urcu / rculfstack.h
index f43c9d8c1e679c344bdb289b445fdd99ed0c466d..48f6297eb5213dd82234b0a0e8bdd86d548d8a9c 100644 (file)
@@ -43,10 +43,11 @@ void rcu_lfs_init(struct rcu_lfs_stack *s)
 
 void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
 {
-       rcu_read_lock();
        for (;;) {
-               struct rcu_lfs_node *head = rcu_dereference(s->head);
+               struct rcu_lfs_node *head;
 
+               rcu_read_lock();
+               head = rcu_dereference(s->head);
                node->next = head;
                /*
                 * uatomic_cmpxchg() implicit memory barrier orders earlier
@@ -57,18 +58,25 @@ void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
                        return;
                } else {
                        /* Failure to prepend. Retry. */
+                       rcu_read_unlock();
                        continue;
                }
        }
 }
 
+/*
+ * The caller must wait for a grace period to pass before freeing the returned
+ * node.
+ * Returns NULL if stack is empty.
+ */
 struct rcu_lfs_node *
 rcu_lfs_pop(struct rcu_lfs_stack *s)
 {
-       rcu_read_lock();
        for (;;) {
-               struct rcu_lfs_node *head = rcu_dereference(s->head);
+               struct rcu_lfs_node *head;
 
+               rcu_read_lock();
+               head = rcu_dereference(s->head);
                if (head) {
                        struct rcu_lfs_node *next = rcu_dereference(head->next);
 
@@ -77,6 +85,7 @@ rcu_lfs_pop(struct rcu_lfs_stack *s)
                                return head;
                        } else {
                                /* Concurrent modification. Retry. */
+                               rcu_read_unlock();
                                continue;
                        }
                } else {
This page took 0.023287 seconds and 4 git commands to generate.