assert(!ret);
}
-static inline void ___cds_wfcq_append(struct cds_wfcq_head *head,
+static inline bool ___cds_wfcq_append(struct cds_wfcq_head *head,
struct cds_wfcq_tail *tail,
struct cds_wfcq_node *new_head,
struct cds_wfcq_node *new_tail)
* perspective.
*/
CMM_STORE_SHARED(old_tail->next, new_head);
+ /*
+ * Return false if queue was empty prior to adding the node,
+ * else return true.
+ */
+ return old_tail != &head->node;
}
/*
*
* Issues a full memory barrier before enqueue. No mutual exclusion is
* required.
+ *
+ * Returns false if the queue was empty prior to adding the node.
+ * Returns true otherwise.
*/
-static inline void _cds_wfcq_enqueue(struct cds_wfcq_head *head,
+static inline bool _cds_wfcq_enqueue(struct cds_wfcq_head *head,
struct cds_wfcq_tail *tail,
struct cds_wfcq_node *new_tail)
{
- ___cds_wfcq_append(head, tail, new_tail, new_tail);
+ return ___cds_wfcq_append(head, tail, new_tail, new_tail);
}
/*
return ___cds_wfcq_dequeue(head, tail, 0);
}
-static inline int
+static inline enum cds_wfcq_ret
___cds_wfcq_splice(
struct cds_wfcq_head *dest_q_head,
struct cds_wfcq_tail *dest_q_tail,
struct cds_wfcq_node *head, *tail;
if (_cds_wfcq_empty(src_q_head, src_q_tail))
- return 0;
+ return CDS_WFCQ_RET_SRC_EMPTY;
head = ___cds_wfcq_node_sync_next(&src_q_head->node, blocking);
if (head == CDS_WFCQ_WOULDBLOCK)
- return -1;
+ return CDS_WFCQ_RET_WOULDBLOCK;
_cds_wfcq_node_init(&src_q_head->node);
/*
* Append the spliced content of src_q into dest_q. Does not
* require mutual exclusion on dest_q (wait-free).
*/
- ___cds_wfcq_append(dest_q_head, dest_q_tail, head, tail);
- return 0;
+ if (___cds_wfcq_append(dest_q_head, dest_q_tail, head, tail))
+ return CDS_WFCQ_RET_DEST_NON_EMPTY;
+ else
+ return CDS_WFCQ_RET_DEST_EMPTY;
}
* dest_q must be already initialized.
* Dequeue/splice/iteration mutual exclusion for src_q should be ensured
* by the caller.
+ * Returns enum cds_wfcq_ret which indicates the state of the src or
+ * dest queue. Never returns CDS_WFCQ_RET_WOULDBLOCK.
*/
-static inline void
+static inline enum cds_wfcq_ret
___cds_wfcq_splice_blocking(
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)
{
- (void) ___cds_wfcq_splice(dest_q_head, dest_q_tail,
+ return ___cds_wfcq_splice(dest_q_head, dest_q_tail,
src_q_head, src_q_tail, 1);
}
/*
* __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.
+ * Same as __cds_wfcq_splice_blocking, but returns
+ * CDS_WFCQ_RET_WOULDBLOCK if it needs to block.
*/
-static inline int
+static inline enum cds_wfcq_ret
___cds_wfcq_splice_nonblocking(
struct cds_wfcq_head *dest_q_head,
struct cds_wfcq_tail *dest_q_tail,
* consistent, but no other memory ordering is ensured.
* Mutual exlusion with cds_wfcq_dequeue_blocking and dequeue lock is
* ensured.
+ * Returns enum cds_wfcq_ret which indicates the state of the src or
+ * dest queue. Never returns CDS_WFCQ_RET_WOULDBLOCK.
*/
-static inline void
+static inline enum cds_wfcq_ret
_cds_wfcq_splice_blocking(
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)
{
+ enum cds_wfcq_ret ret;
+
_cds_wfcq_dequeue_lock(src_q_head, src_q_tail);
- ___cds_wfcq_splice_blocking(dest_q_head, dest_q_tail,
+ ret = ___cds_wfcq_splice_blocking(dest_q_head, dest_q_tail,
src_q_head, src_q_tail);
_cds_wfcq_dequeue_unlock(src_q_head, src_q_tail);
+ return ret;
}
#ifdef __cplusplus
#define CDS_WFCQ_WOULDBLOCK ((void *) -1UL)
+enum cds_wfcq_ret {
+ CDS_WFCQ_RET_WOULDBLOCK = -1,
+ CDS_WFCQ_RET_DEST_EMPTY = 0,
+ CDS_WFCQ_RET_DEST_NON_EMPTY = 1,
+ CDS_WFCQ_RET_SRC_EMPTY = 2,
+};
+
struct cds_wfcq_node {
struct cds_wfcq_node *next;
};
*
* Issues a full memory barrier before enqueue. No mutual exclusion is
* required.
+ *
+ * Returns false if the queue was empty prior to adding the node.
+ * Returns true otherwise.
*/
-extern void cds_wfcq_enqueue(struct cds_wfcq_head *head,
+extern bool cds_wfcq_enqueue(struct cds_wfcq_head *head,
struct cds_wfcq_tail *tail,
struct cds_wfcq_node *node);
* consistent, but no other memory ordering is ensured.
* Mutual exlusion with cds_wfcq_dequeue_blocking and dequeue lock is
* ensured.
+ *
+ * Returns enum cds_wfcq_ret which indicates the state of the src or
+ * dest queue. Cannot block.
*/
-extern void cds_wfcq_splice_blocking(
+extern enum cds_wfcq_ret cds_wfcq_splice_blocking(
struct cds_wfcq_head *dest_q_head,
struct cds_wfcq_tail *dest_q_tail,
struct cds_wfcq_head *src_q_head,
* consistent, but no other memory ordering is ensured.
* Dequeue/splice/iteration mutual exclusion for src_q should be ensured
* by the caller.
+ *
+ * Returns enum cds_wfcq_ret which indicates the state of the src or
+ * dest queue. Cannot block.
*/
-extern void __cds_wfcq_splice_blocking(
+extern enum cds_wfcq_ret __cds_wfcq_splice_blocking(
struct cds_wfcq_head *dest_q_head,
struct cds_wfcq_tail *dest_q_tail,
struct cds_wfcq_head *src_q_head,
/*
* __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.
+ * Same as __cds_wfcq_splice_blocking, but returns
+ * CDS_WFCQ_RET_WOULDBLOCK if it needs to block.
*/
-extern int __cds_wfcq_splice_nonblocking(
+extern enum cds_wfcq_ret __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,
return _cds_wfcq_empty(head, tail);
}
-void cds_wfcq_enqueue(struct cds_wfcq_head *head,
+bool cds_wfcq_enqueue(struct cds_wfcq_head *head,
struct cds_wfcq_tail *tail,
struct cds_wfcq_node *node)
{
- _cds_wfcq_enqueue(head, tail, node);
+ return _cds_wfcq_enqueue(head, tail, node);
}
void cds_wfcq_dequeue_lock(struct cds_wfcq_head *head,
return _cds_wfcq_dequeue_blocking(head, tail);
}
-void cds_wfcq_splice_blocking(
+enum cds_wfcq_ret cds_wfcq_splice_blocking(
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_splice_blocking(dest_q_head, dest_q_tail,
+ return _cds_wfcq_splice_blocking(dest_q_head, dest_q_tail,
src_q_head, src_q_tail);
}
return ___cds_wfcq_dequeue_nonblocking(head, tail);
}
-void __cds_wfcq_splice_blocking(
+enum cds_wfcq_ret __cds_wfcq_splice_blocking(
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_splice_blocking(dest_q_head, dest_q_tail,
+ return ___cds_wfcq_splice_blocking(dest_q_head, dest_q_tail,
src_q_head, src_q_tail);
}
-int __cds_wfcq_splice_nonblocking(
+enum cds_wfcq_ret __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,