X-Git-Url: http://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu%2Frculfqueue.h;h=598fa5071a2ca727e43d07a67cb2a62eb4980632;hp=55f15f82cd7e408dc1477d3517c979670a6bb047;hb=a59f39055b5ecb77b68cf78b9839aa9e8e4ec332;hpb=d9b52143813e104eeee1e3d90061042230b7b5bf diff --git a/urcu/rculfqueue.h b/urcu/rculfqueue.h index 55f15f8..598fa50 100644 --- a/urcu/rculfqueue.h +++ b/urcu/rculfqueue.h @@ -23,44 +23,33 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include #include +#include #ifdef __cplusplus extern "C" { #endif -/* - * Lock-free RCU queue using reference counting. Enqueue and dequeue operations - * hold a RCU read lock to deal with cmpxchg ABA problem. This implementation - * keeps a dummy head node to ensure we can always update the queue locklessly. - * Given that this is a queue, the dummy head node must always advance as we - * dequeue entries. Therefore, we keep a reference count on each entry we are - * dequeueing, so they can be kept as dummy head node until the next dequeue, at - * which point their reference count will be decremented. - */ - struct cds_lfq_queue_rcu; struct cds_lfq_node_rcu { struct cds_lfq_node_rcu *next; - struct urcu_ref ref; - struct cds_lfq_queue_rcu *queue; - struct rcu_head rcu_head; + int dummy; }; struct cds_lfq_queue_rcu { struct cds_lfq_node_rcu *head, *tail; - struct cds_lfq_node_rcu init; /* Dummy initialization node */ - void (*release)(struct urcu_ref *ref); + void (*queue_call_rcu)(struct rcu_head *head, + void (*func)(struct rcu_head *head)); }; #ifdef _LGPL_SOURCE -#include +#include -#define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu +#define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu #define cds_lfq_init_rcu _cds_lfq_init_rcu +#define cds_lfq_destroy_rcu _cds_lfq_destroy_rcu #define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu #define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu @@ -68,7 +57,14 @@ struct cds_lfq_queue_rcu { extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node); extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q, - void (*release)(struct urcu_ref *ref)); + void queue_call_rcu(struct rcu_head *head, + void (*func)(struct rcu_head *head))); +/* + * The queue should be emptied before calling destroy. + * + * Return 0 on success, -EPERM if queue is not empty. + */ +extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q); /* * Should be called under rcu read lock critical section. @@ -79,16 +75,12 @@ extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q, /* * Should be called under rcu read lock critical section. * - * The entry returned by dequeue must be taken care of by doing a - * urcu_delayed_ref_put, which calls the release primitive after the - * reference count drops to zero _and_ a following grace period passes. - * - * 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). + * The caller must wait for a grace period to pass before freeing the returned + * node or modifying the cds_lfq_node_rcu structure. + * Returns NULL if queue is empty. */ -extern struct cds_lfq_node_rcu * -cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q); +extern +struct cds_lfq_node_rcu *cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q); #endif /* !_LGPL_SOURCE */