X-Git-Url: https://git.liburcu.org/?p=urcu.git;a=blobdiff_plain;f=urcu%2Fwfcqueue.h;h=fe2862e28469051966c861c7cd3964772ef1db8a;hp=501120b2b36554ce95f43285be7c4843e97b36f7;hb=47215721095cf47e110f113d26f9e61514405a4c;hpb=f94061a3df4c9eab9ac869a19e4228de54771fcb diff --git a/urcu/wfcqueue.h b/urcu/wfcqueue.h index 501120b..fe2862e 100644 --- a/urcu/wfcqueue.h +++ b/urcu/wfcqueue.h @@ -2,7 +2,7 @@ #define _URCU_WFCQUEUE_H /* - * wfcqueue.h + * urcu/wfcqueue.h * * Userspace RCU library - Concurrent Queue with Wait-Free Enqueue/Blocking Dequeue * @@ -37,10 +37,14 @@ extern "C" { /* * Concurrent queue with wait-free enqueue/blocking dequeue. * - * Inspired from half-wait-free/half-blocking queue implementation done by - * Paul E. McKenney. + * This queue has been designed and implemented collaboratively by + * Mathieu Desnoyers and Lai Jiangshan. Inspired from + * half-wait-free/half-blocking queue implementation done by Paul E. + * McKenney. */ +#define CDS_WFCQ_WOULDBLOCK ((void *) -1UL) + struct cds_wfcq_node { struct cds_wfcq_node *next; }; @@ -84,6 +88,16 @@ struct cds_wfcq_tail { #define __cds_wfcq_first_blocking ___cds_wfcq_first_blocking #define __cds_wfcq_next_blocking ___cds_wfcq_next_blocking +/* + * Locking ensured by caller by holding cds_wfcq_dequeue_lock(). + * Non-blocking: deque, first, next return CDS_WFCQ_WOULDBLOCK if they + * need to block. splice returns nonzero if it needs to block. + */ +#define __cds_wfcq_dequeue_nonblocking ___cds_wfcq_dequeue_nonblocking +#define __cds_wfcq_splice_nonblocking ___cds_wfcq_splice_nonblocking +#define __cds_wfcq_first_nonblocking ___cds_wfcq_first_nonblocking +#define __cds_wfcq_next_nonblocking ___cds_wfcq_next_nonblocking + #else /* !_LGPL_SOURCE */ /* @@ -100,6 +114,10 @@ struct cds_wfcq_tail { * * For convenience, cds_wfcq_dequeue_blocking() and * cds_wfcq_splice_blocking() hold the dequeue lock. + * + * Besides locking, mutual exclusion of dequeue, splice and iteration + * can be ensured by performing all of those operations from a single + * thread, without requiring any lock. */ /* @@ -149,7 +167,8 @@ extern void cds_wfcq_enqueue(struct cds_wfcq_head *head, * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. * It is valid to reuse and free a dequeued node immediately. - * Mutual exlusion with dequeuers is ensured internally. + * Mutual exlusion with cds_wfcq_dequeue_blocking and dequeue lock is + * ensured. */ extern struct cds_wfcq_node *cds_wfcq_dequeue_blocking( struct cds_wfcq_head *head, @@ -162,7 +181,8 @@ extern struct cds_wfcq_node *cds_wfcq_dequeue_blocking( * dest_q must be already initialized. * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Mutual exlusion with dequeuers is ensured internally. + * Mutual exlusion with cds_wfcq_dequeue_blocking and dequeue lock is + * ensured. */ extern void cds_wfcq_splice_blocking( struct cds_wfcq_head *dest_q_head, @@ -171,17 +191,28 @@ extern void cds_wfcq_splice_blocking( struct cds_wfcq_tail *src_q_tail); /* - * __cds_wfcq_dequeue_blocking: + * __cds_wfcq_dequeue_blocking: dequeue a node from a wait-free queue. * * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. * It is valid to reuse and free a dequeued node immediately. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. */ extern struct cds_wfcq_node *__cds_wfcq_dequeue_blocking( struct cds_wfcq_head *head, struct cds_wfcq_tail *tail); +/* + * __cds_wfcq_dequeue_nonblocking: dequeue a node from a wait-free queue. + * + * Same as __cds_wfcq_dequeue_blocking, but returns CDS_WFCQ_WOULDBLOCK + * if it needs to block. + */ +extern struct cds_wfcq_node *__cds_wfcq_dequeue_nonblocking( + struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail); + /* * __cds_wfcq_splice_blocking: enqueue all src_q nodes at the end of dest_q. * @@ -189,7 +220,8 @@ extern struct cds_wfcq_node *__cds_wfcq_dequeue_blocking( * dest_q must be already initialized. * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion for src_q should be ensured + * by the caller. */ extern void __cds_wfcq_splice_blocking( struct cds_wfcq_head *dest_q_head, @@ -197,12 +229,25 @@ extern void __cds_wfcq_splice_blocking( struct cds_wfcq_head *src_q_head, struct cds_wfcq_tail *src_q_tail); +/* + * __cds_wfcq_splice_nonblocking: enqueue all src_q nodes at the end of dest_q. + * + * Same as __cds_wfcq_splice_blocking, but returns nonzero if it needs to + * block. + */ +extern int __cds_wfcq_splice_nonblocking( + struct cds_wfcq_head *dest_q_head, + struct cds_wfcq_tail *dest_q_tail, + struct cds_wfcq_head *src_q_head, + struct cds_wfcq_tail *src_q_tail); + /* * __cds_wfcq_first_blocking: get first node of a queue, without dequeuing. * * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. * * Used by for-like iteration macros: * __cds_wfcq_for_each_blocking() @@ -212,12 +257,23 @@ extern struct cds_wfcq_node *__cds_wfcq_first_blocking( struct cds_wfcq_head *head, struct cds_wfcq_tail *tail); +/* + * __cds_wfcq_first_nonblocking: get first node of a queue, without dequeuing. + * + * Same as __cds_wfcq_first_blocking, but returns CDS_WFCQ_WOULDBLOCK if + * it needs to block. + */ +extern struct cds_wfcq_node *__cds_wfcq_first_nonblocking( + struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail); + /* * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing. * * Content written into the node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. * * Used by for-like iteration macros: * __cds_wfcq_for_each_blocking() @@ -228,6 +284,17 @@ extern struct cds_wfcq_node *__cds_wfcq_next_blocking( struct cds_wfcq_tail *tail, struct cds_wfcq_node *node); +/* + * __cds_wfcq_next_blocking: get next node of a queue, without dequeuing. + * + * Same as __cds_wfcq_next_blocking, but returns CDS_WFCQ_WOULDBLOCK if + * it needs to block. + */ +extern struct cds_wfcq_node *__cds_wfcq_next_nonblocking( + struct cds_wfcq_head *head, + struct cds_wfcq_tail *tail, + struct cds_wfcq_node *node); + #endif /* !_LGPL_SOURCE */ /* @@ -239,7 +306,8 @@ extern struct cds_wfcq_node *__cds_wfcq_next_blocking( * * Content written into each node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. */ #define __cds_wfcq_for_each_blocking(head, tail, node) \ for (node = __cds_wfcq_first_blocking(head, tail); \ @@ -257,7 +325,8 @@ extern struct cds_wfcq_node *__cds_wfcq_next_blocking( * * Content written into each node before enqueue is guaranteed to be * consistent, but no other memory ordering is ensured. - * Should be called with cds_wfcq_dequeue_lock() held. + * Dequeue/splice/iteration mutual exclusion should be ensured by the + * caller. */ #define __cds_wfcq_for_each_blocking_safe(head, tail, node, n) \ for (node = __cds_wfcq_first_blocking(head, tail), \