struct urcu_wait_node {
struct cds_lfs_node node;
int32_t state; /* enum urcu_wait_state */
+ int in_waitqueue;
};
#define URCU_WAIT_NODE_INIT(name, _state) \
bool urcu_wait_add(struct urcu_wait_queue *queue,
struct urcu_wait_node *node)
{
+ cds_lfs_node_init(&node->node);
+ CMM_STORE_SHARED(node->in_waitqueue, true);
return cds_lfs_push(&queue->stack, &node->node);
}
{
urcu_wait_set_state(node, state);
cds_lfs_node_init(&node->node);
+ node->in_waitqueue = false;
+}
+
+static inline
+bool urcu_in_waitqueue(struct urcu_wait_node *node)
+{
+ return CMM_LOAD_SHARED(node->in_waitqueue);
}
/*
if (!node)
return -ENOENT;
wait_node = caa_container_of(node, struct urcu_wait_node, node);
- CMM_STORE_SHARED(wait_node->node.next, NULL);
+ CMM_STORE_SHARED(wait_node->in_waitqueue, false);
/* Don't wake already running threads */
if (!(wait_node->state & URCU_WAIT_RUNNING))
ret = urcu_adaptative_wake_up(wait_node);
struct urcu_wait_node *wait_node =
caa_container_of(iter, struct urcu_wait_node, node);
- CMM_STORE_SHARED(wait_node->node.next, NULL);
+ CMM_STORE_SHARED(wait_node->in_waitqueue, false);
/* Don't wake already running threads */
if (wait_node->state & URCU_WAIT_RUNNING)
continue;
/*
* Make sure we are removed from waitqueue.
*/
- if (CMM_LOAD_SHARED(worker->wait_node.node.next))
+ if (urcu_in_waitqueue(&worker->wait_node))
__urcu_workqueue_wakeup_all(queue);
/*
return URCU_ACCEPT_SHUTDOWN;
urcu_wait_set_state(&worker->wait_node,
URCU_WAIT_WAITING);
- if (!CMM_LOAD_SHARED(worker->wait_node.node.next)) {
+ if (!urcu_in_waitqueue(&worker->wait_node)) {
int was_empty;
- /*
- * NULL next pointer. We are therefore not in
- * the queue.
- */
- cds_lfs_node_init(&worker->wait_node.node);
/* Protect stack dequeue against ABA */
synchronize_rcu();
was_empty = !urcu_wait_add(&queue->waitqueue,
}
} else {
/*
- * Non-NULL next pointer. We are therefore in
- * the queue, or the dispatcher just removed us
- * from it (after we read the next pointer), and
- * is therefore awakening us. The state will
- * therefore have been changed from WAITING to
- * some other state, which will let the busy
- * wait pass through.
+ * We are in the queue, or the dispatcher just removed
+ * us from it (after we read the next pointer), and is
+ * therefore awakening us. The state will therefore have
+ * been changed from WAITING to some other state, which
+ * will let the busy wait pass through.
*/
}
urcu_adaptative_busy_wait(&worker->wait_node);