COMPAT+=compat_futex.c
endif
-lib_LTLIBRARIES = liburcu-cds-common.la \
+lib_LTLIBRARIES = liburcu-common.la \
liburcu.la liburcu-qsbr.la \
liburcu-mb.la liburcu-signal.la liburcu-bp.la \
- liburcu-cds.la liburcu-cds-qsbr.la \
- liburcu-cds-mb.la liburcu-cds-signal.la liburcu-cds-bp.la \
- liburcu-rbtree.la
+ liburcu-cds.la liburcu-rbtree.la
-liburcu_cds_common_la_SOURCES = wfqueue.c wfstack.c $(COMPAT)
+#
+# liburcu-common contains wait-free queues (needed by call_rcu) as well
+# as futex fallbacks.
+#
+liburcu_common_la_SOURCES = wfqueue.c wfstack.c $(COMPAT)
liburcu_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
-liburcu_cds_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
+liburcu_la_LIBADD = liburcu-common.la
liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c $(COMPAT)
-liburcu_cds_qsbr_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
-liburcu_cds_qsbr_la_CFLAGS = -DRCU_QSBR
+liburcu_qsbr_la_LIBADD = liburcu-common.la
liburcu_mb_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
liburcu_mb_la_CFLAGS = -DRCU_MB
-liburcu_cds_mb_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
-liburcu_cds_mb_la_CFLAGS = -DRCU_MB
+liburcu_mb_la_LIBADD = liburcu-common.la
liburcu_signal_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
liburcu_signal_la_CFLAGS = -DRCU_SIGNAL
-liburcu_cds_signal_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
-liburcu_cds_signal_la_CFLAGS = -DRCU_SIGNAL
+liburcu_signal_la_LIBADD = liburcu-common.la
liburcu_bp_la_SOURCES = urcu-bp.c urcu-pointer.c $(COMPAT)
-liburcu_cds_bp_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
-liburcu_cds_bp_la_CFLAGS = -DRCU_BP
+liburcu_bp_la_LIBADD = liburcu-common.la
+
+liburcu_cds_la_SOURCES = rculfqueue.c rculfstack.c $(COMPAT)
+liburcu_cds_la_LIBADD = liburcu-common.la
liburcu_rbtree_la_SOURCES = urcu-rbtree.c $(COMPAT)
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#define _LGPL_SOURCE
-
-#ifdef RCU_QSBR
-# include "urcu-qsbr.h"
-#elif defined(RCU_BP)
-# include "urcu-bp.h"
-#else
-# include "urcu.h"
-#endif
-
-#undef _LGPL_SOURCE
/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
+#undef _LGPL_SOURCE
#include "urcu/rculfqueue.h"
+#define _LGPL_SOURCE
#include "urcu/static/rculfqueue.h"
/*
_cds_lfq_node_init_rcu(node);
}
-void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
+void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q,
+ void queue_call_rcu(struct rcu_head *head,
+ void (*func)(struct rcu_head *head)))
{
- _cds_lfq_init_rcu(q);
+ _cds_lfq_init_rcu(q, queue_call_rcu);
}
int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q)
* 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 */
-#define _LGPL_SOURCE
-
-#ifdef RCU_QSBR
-# include "urcu-qsbr.h"
-#elif defined(RCU_BP)
-# include "urcu-bp.h"
-#else
-# include "urcu.h"
-#endif
-
-#undef _LGPL_SOURCE
/* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
+#undef _LGPL_SOURCE
#include "urcu/rculfstack.h"
+#define _LGPL_SOURCE
#include "urcu/static/rculfstack.h"
/*
_cds_lfs_init_rcu(s);
}
-void cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *node)
+int cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s,
+ struct cds_lfs_node_rcu *node)
{
- _cds_lfs_push_rcu(s, node);
+ return _cds_lfs_push_rcu(s, node);
}
struct cds_lfs_node_rcu *cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s)
URCU_BP=$(top_srcdir)/urcu-bp.c $(top_srcdir)/urcu-pointer.c $(top_srcdir)/wfqueue.c $(COMPAT)
URCU_DEFER=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(top_srcdir)/wfqueue.c $(COMPAT)
+URCU_COMMON_LIB=$(top_builddir)/liburcu-common.la
URCU_LIB=$(top_builddir)/liburcu.la
-URCU_CDS_LIB=$(top_builddir)/liburcu-cds.la
URCU_QSBR_LIB=$(top_builddir)/liburcu-qsbr.la
-URCU_CDS_QSBR_LIB=$(top_builddir)/liburcu-cds-qsbr.la
URCU_MB_LIB=$(top_builddir)/liburcu-mb.la
-URCU_CDS_MB_LIB=$(top_builddir)/liburcu-cds-mb.la
URCU_SIGNAL_LIB=$(top_builddir)/liburcu-signal.la
-URCU_CDS_SIGNAL_LIB=$(top_builddir)/liburcu-cds-signal.la
URCU_BP_LIB=$(top_builddir)/liburcu-bp.la
-URCU_CDS_BP_LIB=$(top_builddir)/liburcu-cds-bp.la
-URCU_CDS_COMMON_LIB=$(top_builddir)/liburcu-cds-common.la
+URCU_CDS_LIB=$(top_builddir)/liburcu-cds.la
URCU_RBTREE=$(URCU) $(top_srcdir)/urcu-rbtree.c
test_urcu_lfq_dynlink_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
test_urcu_lfq_dynlink_LDADD = $(URCU_CDS_LIB)
-test_urcu_wfq_SOURCES = test_urcu_wfq.c $(URCU_CDS_COMMON_LIB) $(COMPAT)
+test_urcu_wfq_SOURCES = test_urcu_wfq.c $(URCU_COMMON_LIB)
test_urcu_wfq_dynlink_SOURCES = test_urcu_wfq.c
test_urcu_wfq_dynlink_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
-test_urcu_wfq_dynlink_LDADD = $(URCU_CDS_COMMON_LIB)
+test_urcu_wfq_dynlink_LDADD = $(URCU_COMMON_LIB)
test_urcu_lfs_SOURCES = test_urcu_lfs.c $(URCU_CDS_LIB) $(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 = $(URCU_CDS_LIB)
-test_urcu_wfs_SOURCES = test_urcu_wfs.c $(URCU_CDS_COMMON_LIB) $(COMPAT)
+test_urcu_wfs_SOURCES = test_urcu_wfs.c $(URCU_COMMON_LIB)
test_urcu_wfs_dynlink_SOURCES = test_urcu_wfs.c
test_urcu_wfs_dynlink_CFLAGS = -DDYNAMIC_LINK_TEST $(AM_CFLAGS)
-test_urcu_wfs_dynlink_LDADD = $(URCU_CDS_COMMON_LIB)
+test_urcu_wfs_dynlink_LDADD = $(URCU_COMMON_LIB)
test_urcu_rbtree_SOURCES = test_urcu_rbtree.c $(URCU_RBTREE)
if (!node)
goto fail;
cds_lfq_node_init_rcu(node);
+ rcu_read_lock();
cds_lfq_enqueue_rcu(&q, node);
+ rcu_read_unlock();
nr_successful_enqueues++;
if (unlikely(wdelay))
for (;;) {
struct cds_lfq_node_rcu *node;
+ rcu_read_lock();
node = cds_lfq_dequeue_rcu(&q);
+ rcu_read_unlock();
+
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
struct cds_lfq_node_rcu *node;
do {
+ rcu_read_lock();
node = cds_lfq_dequeue_rcu(q);
+ rcu_read_unlock();
if (node) {
free(node); /* no more concurrent access */
(*nr_dequeues)++;
tid_dequeuer = malloc(sizeof(*tid_dequeuer) * nr_dequeuers);
count_enqueuer = malloc(2 * sizeof(*count_enqueuer) * nr_enqueuers);
count_dequeuer = malloc(2 * sizeof(*count_dequeuer) * nr_dequeuers);
- cds_lfq_init_rcu(&q);
+ cds_lfq_init_rcu(&q, call_rcu);
next_aff = 0;
for (;;) {
struct cds_lfs_node_rcu *node;
+ rcu_read_lock();
node = cds_lfs_pop_rcu(&s);
+ rcu_read_unlock();
if (node) {
defer_rcu(free, node);
nr_successful_dequeues++;
assert(!ret);
}
-void rcu_bp_exit()
+void rcu_bp_exit(void)
{
- munmap(registry_arena.p, registry_arena.len);
+ if (registry_arena.p)
+ munmap(registry_arena.p, registry_arena.len);
}
/*
#define CAA_BITS_PER_LONG 32
#endif
-#define caa_container_of(ptr, type, member) \
+/*
+ * caa_container_of - Get the address of an object containing a field.
+ *
+ * @ptr: pointer to the field.
+ * @type: type of the object.
+ * @member: name of the field within the object.
+ */
+#define caa_container_of(ptr, type, member) \
({ \
- const typeof(((type *)NULL)->member) * __ptr = (ptr); \
+ const typeof(((type *) NULL)->member) * __ptr = (ptr); \
(type *)((char *)__ptr - offsetof(type, member)); \
})
#define CAA_BUILD_BUG_ON_ZERO(cond) (sizeof(struct { int:-!!(cond); }))
#define CAA_BUILD_BUG_ON(cond) ((void)BUILD_BUG_ON_ZERO(cond))
+/*
+ * __rcu is an annotation that documents RCU pointer accesses that need
+ * to be protected by a read-side critical section. Eventually, a static
+ * checker will be able to use this annotation to detect incorrect RCU
+ * usage.
+ */
+#define __rcu
+
#endif /* _URCU_COMPILER_H */
-/* Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
- The GNU C 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.
-
- The GNU C 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 the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+/*
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ * (originally part of the GNU C Library)
+ * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+ *
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ * Conversion to RCU list.
+ * Copyright (C) 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
+ */
#ifndef _CDS_LIST_H
#define _CDS_LIST_H 1
#define rcu_defer_barrier rcu_defer_barrier_bp
#define rcu_defer_barrier_thread rcu_defer_barrier_thread_bp
-/* Concurrent Data Structures */
-#define cds_lfq_node_init_rcu cds_lfq_node_init_rcu_bp
-#define cds_lfq_init_rcu cds_lfq_init_rcu_bp
-#define cds_lfq_destroy_rcu cds_lfq_destroy_rcu_bp
-#define cds_lfq_enqueue_rcu cds_lfq_enqueue_rcu_bp
-#define cds_lfq_dequeue_rcu cds_lfq_dequeue_rcu_bp
-
-#define cds_lfs_node_init_rcu cds_lfs_node_init_rcu_bp
-#define cds_lfs_init_rcu cds_lfs_init_rcu_bp
-#define cds_lfs_push_rcu cds_lfs_push_rcu_bp
-#define cds_lfs_pop_rcu cds_lfs_pop_rcu_bp
-
#endif /* _URCU_BP_MAP_H */
#define rcu_defer_barrier rcu_defer_barrier_qsbr
#define rcu_defer_barrier_thread rcu_defer_barrier_thread_qsbr
-/* Concurrent Data Structures */
-#define cds_lfq_node_init_rcu cds_lfq_node_init_rcu_qsbr
-#define cds_lfq_init_rcu cds_lfq_init_rcu_qsbr
-#define cds_lfq_destroy_rcu cds_lfq_destroy_rcu_qsbr
-#define cds_lfq_enqueue_rcu cds_lfq_enqueue_rcu_qsbr
-#define cds_lfq_dequeue_rcu cds_lfq_dequeue_rcu_qsbr
-
-#define cds_lfs_node_init_rcu cds_lfs_node_init_rcu_qsbr
-#define cds_lfs_init_rcu cds_lfs_init_rcu_qsbr
-#define cds_lfs_push_rcu cds_lfs_push_rcu_qsbr
-#define cds_lfs_pop_rcu cds_lfs_pop_rcu_qsbr
-
#endif /* _URCU_QSBR_MAP_H */
#define rcu_defer_barrier rcu_defer_barrier_memb
#define rcu_defer_barrier_thread rcu_defer_barrier_thread_memb
-/* Concurrent Data Structures */
-#define cds_lfq_node_init_rcu cds_lfq_node_init_rcu_memb
-#define cds_lfq_init_rcu cds_lfq_init_rcu_memb
-#define cds_lfq_destroy_rcu cds_lfq_destroy_rcu_memb
-#define cds_lfq_enqueue_rcu cds_lfq_enqueue_rcu_memb
-#define cds_lfq_dequeue_rcu cds_lfq_dequeue_rcu_memb
-
-#define cds_lfs_node_init_rcu cds_lfs_node_init_rcu_memb
-#define cds_lfs_init_rcu cds_lfs_init_rcu_memb
-#define cds_lfs_push_rcu cds_lfs_push_rcu_memb
-#define cds_lfs_pop_rcu cds_lfs_pop_rcu_memb
-
#elif defined(RCU_SIGNAL)
#define rcu_read_lock rcu_read_lock_sig
#define rcu_defer_barrier rcu_defer_barrier_sig
#define rcu_defer_barrier_thread rcu_defer_barrier_thread_sig
-/* Concurrent Data Structures */
-#define cds_lfq_node_init_rcu cds_lfq_node_init_rcu_sig
-#define cds_lfq_init_rcu cds_lfq_init_rcu_sig
-#define cds_lfq_destroy_rcu cds_lfq_destroy_rcu_sig
-#define cds_lfq_enqueue_rcu cds_lfq_enqueue_rcu_sig
-#define cds_lfq_dequeue_rcu cds_lfq_dequeue_rcu_sig
-
-#define cds_lfs_node_init_rcu cds_lfs_node_init_rcu_sig
-#define cds_lfs_init_rcu cds_lfs_init_rcu_sig
-#define cds_lfs_push_rcu cds_lfs_push_rcu_sig
-#define cds_lfs_pop_rcu cds_lfs_pop_rcu_sig
-
#elif defined(RCU_MB)
#define rcu_read_lock rcu_read_lock_mb
#define rcu_defer_barrier rcu_defer_barrier_mb
#define rcu_defer_barrier_thread rcu_defer_barrier_thread_mb
-/* Concurrent Data Structures */
-#define cds_lfq_node_init_rcu cds_lfq_node_init_rcu_mb
-#define cds_lfq_init_rcu cds_lfq_init_rcu_mb
-#define cds_lfq_destroy_rcu cds_lfq_destroy_rcu_mb
-#define cds_lfq_enqueue_rcu cds_lfq_enqueue_rcu_mb
-#define cds_lfq_dequeue_rcu cds_lfq_dequeue_rcu_mb
-
-#define cds_lfs_node_init_rcu cds_lfs_node_init_rcu_mb
-#define cds_lfs_init_rcu cds_lfs_init_rcu_mb
-#define cds_lfs_push_rcu cds_lfs_push_rcu_mb
-#define cds_lfs_pop_rcu cds_lfs_pop_rcu_mb
-
#else
#error "Undefined selection"
-/* Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
- Copyright (C) 2009 Pierre-Marc Fournier
- Conversion to RCU list.
- Copyright (C) 2010 Mathieu Desnoyers
-
- The GNU C 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.
-
- The GNU C 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 the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+/*
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ * (originally part of the GNU C Library)
+ * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+ *
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ * Conversion to RCU list.
+ * Copyright (C) 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
+ */
#ifndef _URCU_RCUHLIST_H
#define _URCU_RCUHLIST_H
struct cds_lfq_queue_rcu {
struct cds_lfq_node_rcu *head, *tail;
+ void (*queue_call_rcu)(struct rcu_head *head,
+ void (*func)(struct rcu_head *head));
};
#ifdef _LGPL_SOURCE
#include <urcu/static/rculfqueue.h>
-#define cds_lfq_node_init_rcu_qsbr _cds_lfq_node_init_rcu
-#define cds_lfq_init_rcu_qsbr _cds_lfq_init_rcu
-#define cds_lfq_destroy_rcu_qsbr _cds_lfq_destroy_rcu
-#define cds_lfq_enqueue_rcu_qsbr _cds_lfq_enqueue_rcu
-#define cds_lfq_dequeue_rcu_qsbr _cds_lfq_dequeue_rcu
-
-#define cds_lfq_node_init_rcu_bp _cds_lfq_node_init_rcu
-#define cds_lfq_init_rcu_bp _cds_lfq_init_rcu
-#define cds_lfq_destroy_rcu_bp _cds_lfq_destroy_rcu
-#define cds_lfq_enqueue_rcu_bp _cds_lfq_enqueue_rcu
-#define cds_lfq_dequeue_rcu_bp _cds_lfq_dequeue_rcu
-
-#define cds_lfq_node_init_rcu_memb _cds_lfq_node_init_rcu
-#define cds_lfq_init_rcu_memb _cds_lfq_init_rcu
-#define cds_lfq_destroy_rcu_memb _cds_lfq_destroy_rcu
-#define cds_lfq_enqueue_rcu_memb _cds_lfq_enqueue_rcu
-#define cds_lfq_dequeue_rcu_memb _cds_lfq_dequeue_rcu
-
-#define cds_lfq_node_init_rcu_mb _cds_lfq_node_init_rcu
-#define cds_lfq_init_rcu_mb _cds_lfq_init_rcu
-#define cds_lfq_destroy_rcu_mb _cds_lfq_destroy_rcu
-#define cds_lfq_enqueue_rcu_mb _cds_lfq_enqueue_rcu
-#define cds_lfq_dequeue_rcu_mb _cds_lfq_dequeue_rcu
-
-#define cds_lfq_node_init_rcu_sig _cds_lfq_node_init_rcu
-#define cds_lfq_init_rcu_sig _cds_lfq_init_rcu
-#define cds_lfq_destroy_rcu_sig _cds_lfq_destroy_rcu
-#define cds_lfq_enqueue_rcu_sig _cds_lfq_enqueue_rcu
-#define cds_lfq_dequeue_rcu_sig _cds_lfq_dequeue_rcu
+#define cds_lfq_node_init_rcu _cds_lfq_node_init_rcu
+#define cds_lfq_init_rcu _cds_lfq_init_rcu
+#define cds_lfq_destroy_rcu _cds_lfq_destroy_rcu
+#define cds_lfq_enqueue_rcu _cds_lfq_enqueue_rcu
+#define cds_lfq_dequeue_rcu _cds_lfq_dequeue_rcu
#else /* !_LGPL_SOURCE */
extern void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node);
-extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q);
+extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q,
+ void queue_call_rcu(struct rcu_head *head,
+ void (*func)(struct rcu_head *head)));
/*
* The queue should be emptied before calling destroy.
*
extern int cds_lfq_destroy_rcu(struct cds_lfq_queue_rcu *q);
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*/
extern void cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
struct cds_lfq_node_rcu *node);
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfq_node_rcu structure.
#include <urcu/static/rculfstack.h>
-#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
+#define cds_lfs_node_init_rcu _cds_lfs_node_init_rcu
+#define cds_lfs_init_rcu _cds_lfs_init_rcu
+#define cds_lfs_push_rcu _cds_lfs_push_rcu
+#define cds_lfs_pop_rcu _cds_lfs_pop_rcu
#else /* !_LGPL_SOURCE */
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);
+extern int cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s,
+ struct cds_lfs_node_rcu *node);
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfs_node_rcu structure.
-/* Copyright (C) 2002 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
-
- Copyright (C) 2009 Pierre-Marc Fournier
- Conversion to RCU list.
- Copyright (C) 2010 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
-
- The GNU C 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.
-
- The GNU C 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 the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
+/*
+ * Copyright (C) 2002 Free Software Foundation, Inc.
+ * (originally part of the GNU C Library)
+ * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+ *
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ * Conversion to RCU list.
+ * Copyright (C) 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
+ */
#ifndef _URCU_RCULIST_H
#define _URCU_RCULIST_H
#include <urcu-call-rcu.h>
#include <urcu/uatomic.h>
+#include <urcu-pointer.h>
#include <assert.h>
#include <errno.h>
assert(node->dummy);
dummy = caa_container_of(node, struct cds_lfq_node_rcu_dummy, parent);
- call_rcu(&dummy->head, free_dummy_cb);
+ dummy->q->queue_call_rcu(&dummy->head, free_dummy_cb);
}
static inline
}
static inline
-void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q)
+void _cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q,
+ void queue_call_rcu(struct rcu_head *head,
+ void (*func)(struct rcu_head *head)))
{
q->tail = make_dummy(q, NULL);
q->head = q->tail;
+ q->queue_call_rcu = queue_call_rcu;
}
/*
}
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*/
static inline
void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
for (;;) {
struct cds_lfq_node_rcu *tail, *next;
- rcu_read_lock();
tail = rcu_dereference(q->tail);
next = uatomic_cmpxchg(&tail->next, NULL, node);
if (next == NULL) {
* enqueue might beat us to it, that's fine).
*/
(void) uatomic_cmpxchg(&q->tail, tail, node);
- rcu_read_unlock();
return;
} else {
/*
* Help moving tail further and retry.
*/
(void) uatomic_cmpxchg(&q->tail, tail, next);
- rcu_read_unlock();
continue;
}
}
}
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read lock critical section.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfq_node_rcu structure.
for (;;) {
struct cds_lfq_node_rcu *head, *next;
- rcu_read_lock();
head = rcu_dereference(q->head);
next = rcu_dereference(head->next);
- if (head->dummy && next == NULL) {
- rcu_read_unlock();
+ if (head->dummy && next == NULL)
return NULL; /* empty */
- }
/*
* We never, ever allow dequeue to get to a state where
* the queue is empty (we need at least one node in the
enqueue_dummy(q);
next = rcu_dereference(head->next);
}
- if (uatomic_cmpxchg(&q->head, head, next) != head) {
- rcu_read_unlock();
+ if (uatomic_cmpxchg(&q->head, head, next) != head)
continue; /* Concurrently pushed. */
- }
if (head->dummy) {
/* Free dummy after grace period. */
rcu_free_dummy(head);
- rcu_read_unlock();
continue; /* try again */
}
- rcu_read_unlock();
return head;
}
}
*/
#include <urcu/uatomic.h>
+#include <urcu-pointer.h>
#ifdef __cplusplus
extern "C" {
* required if we first read the old head value). This design decision
* might be revisited after more throrough benchmarking on various
* platforms.
+ *
+ * Returns 0 if the stack was empty prior to adding the node.
+ * Returns non-zero otherwise.
*/
static inline
-void _cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *node)
+int _cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s,
+ struct cds_lfs_node_rcu *node)
{
struct cds_lfs_node_rcu *head = NULL;
if (old_head == head)
break;
}
+ return (int) !!((unsigned long) head);
}
/*
- * Acts as a RCU reader.
+ * Should be called under rcu read-side lock.
*
* The caller must wait for a grace period to pass before freeing the returned
* node or modifying the cds_lfs_node_rcu structure.
for (;;) {
struct cds_lfs_node_rcu *head;
- rcu_read_lock();
head = rcu_dereference(s->head);
if (head) {
struct cds_lfs_node_rcu *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;
}
}
assert(!ret);
}
+/*
+ * Returns 0 if stack was empty, 1 otherwise.
+ */
static inline
-void _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
+int _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
{
struct cds_wfs_node *old_head;
* until node->next is set to old_head.
*/
CMM_STORE_SHARED(node->next, old_head);
+ return (old_head != CDS_WF_STACK_END);
}
/*
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);
+extern int 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);
_cds_wfs_init(s);
}
-void cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
+int cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
{
- _cds_wfs_push(s, node);
+ return _cds_wfs_push(s, node);
}
struct cds_wfs_node *__cds_wfs_pop_blocking(struct cds_wfs_stack *s)