+#ifndef _URCU_RCULFSTACK_H
+#define _URCU_RCULFSTACK_H
+
/*
* rculfstack.h
*
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#if (!defined(_GNU_SOURCE) && !defined(_LGPL_SOURCE))
-#error "Dynamic loader LGPL wrappers not implemented yet"
+#ifdef __cplusplus
+extern "C" {
#endif
-struct rcu_lfs_node {
- struct rcu_lfs_node *next;
+struct cds_lfs_node_rcu {
+ struct cds_lfs_node_rcu *next;
};
-struct rcu_lfs_stack {
- struct rcu_lfs_node *head;
+struct cds_lfs_stack_rcu {
+ struct cds_lfs_node_rcu *head;
};
-void rcu_lfs_node_init(struct rcu_lfs_node *node)
-{
-}
+#ifdef _LGPL_SOURCE
-void rcu_lfs_init(struct rcu_lfs_stack *s)
-{
- s->head = NULL;
-}
+#include <urcu/static/rculfstack.h>
-void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
-{
- rcu_read_lock();
- for (;;) {
- struct rcu_lfs_node *head = rcu_dereference(s->head);
-
- node->next = head;
- /*
- * uatomic_cmpxchg() implicit memory barrier orders earlier
- * stores to node before publication.
- */
- if (uatomic_cmpxchg(&s->head, head, node) == head) {
- rcu_read_unlock();
- return;
- } else {
- /* Failure to prepend. Retry. */
- continue;
- }
- }
-}
+#define cds_lfs_node_init_rcu_qsbr _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu_qsbr _cds_lfs_init_rcu
+#define cds_lfs_push_rcu_qsbr _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu_qsbr _cds_lfs_pop_rcu
+
+#define cds_lfs_node_init_rcu_bp _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu_bp _cds_lfs_init_rcu
+#define cds_lfs_push_rcu_bp _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu_bp _cds_lfs_pop_rcu
+
+#define cds_lfs_node_init_rcu_memb _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu_memb _cds_lfs_init_rcu
+#define cds_lfs_push_rcu_memb _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu_memb _cds_lfs_pop_rcu
+
+#define cds_lfs_node_init_rcu_mb _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu_mb _cds_lfs_init_rcu
+#define cds_lfs_push_rcu_mb _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu_mb _cds_lfs_pop_rcu
+
+#define cds_lfs_node_init_rcu_sig _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu_sig _cds_lfs_init_rcu
+#define cds_lfs_push_rcu_sig _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu_sig _cds_lfs_pop_rcu
+
+#else /* !_LGPL_SOURCE */
-struct rcu_lfs_node *
-rcu_lfs_pop(struct rcu_lfs_stack *s)
-{
- rcu_read_lock();
- for (;;) {
- struct rcu_lfs_node *head = rcu_dereference(s->head);
-
- if (head) {
- struct rcu_lfs_node *next = rcu_dereference(head->next);
-
- if (uatomic_cmpxchg(&s->head, head, next) == head) {
- rcu_read_unlock();
- return head;
- } else {
- /* Concurrent modification. Retry. */
- continue;
- }
- } else {
- /* Empty stack */
- rcu_read_unlock();
- return NULL;
- }
- }
+extern void cds_lfs_node_init_rcu(struct cds_lfs_node_rcu *node);
+extern void cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s);
+extern void cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *node);
+
+/*
+ * Acts as a RCU reader.
+ *
+ * The caller must wait for a grace period to pass before freeing the returned
+ * node or modifying the cds_lfs_node_rcu structure.
+ * Returns NULL if stack is empty.
+ */
+extern struct cds_lfs_node_rcu *cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s);
+
+#endif /* !_LGPL_SOURCE */
+
+#ifdef __cplusplus
}
+#endif
+
+#endif /* _URCU_RCULFSTACK_H */