urcu/uatomic_generic.h urcu/arch_generic.h urcu/wfstack.h \
urcu/wfqueue.h urcu/rculfstack.h urcu/rculfqueue.h \
urcu/wfqueue-static.h urcu/wfstack-static.h \
- urcu/rculfqueue-static.h
+ urcu/rculfqueue-static.h urcu/rculfstack-static.h
nobase_nodist_include_HEADERS = urcu/arch.h urcu/uatomic_arch.h urcu/config.h
EXTRA_DIST = $(top_srcdir)/urcu/arch_*.h $(top_srcdir)/urcu/uatomic_arch_*.h \
lib_LTLIBRARIES = liburcu.la liburcu-qsbr.la liburcu-mb.la liburcu-signal.la \
liburcu-bp.la liburcu-defer.la libwfqueue.la libwfstack.la \
- librculfqueue.la
+ librculfqueue.la librculfstack.la
liburcu_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
libwfqueue_la_SOURCES = wfqueue.c $(COMPAT)
libwfstack_la_SOURCES = wfstack.c $(COMPAT)
librculfqueue_la_SOURCES = rculfqueue.c $(COMPAT)
+librculfstack_la_SOURCES = rculfstack.c $(COMPAT)
--- /dev/null
+/*
+ * rculfstack.c
+ *
+ * Userspace RCU library - Lock-Free RCU Stack
+ *
+ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Use the urcu symbols to select the appropriate rcu flavor at link time */
+#include "urcu.h"
+/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
+#include "urcu/rculfstack.h"
+#include "urcu/rculfstack-static.h"
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ */
+
+
+void rcu_lfs_node_init(struct rcu_lfs_node *node)
+{
+ _rcu_lfs_node_init(node);
+}
+
+void rcu_lfs_init(struct rcu_lfs_stack *s)
+{
+ _rcu_lfs_init(s);
+}
+
+void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
+{
+ _rcu_lfs_push(s, node);
+}
+
+struct rcu_lfs_node *rcu_lfs_pop(struct rcu_lfs_stack *s)
+{
+ return _rcu_lfs_pop(s);
+}
test_urcu_bp test_urcu_bp_dynamic_link test_cycles_per_loop \
test_urcu_lfq test_urcu_wfq test_urcu_lfs test_urcu_wfs \
test_urcu_wfq_dynlink test_urcu_wfs_dynlink \
- test_urcu_lfq_dynlink
+ test_urcu_lfq_dynlink test_urcu_lfs_dynlink
noinst_HEADERS = rcutorture.h
if COMPAT_ARCH
WFQUEUE_LIB=$(top_builddir)/libwfqueue.la
WFSTACK_LIB=$(top_builddir)/libwfstack.la
RCULFQUEUE_LIB=$(top_builddir)/librculfqueue.la
+RCULFSTACK_LIB=$(top_builddir)/librculfstack.la
EXTRA_DIST = $(top_srcdir)/tests/api_*.h
test_urcu_wfq_dynlink_LDADD = $(WFQUEUE_LIB)
test_urcu_lfs_SOURCES = test_urcu_lfs.c $(URCU_DEFER)
+test_urcu_lfs_dynlink_SOURCES = test_urcu_lfs.c $(URCU_DEFER)
+test_urcu_lfs_dynlink_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
+test_urcu_lfs_dynlink_LDADD = $(RCULFSTACK_LIB)
test_urcu_wfs_SOURCES = test_urcu_wfs.c
test_urcu_wfs_dynlink_SOURCES = test_urcu_wfs.c
--- /dev/null
+#ifndef _URCU_RCULFSTACK_STATIC_H
+#define _URCU_RCULFSTACK_STATIC_H
+
+/*
+ * rculfstack-static.h
+ *
+ * Userspace RCU library - Lock-Free RCU Stack
+ *
+ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * TO BE INCLUDED ONLY IN LGPL-COMPATIBLE CODE. See rculfstack.h for linking
+ * dynamically with the userspace rcu library.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <urcu/uatomic_arch.h>
+/* A urcu implementation header should be already included. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _rcu_lfs_node_init(struct rcu_lfs_node *node)
+{
+}
+
+void _rcu_lfs_init(struct rcu_lfs_stack *s)
+{
+ s->head = NULL;
+}
+
+void _rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
+{
+ for (;;) {
+ struct rcu_lfs_node *head;
+
+ rcu_read_lock();
+ 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. */
+ rcu_read_unlock();
+ continue;
+ }
+ }
+}
+
+/*
+ * The caller must wait for a grace period to pass before freeing the returned
+ * node or modifying the rcu_lfs_node structure.
+ * Returns NULL if stack is empty.
+ */
+struct rcu_lfs_node *
+_rcu_lfs_pop(struct rcu_lfs_stack *s)
+{
+ for (;;) {
+ struct rcu_lfs_node *head;
+
+ rcu_read_lock();
+ 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. */
+ rcu_read_unlock();
+ continue;
+ }
+ } else {
+ /* Empty stack */
+ rcu_read_unlock();
+ return NULL;
+ }
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_RCULFSTACK_STATIC_H */
extern "C" {
#endif
-#if (!defined(_GNU_SOURCE) && !defined(_LGPL_SOURCE))
-#error "Dynamic loader LGPL wrappers not implemented yet"
-#endif
-
struct rcu_lfs_node {
struct rcu_lfs_node *next;
};
struct rcu_lfs_node *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/rculfstack-static.h>
-void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node)
-{
- for (;;) {
- struct rcu_lfs_node *head;
+#define rcu_lfs_node_init _rcu_lfs_node_init
+#define rcu_lfs_init _rcu_lfs_init
+#define rcu_lfs_push _rcu_lfs_push
+#define rcu_lfs_pop _rcu_lfs_pop
- rcu_read_lock();
- 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. */
- rcu_read_unlock();
- continue;
- }
- }
-}
+#else /* !_LGPL_SOURCE */
+
+extern void rcu_lfs_node_init(struct rcu_lfs_node *node);
+extern void rcu_lfs_init(struct rcu_lfs_stack *s);
+extern void rcu_lfs_push(struct rcu_lfs_stack *s, struct rcu_lfs_node *node);
/*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the rcu_lfs_node structure.
* Returns NULL if stack is empty.
*/
-struct rcu_lfs_node *
-rcu_lfs_pop(struct rcu_lfs_stack *s)
-{
- for (;;) {
- struct rcu_lfs_node *head;
+extern struct rcu_lfs_node *rcu_lfs_pop(struct rcu_lfs_stack *s);
- rcu_read_lock();
- 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. */
- rcu_read_unlock();
- continue;
- }
- } else {
- /* Empty stack */
- rcu_read_unlock();
- return NULL;
- }
- }
-}
+#endif /* !_LGPL_SOURCE */
#ifdef __cplusplus
}