Fix: wfcqueue nonblocking dequeue
[urcu.git] / urcu / static / wfcqueue.h
index 120a5989e6a4341c7d2ec8a4fc719812235542ae..a284b580af7d8777087ba17e6094c40e03abecc9 100644 (file)
@@ -6,8 +6,8 @@
  *
  * Userspace RCU library - Concurrent Queue with Wait-Free Enqueue/Blocking Dequeue
  *
- * TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See wfcqueue.h for linking
- * dynamically with the userspace rcu library.
+ * TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See urcu/wfcqueue.h for
+ * linking dynamically with the userspace rcu library.
  *
  * Copyright 2010-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  * Copyright 2011-2012 - Lai Jiangshan <laijs@cn.fujitsu.com>
@@ -312,6 +312,8 @@ ___cds_wfcq_dequeue(struct cds_wfcq_head *head,
                return NULL;
 
        node = ___cds_wfcq_node_sync_next(&head->node, blocking);
+       if (!blocking && node == CDS_WFCQ_WOULDBLOCK)
+               return CDS_WFCQ_WOULDBLOCK;
 
        if ((next = CMM_LOAD_SHARED(node->next)) == NULL) {
                /*
@@ -332,6 +334,15 @@ ___cds_wfcq_dequeue(struct cds_wfcq_head *head,
                if (uatomic_cmpxchg(&tail->p, node, &head->node) == node)
                        return node;
                next = ___cds_wfcq_node_sync_next(node, blocking);
+               /*
+                * In nonblocking mode, if we would need to block to
+                * get node's next, set the head next node pointer
+                * (currently NULL) back to its original value.
+                */
+               if (!blocking && next == CDS_WFCQ_WOULDBLOCK) {
+                       head->node.next = node;
+                       return CDS_WFCQ_WOULDBLOCK;
+               }
        }
 
        /*
This page took 0.022789 seconds and 4 git commands to generate.