Merge branch 'master' into rbtree2
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 3 Sep 2011 14:44:43 +0000 (10:44 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 3 Sep 2011 14:44:43 +0000 (10:44 -0400)
Conflicts:
Makefile.am

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
21 files changed:
Makefile.am
rculfqueue.c
rculfstack.c
tests/Makefile.am
tests/test_urcu_lfq.c
tests/test_urcu_lfs.c
urcu-bp.c
urcu/compiler.h
urcu/list.h
urcu/map/urcu-bp.h
urcu/map/urcu-qsbr.h
urcu/map/urcu.h
urcu/rcuhlist.h
urcu/rculfqueue.h
urcu/rculfstack.h
urcu/rculist.h
urcu/static/rculfqueue.h
urcu/static/rculfstack.h
urcu/static/wfstack.h
urcu/wfstack.h
wfstack.c

index a1609b34ca9d3f4537ae6a9b2e372822dce259df..8f06cf947f8e8b2b9788e537715f1688b0d11198 100644 (file)
@@ -34,35 +34,36 @@ if COMPAT_FUTEX
 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)
 
index c579e75a759e4e25d0f1780ecabd5c0b1bcd3e2a..38eddcf3a4283c2b86d2d66ee5604bf3a57b2213 100644 (file)
  * 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"
 
 /*
@@ -44,9 +35,11 @@ void cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node)
        _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)
index aa906af9480c66efce8c35ccf8d2b3625b9aabfd..574ea874265b316f9aed44ce998c16a034f3c585 100644 (file)
  * 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"
 
 /*
@@ -51,9 +41,10 @@ void cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s)
        _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)
index d8431f4e853051121100bb474991c4b97eda2ff0..51e961ce82b8816689eccbf61e03b3692b15ddad 100644 (file)
@@ -38,17 +38,13 @@ URCU_SIGNAL=$(top_srcdir)/urcu.c $(top_srcdir)/urcu-pointer.c $(top_srcdir)/wfqu
 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
 
@@ -167,20 +163,20 @@ test_urcu_lfq_dynlink_SOURCES = test_urcu_lfq.c $(URCU)
 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)
 
index 82a90b0cdecc23f05c3572cf6b6819f00ac72531..b61a7d4815788af2bcd9e197dc319a8eb053791a 100644 (file)
@@ -180,7 +180,9 @@ void *thr_enqueuer(void *_count)
                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))
@@ -228,7 +230,10 @@ void *thr_dequeuer(void *_count)
        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++;
@@ -257,7 +262,9 @@ void test_end(struct cds_lfq_queue_rcu *q, unsigned long long *nr_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)++;
@@ -356,7 +363,7 @@ int main(int argc, char **argv)
        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;
 
index a7f9af3abd5086ee21e73aa0f3269530e612886a..252454d29aeb46d4758e30b2a7f6b864cc8e3b65 100644 (file)
@@ -229,7 +229,9 @@ void *thr_dequeuer(void *_count)
        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++;
index 80eaefe7ea78a35cd20d138bcb9ac6ebd08c31b4..2ae3408c25fd42cc6788c6ec8664c91cf9868d87 100644 (file)
--- a/urcu-bp.c
+++ b/urcu-bp.c
@@ -373,9 +373,10 @@ end:
        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);
 }
 
 /*
index 489677b3aefe1ad6dd294006d903721f375f66a7..4bced2a9849846a25b8c1fd59a15cd2b03af0060 100644 (file)
 #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 */
index ab7a470a8d0f245541ce7b853b72875784ad511e..7d2a9a11e39b12d061e6a68b90b6918f307af17a 100644 (file)
@@ -1,21 +1,26 @@
-/* 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
index f62b5b38f15ec28a9a61f5af37c657dd52af7b21..4abe8dccb1bc8d56358baedf9f5457eb608730c8 100644 (file)
 #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 */
index 6e4a1963413775e28ebbe6e6a364c6adc4ce12f9..0d88d83afa3d70946f131c36fdf296aeea3a4c28 100644 (file)
 #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 */
index 90c2f65a79a04096b244bf95692fdeb0213be417..3f436a7375120366bca0898aafd3debdc45a48a5 100644 (file)
 #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"
index ef024abe7034f70d5db05312d620a329fb03ab08..83b13632536cb15a3a398505da960f4e3417c086 100644 (file)
@@ -1,25 +1,26 @@
-/* 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
index 1582694e92abbcfc5bfc8104f2016fb480f41aff..598fa5071a2ca727e43d07a67cb2a62eb4980632 100644 (file)
@@ -39,46 +39,26 @@ struct cds_lfq_node_rcu {
 
 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.
  *
@@ -87,13 +67,13 @@ extern void cds_lfq_init_rcu(struct cds_lfq_queue_rcu *q);
 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.
index f6739528a650b2bf8c9bb8d41a35dc400a02c16f..93c0bc92f82544043906d3aca51dc63d6d7995c9 100644 (file)
@@ -39,39 +39,20 @@ struct cds_lfs_stack_rcu {
 
 #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.
index 621831ce0aec6d3bd8117faa1aeed3b76bb64e16..575e1fb0d8f4f836166695f80b732898d8c0265a 100644 (file)
@@ -1,25 +1,26 @@
-/* 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
index 99335c41ec41d33078279e2f843431111cf307e8..af73c6f2ef7565dc69e16f62d539ded7ed66d583 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <urcu-call-rcu.h>
 #include <urcu/uatomic.h>
+#include <urcu-pointer.h>
 #include <assert.h>
 #include <errno.h>
 
@@ -88,7 +89,7 @@ void rcu_free_dummy(struct cds_lfq_node_rcu *node)
 
        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
@@ -109,10 +110,13 @@ void _cds_lfq_node_init_rcu(struct cds_lfq_node_rcu *node)
 }
 
 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;
 }
 
 /*
@@ -133,7 +137,7 @@ 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.
  */
 static inline
 void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
@@ -147,7 +151,6 @@ 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) {
@@ -157,7 +160,6 @@ void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
                         * enqueue might beat us to it, that's fine).
                         */
                        (void) uatomic_cmpxchg(&q->tail, tail, node);
-                       rcu_read_unlock();
                        return;
                } else {
                        /*
@@ -165,7 +167,6 @@ void _cds_lfq_enqueue_rcu(struct cds_lfq_queue_rcu *q,
                         * Help moving tail further and retry.
                         */
                        (void) uatomic_cmpxchg(&q->tail, tail, next);
-                       rcu_read_unlock();
                        continue;
                }
        }
@@ -182,7 +183,7 @@ void enqueue_dummy(struct cds_lfq_queue_rcu *q)
 }
 
 /*
- * 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.
@@ -194,13 +195,10 @@ struct cds_lfq_node_rcu *_cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q)
        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
@@ -212,17 +210,13 @@ struct cds_lfq_node_rcu *_cds_lfq_dequeue_rcu(struct cds_lfq_queue_rcu *q)
                        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;
        }
 }
index 9d69fa736996c4dfc704bbffc88d9f14395344c8..3473ccef82299b0b41559734e75377b2ac0f1941 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <urcu/uatomic.h>
+#include <urcu-pointer.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -64,9 +65,13 @@ void _cds_lfs_init_rcu(struct cds_lfs_stack_rcu *s)
  * 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;
 
@@ -82,10 +87,11 @@ void _cds_lfs_push_rcu(struct cds_lfs_stack_rcu *s, struct cds_lfs_node_rcu *nod
                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.
@@ -98,22 +104,18 @@ _cds_lfs_pop_rcu(struct cds_lfs_stack_rcu *s)
        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;
                }
        }
index 79ed3f774446e042de152ed7c04a7a43cf5aa65b..cb68a59a16d8dc270355d1b6b29506d2120c812f 100644 (file)
@@ -56,8 +56,11 @@ void _cds_wfs_init(struct cds_wfs_stack *s)
        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;
 
@@ -72,6 +75,7 @@ void _cds_wfs_push(struct cds_wfs_stack *s, struct cds_wfs_node *node)
         * until node->next is set to old_head.
         */
        CMM_STORE_SHARED(node->next, old_head);
+       return (old_head != CDS_WF_STACK_END);
 }
 
 /*
index 354646dfb4237bf626478d2291de52bb2f47fbf1..db2ee0c005a85b261997bc10a3a1c72bcb73a809 100644 (file)
@@ -54,7 +54,7 @@ struct cds_wfs_stack {
 
 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);
index d999a5b433dee30a979a5c99c31e20680e2ace81..e9799e6d67b2a1a9b58f6912a7b95576810e6fcb 100644 (file)
--- a/wfstack.c
+++ b/wfstack.c
@@ -38,9 +38,9 @@ void cds_wfs_init(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)
This page took 0.040774 seconds and 4 git commands to generate.