#define _URCU_WFSTACK_H
/*
- * rcuwfstack.h
+ * wfstack.h
*
* Userspace RCU library - Stack with Wait-Free push, Blocking pop.
*
extern "C" {
#endif
-#if (!defined(_GNU_SOURCE) && !defined(_LGPL_SOURCE))
-#error "Dynamic loader LGPL wrappers not implemented yet"
-#endif
-
-#define WF_STACK_END ((void *)0x1UL)
-#define WFS_ADAPT_ATTEMPTS 10 /* Retry if being set */
-#define WFS_WAIT 10 /* Wait 10 ms if being set */
-
-struct wfs_node {
- struct wfs_node *next;
+struct cds_wfs_node {
+ struct cds_wfs_node *next;
};
-struct wfs_stack {
- struct wfs_node *head;
+struct cds_wfs_stack {
+ struct cds_wfs_node *head;
pthread_mutex_t lock;
};
-void wfs_node_init(struct wfs_node *node)
-{
- node->next = NULL;
-}
+#ifdef _LGPL_SOURCE
-void wfs_init(struct wfs_stack *s)
-{
- int ret;
+#include <urcu/static/wfstack.h>
- s->head = WF_STACK_END;
- ret = pthread_mutex_init(&s->lock, NULL);
- assert(!ret);
-}
+#define cds_wfs_node_init _cds_wfs_node_init
+#define cds_wfs_init _cds_wfs_init
+#define cds_wfs_push _cds_wfs_push
+#define __cds_wfs_pop_blocking ___cds_wfs_pop_blocking
+#define cds_wfs_pop_blocking _cds_wfs_pop_blocking
-void wfs_push(struct wfs_stack *s, struct wfs_node *node)
-{
- struct wfs_node *old_head;
+#else /* !_LGPL_SOURCE */
- assert(node->next == NULL);
- /*
- * uatomic_xchg() implicit memory barrier orders earlier stores to node
- * (setting it to NULL) before publication.
- */
- old_head = uatomic_xchg(&s->head, node);
- /*
- * At this point, dequeuers see a NULL node->next, they should busy-wait
- * until node->next is set to old_head.
- */
- STORE_SHARED(node->next, old_head);
-}
+extern void cds_wfs_node_init(struct cds_wfs_node *node);
+extern void cds_wfs_init(struct cds_wfs_stack *s);
+extern void cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node);
+/* __cds_wfs_pop_blocking: caller ensures mutual exclusion between pops */
+extern struct cds_wfs_node *__cds_wfs_pop_blocking(struct cds_wfs_stack *s);
+extern struct cds_wfs_node *cds_wfs_pop_blocking(struct cds_wfs_stack *s);
-/*
- * Returns NULL if stack is empty.
- */
-struct wfs_node *
-__wfs_pop_blocking(struct wfs_stack *s)
-{
- struct wfs_node *head, *next;
- int attempt = 0;
-
-retry:
- head = LOAD_SHARED(s->head);
- if (head == WF_STACK_END)
- return NULL;
- /*
- * Adaptative busy-looping waiting for push to complete.
- */
- while ((next = LOAD_SHARED(head->next)) == NULL) {
- if (++attempt >= WFS_ADAPT_ATTEMPTS) {
- poll(NULL, 0, WFS_WAIT); /* Wait for 10ms */
- attempt = 0;
- } else
- cpu_relax();
- }
- if (uatomic_cmpxchg(&s->head, head, next) == head)
- return head;
- else
- goto retry; /* Concurrent modification. Retry. */
-}
-
-struct wfs_node *
-wfs_pop_blocking(struct wfs_stack *s)
-{
- struct wfs_node *retnode;
- int ret;
-
- ret = pthread_mutex_lock(&s->lock);
- assert(!ret);
- retnode = __wfs_pop_blocking(s);
- ret = pthread_mutex_unlock(&s->lock);
- assert(!ret);
- return retnode;
-}
+#endif /* !_LGPL_SOURCE */
#ifdef __cplusplus
}