+#ifndef _URCU_RCULFQUEUE_H
+#define _URCU_RCULFQUEUE_H
+
/*
* rculfqueue.h
*
#include <urcu/urcu_ref.h>
#include <assert.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if (!defined(_GNU_SOURCE) && !defined(_LGPL_SOURCE))
#error "Dynamic loader LGPL wrappers not implemented yet"
#endif
* node before publication.
*/
- rcu_read_lock();
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.
*/
* further and retry.
*/
uatomic_cmpxchg(&q->tail, tail, next);
+ rcu_read_unlock();
continue;
}
}
/*
* The entry returned by dequeue must be taken care of by doing a urcu_ref_put,
* which calls the release primitive when the reference count drops to zero. A
- * grace period must be waited before performing the actual memory reclamation
- * in the release primitive.
- * The entry lfq node returned by dequeue must no be re-used before the
- * reference count reaches zero.
+ * grace period must be waited after execution of the release callback before
+ * performing the actual memory reclamation or modifying the rcu_lfq_node
+ * structure.
+ * In other words, the entry lfq node returned by dequeue must not be
+ * modified/re-used/freed until the reference count reaches zero and a grace
+ * period has elapsed (after the refcount reached 0).
*/
struct rcu_lfq_node *
rcu_lfq_dequeue(struct rcu_lfq_queue *q, void (*release)(struct urcu_ref *))
{
- rcu_read_lock();
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();
return next;
} else {
/* Concurrently pushed, retry */
+ rcu_read_unlock();
continue;
}
} else {
}
}
}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_RCULFQUEUE_H */