#include <urcu-call-rcu.h>
#include <urcu/uatomic.h>
+#include <urcu-pointer.h>
#include <assert.h>
#include <errno.h>
assert(node->dummy);
dummy = caa_container_of(node, struct cds_lfq_node_rcu_dummy, parent);
- call_rcu(&dummy->head, free_dummy_cb);
+ dummy->q->queue_call_rcu(&dummy->head, free_dummy_cb);
}
static inline
}
static inline
-void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
+void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q,
+ void queue_call_rcu(struct rcu_head *head,
+ void (*func)(struct rcu_head *head)))
{
q->tail = make_dummy(q, NULL);
q->head = q->tail;
+ q->queue_call_rcu = queue_call_rcu;
}
/*
}
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*/
static inline
void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
for (;;) {
struct cds_lfq_node_rcu *tail, *next;
- rcu_read_lock();
tail = rcu_dereference(q->tail);
next = uatomic_cmpxchg(&tail->next, NULL, node);
if (next == NULL) {
* enqueue might beat us to it, that's fine).
*/
(void) uatomic_cmpxchg(&q->tail, tail, node);
- rcu_read_unlock();
return;
} else {
/*
* Help moving tail further and retry.
*/
(void) uatomic_cmpxchg(&q->tail, tail, next);
- rcu_read_unlock();
continue;
}
}
}
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfq_node_rcu structure.
for (;;) {
struct cds_lfq_node_rcu *head, *next;
- rcu_read_lock();
head = rcu_dereference(q->head);
next = rcu_dereference(head->next);
- if (head->dummy && next == NULL) {
- rcu_read_unlock();
+ if (head->dummy && next == NULL)
return NULL; /* empty */
- }
/*
* We never, ever allow dequeue to get to a state where
* the queue is empty (we need at least one node in the
enqueue_dummy(q);
next = rcu_dereference(head->next);
}
- if (uatomic_cmpxchg(&q->head, head, next) != head) {
- rcu_read_unlock();
+ if (uatomic_cmpxchg(&q->head, head, next) != head)
continue; /* Concurrently pushed. */
- }
if (head->dummy) {
/* Free dummy after grace period. */
rcu_free_dummy(head);
- rcu_read_unlock();
continue; /* try again */
}
- rcu_read_unlock();
return head;
}
}