RCU lock-free queue: don't hold RCU read lock across retry
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 13 Jul 2010 15:59:55 +0000 (11:59 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Tue, 13 Jul 2010 15:59:55 +0000 (11:59 -0400)
Be nicer to grace periods.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
urcu/rculfqueue.h

index 32fca49a6cb126a38ad4342c31a23a74a091545f..09e5d41ea0db7b7f40032419b070ed55daecdfdd 100644 (file)
@@ -72,11 +72,11 @@ void rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *node)
         * node before publication.
         */
 
         * node before publication.
         */
 
-       rcu_read_lock();
        for (;;) {
        for (;;) {
-               struct rcu_lfq_node *tail = rcu_dereference(q->tail);
-               struct rcu_lfq_node *next;
+               struct rcu_lfq_node *tail, *next;
 
 
+               rcu_read_lock();
+               tail = rcu_dereference(q->tail);
                /*
                 * Typically expect tail->next to be NULL.
                 */
                /*
                 * Typically expect tail->next to be NULL.
                 */
@@ -97,6 +97,7 @@ void rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *node)
                         * further and retry.
                         */
                        uatomic_cmpxchg(&q->tail, tail, next);
                         * further and retry.
                         */
                        uatomic_cmpxchg(&q->tail, tail, next);
+                       rcu_read_unlock();
                        continue;
                }
        }
                        continue;
                }
        }
@@ -113,11 +114,12 @@ void rcu_lfq_enqueue(struct rcu_lfq_queue *q, struct rcu_lfq_node *node)
 struct rcu_lfq_node *
 rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref *))
 {
 struct rcu_lfq_node *
 rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref *))
 {
-       rcu_read_lock();
        for (;;) {
        for (;;) {
-               struct rcu_lfq_node *head = rcu_dereference(q->head);
-               struct rcu_lfq_node *next = rcu_dereference(head->next);
+               struct rcu_lfq_node *head, *next;
 
 
+               rcu_read_lock();
+               head = rcu_dereference(q->head);
+               next = rcu_dereference(head->next);
                if (next) {
                        if (uatomic_cmpxchg(&q->head, head, next) == head) {
                                rcu_read_unlock();
                if (next) {
                        if (uatomic_cmpxchg(&q->head, head, next) == head) {
                                rcu_read_unlock();
@@ -125,6 +127,7 @@ rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref *))
                                return next;
                        } else {
                                /* Concurrently pushed, retry */
                                return next;
                        } else {
                                /* Concurrently pushed, retry */
+                               rcu_read_unlock();
                                continue;
                        }
                } else {
                                continue;
                        }
                } else {
This page took 0.031633 seconds and 4 git commands to generate.