Refactor liburcu to support many flavors per compile unit
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 28 Nov 2018 17:07:09 +0000 (12:07 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 12 Dec 2018 15:18:49 +0000 (10:18 -0500)
This refactoring keeps the prior use of liburcu "map" APIs unchanged.
However, it introduces the following new APIs:

Each urcu flavor is now available as its own header:

include/urcu/urcu-memb.h
include/urcu/urcu-mb.h
include/urcu/urcu-signal.h
include/urcu/urcu-bp.h
include/urcu/urcu-qsbr.h

The installed urcu headers that were not under the urcu/ subdirectory
are moved there:

include/urcu-call-rcu.h -> include/urcu/call-rcu.h
include/urcu-defer.h -> include/urcu/defer.h
include/urcu-flavor.h -> include/urcu/flavor.h
include/urcu-pointer.h -> include/urcu/pointer.h
include/urcu-bp.h -> include/urcu/urcu-bp.h
include/urcu.h -> include/urcu/urcu.h
include/urcu-qsbr.h -> include/urcu/urcu-qsbr.h

The liburcu "map" API is now only available for use when URCU_API_MAP is
defined before including the liburcu flavor headers.

The old headers are now placeholders defining URCU_API_MAP and including
the new headers for backward compatibility:

include/urcu-bp.h
include/urcu-call-rcu.h
include/urcu-defer.h
include/urcu-flavor.h
include/urcu-pointer.h
include/urcu-qsbr.h
include/urcu.h

The header include/urcu/urcu.h now includes the right header between the
memb, signal, or mb flavors based on the compiler defines.

The symbol names of liburcu flavors are cleaned up, favoring the
following hierarchy:

urcu_<flavor name>_...

This is an ABI-breaking change, however the previous symbols name were
kept as aliases to maintain backward compatibility. They will be removed
when the next SONAME bump occurs.

The new liburcu-memb.so shared object is introduced, properly
namespacing this flavor. It is a duplicate of the previous liburcu.so,
which is kept around for backward compatibility.

The new URCU_API_MAP macro is introduced, controlling whether the
urcu API "mapping" should stay defined after inclusion of the flavor
headers. Users wishing to use the prior urcu API should either
explicitly define URCU_API_MAP before including the urcu/urcu*.h flavor
headers, or include the flavor header files from the include toplevel
directory, which are placeholders for backward compatibility. Use of
many urcu flavors within the same _LGPL_SOURCE compile unit should not
use the "map" APIs.

Internally, the "map" header files are split into one header per
flavor. The include guards are removed, so their effect can be
applied more than once. A new include/urcu/map/clear.h header is
introduced, which undefines the mappings at the end of the flavor
header if URCU_API_MAP is not set.

The new APIs namespaced for each urcu flavor is the recommended way to
use liburcu. We can expect the prior APIs to eventually become
deprecated over time.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
48 files changed:
configure.ac
include/Makefile.am
include/urcu-bp.h [new file with mode: 0644]
include/urcu-call-rcu.h [new file with mode: 0644]
include/urcu-defer.h [new file with mode: 0644]
include/urcu-flavor.h [new file with mode: 0644]
include/urcu-pointer.h [new file with mode: 0644]
include/urcu-qsbr.h [new file with mode: 0644]
include/urcu.h [new file with mode: 0644]
include/urcu/call-rcu.h [new file with mode: 0644]
include/urcu/config.h.in
include/urcu/defer.h [new file with mode: 0644]
include/urcu/flavor.h [new file with mode: 0644]
include/urcu/map/clear.h [new file with mode: 0644]
include/urcu/map/urcu-bp.h
include/urcu/map/urcu-mb.h [new file with mode: 0644]
include/urcu/map/urcu-memb.h [new file with mode: 0644]
include/urcu/map/urcu-qsbr.h
include/urcu/map/urcu-signal.h [new file with mode: 0644]
include/urcu/map/urcu.h
include/urcu/pointer.h [new file with mode: 0644]
include/urcu/static/urcu-bp.h
include/urcu/static/urcu-common.h [new file with mode: 0644]
include/urcu/static/urcu-mb.h [new file with mode: 0644]
include/urcu/static/urcu-memb.h [new file with mode: 0644]
include/urcu/static/urcu-qsbr.h
include/urcu/static/urcu-signal.h [new file with mode: 0644]
include/urcu/static/urcu.h
include/urcu/urcu-bp.h [new file with mode: 0644]
include/urcu/urcu-mb.h [new file with mode: 0644]
include/urcu/urcu-memb.h [new file with mode: 0644]
include/urcu/urcu-qsbr.h [new file with mode: 0644]
include/urcu/urcu-signal.h [new file with mode: 0644]
include/urcu/urcu.h [new file with mode: 0644]
src/Makefile.am
src/urcu-bp.c
src/urcu-bp.h [deleted file]
src/urcu-call-rcu-impl.h
src/urcu-call-rcu.h [deleted file]
src/urcu-defer-impl.h
src/urcu-defer.h [deleted file]
src/urcu-flavor.h [deleted file]
src/urcu-pointer.h [deleted file]
src/urcu-qsbr.c
src/urcu-qsbr.h [deleted file]
src/urcu-utils.h [new file with mode: 0644]
src/urcu.c
src/urcu.h [deleted file]

index 9145081..8e7ff4c 100644 (file)
@@ -508,6 +508,8 @@ PPRINT_PROP_BOOL([Require membarrier], $value)
 test "x$enable_rcu_debug" = "xyes" && value=1 || value=0
 PPRINT_PROP_BOOL([Internal debugging], $value)
 
+PPRINT_PROP_BOOL([Multi-flavor support], 1)
+
 report_bindir="`eval eval echo $bindir`"
 report_libdir="`eval eval echo $libdir`"
 
index 36667b4..a567f91 100644 (file)
@@ -6,12 +6,21 @@ nobase_dist_include_HEADERS = urcu/compiler.h urcu/hlist.h urcu/list.h \
                urcu/uatomic_arch.h urcu/rculfhash.h urcu/wfcqueue.h \
                urcu/lfstack.h urcu/syscall-compat.h \
                urcu/map/urcu-bp.h urcu/map/urcu.h urcu/map/urcu-qsbr.h \
+               urcu/map/clear.h urcu/map/urcu-mb.h urcu/map/urcu-memb.h \
+               urcu/map/urcu-signal.h \
                urcu/static/lfstack.h urcu/static/rculfqueue.h \
                urcu/static/rculfstack.h urcu/static/urcu-bp.h \
                urcu/static/urcu.h urcu/static/urcu-pointer.h \
                urcu/static/urcu-qsbr.h urcu/static/wfcqueue.h \
                urcu/static/wfqueue.h urcu/static/wfstack.h \
-               urcu/tls-compat.h urcu/debug.h
+               urcu/static/urcu-mb.h urcu/static/urcu-memb.h \
+               urcu/static/urcu-signal.h urcu/static/urcu-common.h \
+               urcu/tls-compat.h urcu/debug.h urcu/urcu.h urcu/urcu-bp.h \
+               urcu/call-rcu.h urcu/defer.h \
+               urcu/pointer.h urcu/urcu-qsbr.h urcu/flavor.h \
+               urcu/urcu-mb.h urcu/urcu-memb.h urcu/urcu-signal.h \
+               urcu.h urcu-bp.h urcu-call-rcu.h urcu-defer.h \
+               urcu-pointer.h urcu-qsbr.h urcu-flavor.h
 
 # Don't distribute generated headers
 nobase_nodist_include_HEADERS = urcu/arch.h urcu/uatomic.h urcu/config.h
diff --git a/include/urcu-bp.h b/include/urcu-bp.h
new file mode 100644 (file)
index 0000000..acafee2
--- /dev/null
@@ -0,0 +1,2 @@
+#define URCU_API_MAP
+#include <urcu/urcu-bp.h>
diff --git a/include/urcu-call-rcu.h b/include/urcu-call-rcu.h
new file mode 100644 (file)
index 0000000..162bc56
--- /dev/null
@@ -0,0 +1 @@
+#include <urcu/call-rcu.h>
diff --git a/include/urcu-defer.h b/include/urcu-defer.h
new file mode 100644 (file)
index 0000000..e097d45
--- /dev/null
@@ -0,0 +1 @@
+#include <urcu/defer.h>
diff --git a/include/urcu-flavor.h b/include/urcu-flavor.h
new file mode 100644 (file)
index 0000000..aca264d
--- /dev/null
@@ -0,0 +1 @@
+#include <urcu/flavor.h>
diff --git a/include/urcu-pointer.h b/include/urcu-pointer.h
new file mode 100644 (file)
index 0000000..97aed98
--- /dev/null
@@ -0,0 +1 @@
+#include <urcu/pointer.h>
diff --git a/include/urcu-qsbr.h b/include/urcu-qsbr.h
new file mode 100644 (file)
index 0000000..43d95a9
--- /dev/null
@@ -0,0 +1,2 @@
+#define URCU_API_MAP
+#include <urcu/urcu-qsbr.h>
diff --git a/include/urcu.h b/include/urcu.h
new file mode 100644 (file)
index 0000000..5599961
--- /dev/null
@@ -0,0 +1,2 @@
+#define URCU_API_MAP
+#include <urcu/urcu.h>
diff --git a/include/urcu/call-rcu.h b/include/urcu/call-rcu.h
new file mode 100644 (file)
index 0000000..339ebac
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef _URCU_CALL_RCU_H
+#define _URCU_CALL_RCU_H
+
+/*
+ * urcu-call-rcu.h
+ *
+ * Userspace RCU header - deferred execution
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu-defer.h>
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+
+#include <urcu/wfcqueue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Note that struct call_rcu_data is opaque to callers. */
+
+struct call_rcu_data;
+
+/* Flag values. */
+
+#define URCU_CALL_RCU_RT       (1U << 0)
+#define URCU_CALL_RCU_RUNNING  (1U << 1)
+#define URCU_CALL_RCU_STOP     (1U << 2)
+#define URCU_CALL_RCU_STOPPED  (1U << 3)
+#define URCU_CALL_RCU_PAUSE    (1U << 4)
+#define URCU_CALL_RCU_PAUSED   (1U << 5)
+
+/*
+ * The rcu_head data structure is placed in the structure to be freed
+ * via call_rcu().
+ */
+
+struct rcu_head {
+       struct cds_wfcq_node next;
+       void (*func)(struct rcu_head *head);
+};
+
+/*
+ * Exported functions
+ *
+ * Important: see rcu-api.md in userspace-rcu documentation for
+ * call_rcu family of functions usage detail, including the surrounding
+ * RCU usage required when using these primitives.
+ */
+
+void call_rcu(struct rcu_head *head,
+             void (*func)(struct rcu_head *head));
+
+struct call_rcu_data *create_call_rcu_data(unsigned long flags,
+                                          int cpu_affinity);
+void call_rcu_data_free(struct call_rcu_data *crdp);
+
+struct call_rcu_data *get_default_call_rcu_data(void);
+struct call_rcu_data *get_cpu_call_rcu_data(int cpu);
+struct call_rcu_data *get_thread_call_rcu_data(void);
+struct call_rcu_data *get_call_rcu_data(void);
+pthread_t get_call_rcu_thread(struct call_rcu_data *crdp);
+
+void set_thread_call_rcu_data(struct call_rcu_data *crdp);
+int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp);
+
+int create_all_cpu_call_rcu_data(unsigned long flags);
+void free_all_cpu_call_rcu_data(void);
+
+void call_rcu_before_fork(void);
+void call_rcu_after_fork_parent(void);
+void call_rcu_after_fork_child(void);
+
+void rcu_barrier(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_CALL_RCU_H */
index 9ed0454..9f2aa99 100644 (file)
@@ -30,3 +30,6 @@
 /* Enable internal debugging self-checks.
    Introduce performance penalty. */
 #undef CONFIG_RCU_DEBUG
+
+/* Expose multi-flavor support */
+#define CONFIG_RCU_MULTIFLAVOR 1
diff --git a/include/urcu/defer.h b/include/urcu/defer.h
new file mode 100644 (file)
index 0000000..43eca34
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _URCU_BATCH_H
+#define _URCU_BATCH_H
+
+/*
+ * urcu-defer.h
+ *
+ * Userspace RCU header - deferred execution
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu-defer.h>
+ *
+ * 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 <stdlib.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Note: the defer_rcu() API is currently EXPERIMENTAL. It may change in the
+ * future.
+ *
+ * Important !
+ *
+ * Each thread queuing memory reclamation must be registered with
+ * rcu_defer_register_thread(). rcu_defer_unregister_thread() should be
+ * called before the thread exits.
+ *
+ * *NEVER* use defer_rcu() within a RCU read-side critical section, because this
+ * primitive need to call synchronize_rcu() if the thread queue is full.
+ */
+
+extern void defer_rcu(void (*fct)(void *p), void *p);
+
+/*
+ * Thread registration for reclamation.
+ */
+extern int rcu_defer_register_thread(void);
+extern void rcu_defer_unregister_thread(void);
+extern void rcu_defer_barrier(void);
+extern void rcu_defer_barrier_thread(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_BATCH_H */
diff --git a/include/urcu/flavor.h b/include/urcu/flavor.h
new file mode 100644 (file)
index 0000000..411fefb
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef _URCU_FLAVOR_H
+#define _URCU_FLAVOR_H
+
+/*
+ * urcu-flavor.h
+ *
+ * Userspace RCU header - rcu flavor declarations
+ *
+ * Copyright (c) 2011 Lai Jiangshan <laijs@cn.fujitsu.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
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct urcu_atfork {
+       void (*before_fork)(void *priv);
+       void (*after_fork_parent)(void *priv);
+       void (*after_fork_child)(void *priv);
+       void *priv;
+};
+
+void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork);
+void urcu_unregister_rculfhash_atfork(struct urcu_atfork *atfork);
+
+struct rcu_flavor_struct {
+       void (*read_lock)(void);
+       void (*read_unlock)(void);
+       int (*read_ongoing)(void);
+       void (*read_quiescent_state)(void);
+       void (*update_call_rcu)(struct rcu_head *head,
+                               void (*func)(struct rcu_head *head));
+       void (*update_synchronize_rcu)(void);
+       void (*update_defer_rcu)(void (*fct)(void *p), void *p);
+
+       void (*thread_offline)(void);
+       void (*thread_online)(void);
+       void (*register_thread)(void);
+       void (*unregister_thread)(void);
+
+       void (*barrier)(void);
+
+       void (*register_rculfhash_atfork)(struct urcu_atfork *atfork);
+       void (*unregister_rculfhash_atfork)(struct urcu_atfork *atfork);
+};
+
+#define DEFINE_RCU_FLAVOR(x)                           \
+const struct rcu_flavor_struct x = {                   \
+       .read_lock              = rcu_read_lock,        \
+       .read_unlock            = rcu_read_unlock,      \
+       .read_ongoing           = rcu_read_ongoing,     \
+       .read_quiescent_state   = rcu_quiescent_state,  \
+       .update_call_rcu        = call_rcu,             \
+       .update_synchronize_rcu = synchronize_rcu,      \
+       .update_defer_rcu       = defer_rcu,            \
+       .thread_offline         = rcu_thread_offline,   \
+       .thread_online          = rcu_thread_online,    \
+       .register_thread        = rcu_register_thread,  \
+       .unregister_thread      = rcu_unregister_thread,\
+       .barrier                = rcu_barrier,          \
+       .register_rculfhash_atfork = urcu_register_rculfhash_atfork,    \
+       .unregister_rculfhash_atfork = urcu_unregister_rculfhash_atfork,\
+}
+
+#define DEFINE_RCU_FLAVOR_ALIAS(x, y) _DEFINE_RCU_FLAVOR_ALIAS(x, y)
+#define _DEFINE_RCU_FLAVOR_ALIAS(x, y)                 \
+__attribute__((alias(#x)))                             \
+extern const struct rcu_flavor_struct y;
+
+extern const struct rcu_flavor_struct rcu_flavor;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_FLAVOR_H */
diff --git a/include/urcu/map/clear.h b/include/urcu/map/clear.h
new file mode 100644 (file)
index 0000000..76d5464
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * map/urcu-clear.h
+ *
+ * Userspace RCU header -- name mapping to allow multiple flavors to be
+ * used in the same executable.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #undef _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#undef rcu_read_lock
+#undef _rcu_read_lock
+#undef rcu_read_unlock
+#undef _rcu_read_unlock
+#undef rcu_read_ongoing
+#undef _rcu_read_ongoing
+#undef rcu_quiescent_state
+#undef _rcu_quiescent_state
+#undef rcu_thread_offline
+#undef rcu_thread_online
+#undef rcu_register_thread
+#undef rcu_unregister_thread
+#undef rcu_init
+#undef rcu_exit
+#undef synchronize_rcu
+#undef rcu_reader
+#undef rcu_gp
+
+#undef get_cpu_call_rcu_data
+#undef get_call_rcu_thread
+#undef create_call_rcu_data
+#undef set_cpu_call_rcu_data
+#undef get_default_call_rcu_data
+#undef get_call_rcu_data
+#undef get_thread_call_rcu_data
+#undef set_thread_call_rcu_data
+#undef create_all_cpu_call_rcu_data
+#undef free_all_cpu_call_rcu_data
+#undef call_rcu
+#undef call_rcu_data_free
+#undef call_rcu_before_fork
+#undef call_rcu_after_fork_parent
+#undef call_rcu_after_fork_child
+#undef rcu_barrier
+
+#undef defer_rcu
+#undef rcu_defer_register_thread
+#undef rcu_defer_unregister_thread
+#undef rcu_defer_barrier
+
+#undef rcu_defer_barrier_thread
+#undef rcu_defer_exit
+
+#undef rcu_flavor
+
+#undef urcu_register_rculfhash_atfork
+#undef urcu_unregister_rculfhash_atfork
+
+/* Aliases for ABI(6) compat */
+
+#undef alias_rcu_flavor
+
+/* src/urcu.c */
+#undef alias_rcu_read_lock
+#undef alias_rcu_read_unlock
+#undef alias_rcu_read_ongoing
+#undef alias_rcu_register_thread
+#undef alias_rcu_unregister_thread
+#undef alias_rcu_init
+#undef alias_rcu_exit
+#undef alias_synchronize_rcu
+#undef alias_rcu_reader
+#undef alias_rcu_gp
+
+/* src/urcu-call-rcu-impl.h */
+#undef alias_get_cpu_call_rcu_data
+#undef alias_get_call_rcu_thread
+#undef alias_create_call_rcu_data
+#undef alias_set_cpu_call_rcu_data
+#undef alias_get_default_call_rcu_data
+#undef alias_get_call_rcu_data
+#undef alias_get_thread_call_rcu_data
+#undef alias_set_thread_call_rcu_data
+#undef alias_create_all_cpu_call_rcu_data
+#undef alias_free_all_cpu_call_rcu_data
+#undef alias_call_rcu
+#undef alias_call_rcu_data_free
+#undef alias_call_rcu_before_fork
+#undef alias_call_rcu_after_fork_parent
+#undef alias_call_rcu_after_fork_child
+#undef alias_rcu_barrier
+
+#undef alias_urcu_register_rculfhash_atfork
+#undef alias_urcu_unregister_rculfhash_atfork
+
+/* src/urcu-defer-impl.h */
+#undef alias_defer_rcu
+#undef alias_rcu_defer_register_thread
+#undef alias_rcu_defer_unregister_thread
+#undef alias_rcu_defer_barrier
+#undef alias_rcu_defer_barrier_thread
+#undef alias_rcu_defer_exit
index 1476924..ed73ab2 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef _URCU_BP_MAP_H
-#define _URCU_BP_MAP_H
-
 /*
- * urcu-map.h
+ * urcu/map/urcu-bp.h
  *
  * Userspace RCU header -- name mapping to allow multiple flavors to be
  * used in the same executable.
 
 /* Mapping macros to allow multiple flavors in a single binary. */
 
-#define rcu_read_lock                  rcu_read_lock_bp
-#define _rcu_read_lock                 _rcu_read_lock_bp
-#define rcu_read_unlock                        rcu_read_unlock_bp
-#define _rcu_read_unlock               _rcu_read_unlock_bp
-#define rcu_read_ongoing               rcu_read_ongoing_bp
-#define _rcu_read_ongoing              _rcu_read_ongoing_bp
-#define rcu_register_thread            rcu_register_thread_bp
-#define rcu_unregister_thread          rcu_unregister_thread_bp
-#define rcu_init                       rcu_init_bp
-#define rcu_exit                       rcu_exit_bp
-#define synchronize_rcu                        synchronize_rcu_bp
-#define rcu_reader                     rcu_reader_bp
-#define rcu_gp                         rcu_gp_bp
+#define rcu_read_lock                  urcu_bp_read_lock
+#define _rcu_read_lock                 _urcu_bp_read_lock
+#define rcu_read_unlock                        urcu_bp_read_unlock
+#define _rcu_read_unlock               _urcu_bp_read_unlock
+#define rcu_read_ongoing               urcu_bp_read_ongoing
+#define _rcu_read_ongoing              _urcu_bp_read_ongoing
+#define rcu_quiescent_state            urcu_bp_quiescent_state
+#define _rcu_quiescent_state           _urcu_bp_quiescent_state
+#define rcu_thread_offline             urcu_bp_thread_offline
+#define rcu_thread_online              urcu_bp_thread_online
+#define rcu_register_thread            urcu_bp_register_thread
+#define rcu_unregister_thread          urcu_bp_unregister_thread
+#define rcu_init                       urcu_bp_init
+#define rcu_exit                       urcu_bp_exit
+#define synchronize_rcu                        urcu_bp_synchronize_rcu
+#define rcu_reader                     urcu_bp_reader
+#define rcu_gp                         urcu_bp_gp
 
-#define get_cpu_call_rcu_data          get_cpu_call_rcu_data_bp
-#define get_call_rcu_thread            get_call_rcu_thread_bp
-#define create_call_rcu_data           create_call_rcu_data_bp
-#define set_cpu_call_rcu_data          set_cpu_call_rcu_data_bp
-#define get_default_call_rcu_data      get_default_call_rcu_data_bp
-#define get_call_rcu_data              get_call_rcu_data_bp
-#define get_thread_call_rcu_data       get_thread_call_rcu_data_bp
-#define set_thread_call_rcu_data       set_thread_call_rcu_data_bp
-#define create_all_cpu_call_rcu_data   create_all_cpu_call_rcu_data_bp
-#define free_all_cpu_call_rcu_data     free_all_cpu_call_rcu_data_bp
-#define call_rcu                       call_rcu_bp
-#define call_rcu_data_free             call_rcu_data_free_bp
-#define call_rcu_before_fork           call_rcu_before_fork_bp
-#define call_rcu_after_fork_parent     call_rcu_after_fork_parent_bp
-#define call_rcu_after_fork_child      call_rcu_after_fork_child_bp
-#define rcu_barrier                    rcu_barrier_bp
+#define get_cpu_call_rcu_data          urcu_bp_get_cpu_call_rcu_data
+#define get_call_rcu_thread            urcu_bp_get_call_rcu_thread
+#define create_call_rcu_data           urcu_bp_create_call_rcu_data
+#define set_cpu_call_rcu_data          urcu_bp_set_cpu_call_rcu_data
+#define get_default_call_rcu_data      urcu_bp_get_default_call_rcu_data
+#define get_call_rcu_data              urcu_bp_get_call_rcu_data
+#define get_thread_call_rcu_data       urcu_bp_get_thread_call_rcu_data
+#define set_thread_call_rcu_data       urcu_bp_set_thread_call_rcu_data
+#define create_all_cpu_call_rcu_data   urcu_bp_create_all_cpu_call_rcu_data
+#define free_all_cpu_call_rcu_data     urcu_bp_free_all_cpu_call_rcu_data
+#define call_rcu                       urcu_bp_call_rcu
+#define call_rcu_data_free             urcu_bp_call_rcu_data_free
+#define call_rcu_before_fork           urcu_bp_call_rcu_before_fork
+#define call_rcu_after_fork_parent     urcu_bp_call_rcu_after_fork_parent
+#define call_rcu_after_fork_child      urcu_bp_call_rcu_after_fork_child
+#define rcu_barrier                    urcu_bp_barrier
 
-#define defer_rcu                      defer_rcu_bp
-#define rcu_defer_register_thread      rcu_defer_register_thread_bp
-#define rcu_defer_unregister_thread    rcu_defer_unregister_thread_bp
-#define rcu_defer_barrier              rcu_defer_barrier_bp
-#define rcu_defer_barrier_thread       rcu_defer_barrier_thread_bp
-#define rcu_defer_exit                 rcu_defer_exit_bp
+#define defer_rcu                      urcu_bp_defer_rcu
+#define rcu_defer_register_thread      urcu_bp_defer_register_thread
+#define rcu_defer_unregister_thread    urcu_bp_defer_unregister_thread
+#define rcu_defer_barrier              urcu_bp_defer_barrier
+#define rcu_defer_barrier_thread       urcu_bp_defer_barrier_thread
+#define rcu_defer_exit                 urcu_bp_defer_exit
 
-#define rcu_flavor                     rcu_flavor_bp
+#define rcu_flavor                     urcu_bp_flavor
 
-#define rcu_yield_active               rcu_yield_active_bp
-#define rcu_rand_yield                 rcu_rand_yield_bp
+#define rcu_yield_active               urcu_bp_yield_active
+#define rcu_rand_yield                 urcu_bp_rand_yield
 
 #define urcu_register_rculfhash_atfork         \
-               urcu_register_rculfhash_atfork_bp
+               urcu_bp_register_rculfhash_atfork
 #define urcu_unregister_rculfhash_atfork       \
-               urcu_unregister_rculfhash_atfork_bp
+               urcu_bp_unregister_rculfhash_atfork
+
+
+/* Aliases for ABI(6) compat */
 
-#endif /* _URCU_BP_MAP_H */
+#define alias_rcu_flavor               rcu_flavor_bp
+
+#define alias_get_cpu_call_rcu_data    get_cpu_call_rcu_data_bp
+#define alias_get_call_rcu_thread      get_call_rcu_thread_bp
+#define alias_create_call_rcu_data     create_call_rcu_data_bp
+#define alias_set_cpu_call_rcu_data    set_cpu_call_rcu_data_bp
+#define alias_get_default_call_rcu_data        get_default_call_rcu_data_bp
+#define alias_get_call_rcu_data                get_call_rcu_data_bp
+#define alias_get_thread_call_rcu_data get_thread_call_rcu_data_bp
+#define alias_set_thread_call_rcu_data set_thread_call_rcu_data_bp
+#define alias_create_all_cpu_call_rcu_data     \
+               create_all_cpu_call_rcu_data_bp
+#define alias_free_all_cpu_call_rcu_data       \
+               free_all_cpu_call_rcu_data_bp
+#define alias_call_rcu                 call_rcu_bp
+#define alias_call_rcu_data_free       call_rcu_data_free_bp
+#define alias_call_rcu_before_fork     call_rcu_before_fork_bp
+#define alias_call_rcu_after_fork_parent       \
+               call_rcu_after_fork_parent_bp
+#define alias_call_rcu_after_fork_child        call_rcu_after_fork_child_bp
+#define alias_rcu_barrier              rcu_barrier_bp
+
+#define alias_defer_rcu                        defer_rcu_bp
+#define alias_rcu_defer_register_thread        rcu_defer_register_thread_bp
+#define alias_rcu_defer_unregister_thread      \
+               rcu_defer_unregister_thread_bp
+#define alias_rcu_defer_barrier                rcu_defer_barrier_bp
+#define alias_rcu_defer_barrier_thread rcu_defer_barrier_thread_bp
+#define alias_rcu_defer_exit           rcu_defer_exit_bp
+
+#define alias_urcu_register_rculfhash_atfork   \
+               urcu_register_rculfhash_atfork_bp
+#define alias_urcu_unregister_rculfhash_atfork \
+               urcu_unregister_rculfhash_atfork_bp
diff --git a/include/urcu/map/urcu-mb.h b/include/urcu/map/urcu-mb.h
new file mode 100644 (file)
index 0000000..fa77a1a
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * urcu/map/urcu-mb.h
+ *
+ * Userspace RCU header -- name mapping to allow multiple flavors to be
+ * used in the same executable.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#define rcu_read_lock                  urcu_mb_read_lock
+#define _rcu_read_lock                 _urcu_mb_read_lock
+#define rcu_read_unlock                        urcu_mb_read_unlock
+#define _rcu_read_unlock               _urcu_mb_read_unlock
+#define rcu_read_ongoing               urcu_mb_read_ongoing
+#define _rcu_read_ongoing              _urcu_mb_read_ongoing
+#define rcu_quiescent_state            urcu_mb_quiescent_state
+#define _rcu_quiescent_state           _urcu_mb_quiescent_state
+#define rcu_thread_offline             urcu_mb_thread_offline
+#define rcu_thread_online              urcu_mb_thread_online
+#define rcu_register_thread            urcu_mb_register_thread
+#define rcu_unregister_thread          urcu_mb_unregister_thread
+#define rcu_init                       urcu_mb_init
+#define rcu_exit                       urcu_mb_exit
+#define synchronize_rcu                        urcu_mb_synchronize_rcu
+#define rcu_reader                     urcu_mb_reader
+#define rcu_gp                         urcu_mb_gp
+
+#define get_cpu_call_rcu_data          urcu_mb_get_cpu_call_rcu_data
+#define get_call_rcu_thread            urcu_mb_get_call_rcu_thread
+#define create_call_rcu_data           urcu_mb_create_call_rcu_data
+#define set_cpu_call_rcu_data          urcu_mb_set_cpu_call_rcu_data
+#define get_default_call_rcu_data      urcu_mb_get_default_call_rcu_data
+#define get_call_rcu_data              urcu_mb_get_call_rcu_data
+#define get_thread_call_rcu_data       urcu_mb_get_thread_call_rcu_data
+#define set_thread_call_rcu_data       urcu_mb_set_thread_call_rcu_data
+#define create_all_cpu_call_rcu_data   urcu_mb_create_all_cpu_call_rcu_data
+#define free_all_cpu_call_rcu_data     urcu_mb_free_all_cpu_call_rcu_data
+#define call_rcu                       urcu_mb_call_rcu
+#define call_rcu_data_free             urcu_mb_call_rcu_data_free
+#define call_rcu_before_fork           urcu_mb_call_rcu_before_fork
+#define call_rcu_after_fork_parent     urcu_mb_call_rcu_after_fork_parent
+#define call_rcu_after_fork_child      urcu_mb_call_rcu_after_fork_child
+#define rcu_barrier                    urcu_mb_barrier
+
+#define defer_rcu                      urcu_mb_defer_rcu
+#define rcu_defer_register_thread      urcu_mb_defer_register_thread
+#define rcu_defer_unregister_thread    urcu_mb_defer_unregister_thread
+#define rcu_defer_barrier              urcu_mb_defer_barrier
+#define rcu_defer_barrier_thread       urcu_mb_defer_barrier_thread
+#define rcu_defer_exit                 urcu_mb_defer_exit
+
+#define rcu_flavor                     urcu_mb_flavor
+
+#define urcu_register_rculfhash_atfork         \
+               urcu_mb_register_rculfhash_atfork
+#define urcu_unregister_rculfhash_atfork       \
+               urcu_mb_unregister_rculfhash_atfork
+
+
+/* Aliases for ABI(6) compat */
+
+#define alias_rcu_flavor               rcu_flavor_mb
+
+/* src/urcu.c */
+#define alias_rcu_read_lock            rcu_read_lock_mb
+#define alias_rcu_read_unlock          rcu_read_unlock_mb
+#define alias_rcu_read_ongoing         rcu_read_ongoing_mb
+#define alias_rcu_register_thread      rcu_register_thread_mb
+#define alias_rcu_unregister_thread    rcu_unregister_thread_mb
+#define alias_rcu_init                 rcu_init_mb
+#define alias_synchronize_rcu          synchronize_rcu_mb
+#define alias_rcu_reader               rcu_reader_mb
+#define alias_rcu_gp                   rcu_gp_mb
+
+/* src/urcu-call-rcu-impl.h */
+#define alias_get_cpu_call_rcu_data    get_cpu_call_rcu_data_mb
+#define alias_get_call_rcu_thread      get_call_rcu_thread_mb
+#define alias_create_call_rcu_data     create_call_rcu_data_mb
+#define alias_set_cpu_call_rcu_data    set_cpu_call_rcu_data_mb
+#define alias_get_default_call_rcu_data        get_default_call_rcu_data_mb
+#define alias_get_call_rcu_data                get_call_rcu_data_mb
+#define alias_get_thread_call_rcu_data get_thread_call_rcu_data_mb
+#define alias_set_thread_call_rcu_data set_thread_call_rcu_data_mb
+#define alias_create_all_cpu_call_rcu_data     \
+               create_all_cpu_call_rcu_data_mb
+#define alias_free_all_cpu_call_rcu_data       \
+               free_all_cpu_call_rcu_data_mb
+#define alias_call_rcu                 call_rcu_mb
+#define alias_call_rcu_data_free       call_rcu_data_free_mb
+#define alias_call_rcu_before_fork     call_rcu_before_fork_mb
+#define alias_call_rcu_after_fork_parent       \
+               call_rcu_after_fork_parent_mb
+#define alias_call_rcu_after_fork_child        call_rcu_after_fork_child_mb
+#define alias_rcu_barrier              rcu_barrier_mb
+
+#define alias_urcu_register_rculfhash_atfork   \
+               urcu_register_rculfhash_atfork_mb
+#define alias_urcu_unregister_rculfhash_atfork \
+               urcu_unregister_rculfhash_atfork_mb
+
+/* src/urcu-defer-impl.h */
+#define alias_defer_rcu                        defer_rcu_mb
+#define alias_rcu_defer_register_thread        rcu_defer_register_thread_mb
+#define alias_rcu_defer_unregister_thread      \
+               rcu_defer_unregister_thread_mb
+#define alias_rcu_defer_barrier                rcu_defer_barrier_mb
+#define alias_rcu_defer_barrier_thread rcu_defer_barrier_thread_mb
+#define alias_rcu_defer_exit           rcu_defer_exit_mb
diff --git a/include/urcu/map/urcu-memb.h b/include/urcu/map/urcu-memb.h
new file mode 100644 (file)
index 0000000..33f9a9b
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * urcu/map/urcu-memb.h
+ *
+ * Userspace RCU header -- name mapping to allow multiple flavors to be
+ * used in the same executable.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#define rcu_read_lock                  urcu_memb_read_lock
+#define _rcu_read_lock                 _urcu_memb_read_lock
+#define rcu_read_unlock                        urcu_memb_read_unlock
+#define _rcu_read_unlock               _urcu_memb_read_unlock
+#define rcu_read_ongoing               urcu_memb_read_ongoing
+#define _rcu_read_ongoing              _urcu_memb_read_ongoing
+#define rcu_quiescent_state            urcu_memb_quiescent_state
+#define _rcu_quiescent_state           _urcu_memb_quiescent_state
+#define rcu_thread_offline             urcu_memb_thread_offline
+#define rcu_thread_online              urcu_memb_thread_online
+#define rcu_register_thread            urcu_memb_register_thread
+#define rcu_unregister_thread          urcu_memb_unregister_thread
+#define rcu_init                       urcu_memb_init
+#define rcu_exit                       urcu_memb_exit
+#define synchronize_rcu                        urcu_memb_synchronize_rcu
+#define rcu_reader                     urcu_memb_reader
+#define rcu_gp                         urcu_memb_gp
+
+#define get_cpu_call_rcu_data          urcu_memb_get_cpu_call_rcu_data
+#define get_call_rcu_thread            urcu_memb_get_call_rcu_thread
+#define create_call_rcu_data           urcu_memb_create_call_rcu_data
+#define set_cpu_call_rcu_data          urcu_memb_set_cpu_call_rcu_data
+#define get_default_call_rcu_data      urcu_memb_get_default_call_rcu_data
+#define get_call_rcu_data              urcu_memb_get_call_rcu_data
+#define get_thread_call_rcu_data       urcu_memb_get_thread_call_rcu_data
+#define set_thread_call_rcu_data       urcu_memb_set_thread_call_rcu_data
+#define create_all_cpu_call_rcu_data   urcu_memb_create_all_cpu_call_rcu_data
+#define free_all_cpu_call_rcu_data     urcu_memb_free_all_cpu_call_rcu_data
+#define call_rcu                       urcu_memb_call_rcu
+#define call_rcu_data_free             urcu_memb_call_rcu_data_free
+#define call_rcu_before_fork           urcu_memb_call_rcu_before_fork
+#define call_rcu_after_fork_parent     urcu_memb_call_rcu_after_fork_parent
+#define call_rcu_after_fork_child      urcu_memb_call_rcu_after_fork_child
+#define rcu_barrier                    urcu_memb_barrier
+
+#define defer_rcu                      urcu_memb_defer_rcu
+#define rcu_defer_register_thread      urcu_memb_defer_register_thread
+#define rcu_defer_unregister_thread    urcu_memb_defer_unregister_thread
+#define rcu_defer_barrier              urcu_memb_defer_barrier
+#define rcu_defer_barrier_thread       urcu_memb_defer_barrier_thread
+#define rcu_defer_exit                 urcu_memb_defer_exit
+
+#define rcu_flavor                     urcu_memb_flavor
+
+#define urcu_register_rculfhash_atfork         \
+               urcu_memb_register_rculfhash_atfork
+#define urcu_unregister_rculfhash_atfork       \
+               urcu_memb_unregister_rculfhash_atfork
+
+
+/* Aliases for ABI(6) compat */
+
+#define alias_rcu_flavor               rcu_flavor_memb
+
+/* src/urcu.c */
+#define alias_rcu_read_lock            rcu_read_lock_memb
+#define alias_rcu_read_unlock          rcu_read_unlock_memb
+#define alias_rcu_read_ongoing         rcu_read_ongoing_memb
+#define alias_rcu_register_thread      rcu_register_thread_memb
+#define alias_rcu_unregister_thread    rcu_unregister_thread_memb
+#define alias_rcu_init                 rcu_init_memb
+#define alias_synchronize_rcu          synchronize_rcu_memb
+#define alias_rcu_reader               rcu_reader_memb
+#define alias_rcu_gp                   rcu_gp_memb
+
+/* src/urcu-call-rcu-impl.h */
+#define alias_get_cpu_call_rcu_data    get_cpu_call_rcu_data_memb
+#define alias_get_call_rcu_thread      get_call_rcu_thread_memb
+#define alias_create_call_rcu_data     create_call_rcu_data_memb
+#define alias_set_cpu_call_rcu_data    set_cpu_call_rcu_data_memb
+#define alias_get_default_call_rcu_data        get_default_call_rcu_data_memb
+#define alias_get_call_rcu_data                get_call_rcu_data_memb
+#define alias_get_thread_call_rcu_data get_thread_call_rcu_data_memb
+#define alias_set_thread_call_rcu_data set_thread_call_rcu_data_memb
+#define alias_create_all_cpu_call_rcu_data     \
+               create_all_cpu_call_rcu_data_memb
+#define alias_free_all_cpu_call_rcu_data       \
+               free_all_cpu_call_rcu_data_memb
+#define alias_call_rcu                 call_rcu_memb
+#define alias_call_rcu_data_free       call_rcu_data_free_memb
+#define alias_call_rcu_before_fork     call_rcu_before_fork_memb
+#define alias_call_rcu_after_fork_parent       \
+               call_rcu_after_fork_parent_memb
+#define alias_call_rcu_after_fork_child        call_rcu_after_fork_child_memb
+#define alias_rcu_barrier              rcu_barrier_memb
+
+#define alias_urcu_register_rculfhash_atfork   \
+               urcu_register_rculfhash_atfork_memb
+#define alias_urcu_unregister_rculfhash_atfork \
+               urcu_unregister_rculfhash_atfork_memb
+
+/* src/urcu-defer-impl.h */
+#define alias_defer_rcu                        defer_rcu_memb
+#define alias_rcu_defer_register_thread        rcu_defer_register_thread_memb
+#define alias_rcu_defer_unregister_thread      \
+               rcu_defer_unregister_thread_memb
+#define alias_rcu_defer_barrier                rcu_defer_barrier_memb
+#define alias_rcu_defer_barrier_thread rcu_defer_barrier_thread_memb
+#define alias_rcu_defer_exit           rcu_defer_exit_memb
index bf38c82..2b4d861 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef _URCU_QSBR_MAP_H
-#define _URCU_QSBR_MAP_H
-
 /*
- * urcu-map.h
+ * urcu/map/urcu-qsbr.h
  *
  * Userspace RCU header -- name mapping to allow multiple flavors to be
  * used in the same executable.
  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
  */
 
-/* Mapping macros to allow multiple flavors in a single binary. */
-
-#define rcu_read_lock                  rcu_read_lock_qsbr
-#define _rcu_read_lock                 _rcu_read_lock_qsbr
-#define rcu_read_unlock                        rcu_read_unlock_qsbr
-#define _rcu_read_unlock               _rcu_read_unlock_qsbr
-#define rcu_read_ongoing               rcu_read_ongoing_qsbr
-#define _rcu_read_ongoing              _rcu_read_ongoing_qsbr
-#define rcu_quiescent_state            rcu_quiescent_state_qsbr
-#define _rcu_quiescent_state           _rcu_quiescent_state_qsbr
-#define rcu_thread_offline             rcu_thread_offline_qsbr
-#define rcu_thread_online              rcu_thread_online_qsbr
-#define rcu_register_thread            rcu_register_thread_qsbr
-#define rcu_unregister_thread          rcu_unregister_thread_qsbr
-#define rcu_exit                       rcu_exit_qsbr
-#define synchronize_rcu                        synchronize_rcu_qsbr
-#define rcu_reader                     rcu_reader_qsbr
-#define rcu_gp                         rcu_gp_qsbr
+#define rcu_read_lock                  urcu_qsbr_read_lock
+#define _rcu_read_lock                 _urcu_qsbr_read_lock
+#define rcu_read_unlock                        urcu_qsbr_read_unlock
+#define _rcu_read_unlock               _urcu_qsbr_read_unlock
+#define rcu_read_ongoing               urcu_qsbr_read_ongoing
+#define _rcu_read_ongoing              _urcu_qsbr_read_ongoing
+#define rcu_quiescent_state            urcu_qsbr_quiescent_state
+#define _rcu_quiescent_state           _urcu_qsbr_quiescent_state
+#define rcu_thread_offline             urcu_qsbr_thread_offline
+#define rcu_thread_online              urcu_qsbr_thread_online
+#define rcu_register_thread            urcu_qsbr_register_thread
+#define rcu_unregister_thread          urcu_qsbr_unregister_thread
+#define rcu_exit                       urcu_qsbr_exit
+#define synchronize_rcu                        urcu_qsbr_synchronize_rcu
+#define rcu_reader                     urcu_qsbr_reader
+#define rcu_gp                         urcu_qsbr_gp
 
-#define get_cpu_call_rcu_data          get_cpu_call_rcu_data_qsbr
-#define get_call_rcu_thread            get_call_rcu_thread_qsbr
-#define create_call_rcu_data           create_call_rcu_data_qsbr
-#define set_cpu_call_rcu_data          set_cpu_call_rcu_data_qsbr
-#define get_default_call_rcu_data      get_default_call_rcu_data_qsbr
-#define get_call_rcu_data              get_call_rcu_data_qsbr
-#define get_thread_call_rcu_data       get_thread_call_rcu_data_qsbr
-#define set_thread_call_rcu_data       set_thread_call_rcu_data_qsbr
-#define create_all_cpu_call_rcu_data   create_all_cpu_call_rcu_data_qsbr
-#define call_rcu                       call_rcu_qsbr
-#define call_rcu_data_free             call_rcu_data_free_qsbr
-#define call_rcu_before_fork           call_rcu_before_fork_qsbr
-#define call_rcu_after_fork_parent     call_rcu_after_fork_parent_qsbr
-#define call_rcu_after_fork_child      call_rcu_after_fork_child_qsbr
-#define rcu_barrier                    rcu_barrier_qsbr
+#define get_cpu_call_rcu_data          urcu_qsbr_get_cpu_call_rcu_data
+#define get_call_rcu_thread            urcu_qsbr_get_call_rcu_thread
+#define create_call_rcu_data           urcu_qsbr_create_call_rcu_data
+#define set_cpu_call_rcu_data          urcu_qsbr_set_cpu_call_rcu_data
+#define get_default_call_rcu_data      urcu_qsbr_get_default_call_rcu_data
+#define get_call_rcu_data              urcu_qsbr_get_call_rcu_data
+#define get_thread_call_rcu_data       urcu_qsbr_get_thread_call_rcu_data
+#define set_thread_call_rcu_data       urcu_qsbr_set_thread_call_rcu_data
+#define create_all_cpu_call_rcu_data   urcu_qsbr_create_all_cpu_call_rcu_data
+#define free_all_cpu_call_rcu_data     urcu_qsbr_free_all_cpu_call_rcu_data
+#define call_rcu                       urcu_qsbr_call_rcu
+#define call_rcu_data_free             urcu_qsbr_call_rcu_data_free
+#define call_rcu_before_fork           urcu_qsbr_call_rcu_before_fork
+#define call_rcu_after_fork_parent     urcu_qsbr_call_rcu_after_fork_parent
+#define call_rcu_after_fork_child      urcu_qsbr_call_rcu_after_fork_child
+#define rcu_barrier                    urcu_qsbr_barrier
 
-#define defer_rcu                      defer_rcu_qsbr
-#define rcu_defer_register_thread      rcu_defer_register_thread_qsbr
-#define rcu_defer_unregister_thread    rcu_defer_unregister_thread_qsbr
-#define        rcu_defer_barrier               rcu_defer_barrier_qsbr
-#define rcu_defer_barrier_thread       rcu_defer_barrier_thread_qsbr
-#define rcu_defer_exit                 rcu_defer_exit_qsbr
+#define defer_rcu                      urcu_qsbr_defer_rcu
+#define rcu_defer_register_thread      urcu_qsbr_defer_register_thread
+#define rcu_defer_unregister_thread    urcu_qsbr_defer_unregister_thread
+#define        rcu_defer_barrier               urcu_qsbr_defer_barrier
+#define rcu_defer_barrier_thread       urcu_qsbr_defer_barrier_thread
+#define rcu_defer_exit                 urcu_qsbr_defer_exit
 
-#define rcu_flavor                     rcu_flavor_qsbr
+#define rcu_flavor                     urcu_qsbr_flavor
 
 #define urcu_register_rculfhash_atfork         \
-               urcu_register_rculfhash_atfork_qsbr
+               urcu_qsbr_register_rculfhash_atfork
 #define urcu_unregister_rculfhash_atfork       \
+               urcu_qsbr_unregister_rculfhash_atfork
+
+/* Aliases for ABI(6) compat */
+
+#define alias_rcu_flavor               rcu_flavor_qsbr
+
+/* src/urcu.c */
+#define alias_rcu_read_lock            rcu_read_lock_qsbr
+#define alias_rcu_read_unlock          rcu_read_unlock_qsbr
+#define alias_rcu_read_ongoing         rcu_read_ongoing_qsbr
+#define alias_rcu_register_thread      rcu_register_thread_qsbr
+#define alias_rcu_unregister_thread    rcu_unregister_thread_qsbr
+#define alias_rcu_init                 rcu_init_qsbr
+#define alias_synchronize_rcu          synchronize_rcu_qsbr
+#define alias_rcu_reader               rcu_reader_qsbr
+#define alias_rcu_gp                   rcu_gp_qsbr
+
+/* src/urcu-call-rcu-impl.h */
+#define alias_get_cpu_call_rcu_data    get_cpu_call_rcu_data_qsbr
+#define alias_get_call_rcu_thread      get_call_rcu_thread_qsbr
+#define alias_create_call_rcu_data     create_call_rcu_data_qsbr
+#define alias_set_cpu_call_rcu_data    set_cpu_call_rcu_data_qsbr
+#define alias_get_default_call_rcu_data        get_default_call_rcu_data_qsbr
+#define alias_get_call_rcu_data                get_call_rcu_data_qsbr
+#define alias_get_thread_call_rcu_data get_thread_call_rcu_data_qsbr
+#define alias_set_thread_call_rcu_data set_thread_call_rcu_data_qsbr
+#define alias_create_all_cpu_call_rcu_data     \
+               create_all_cpu_call_rcu_data_qsbr
+#define alias_free_all_cpu_call_rcu_data       \
+               free_all_cpu_call_rcu_data_qsbr
+#define alias_call_rcu                 call_rcu_qsbr
+#define alias_call_rcu_data_free       call_rcu_data_free_qsbr
+#define alias_call_rcu_before_fork     call_rcu_before_fork_qsbr
+#define alias_call_rcu_after_fork_parent       \
+               call_rcu_after_fork_parent_qsbr
+#define alias_call_rcu_after_fork_child        call_rcu_after_fork_child_qsbr
+#define alias_rcu_barrier              rcu_barrier_qsbr
+
+#define alias_urcu_register_rculfhash_atfork   \
+               urcu_register_rculfhash_atfork_qsbr
+#define alias_urcu_unregister_rculfhash_atfork \
                urcu_unregister_rculfhash_atfork_qsbr
 
-#endif /* _URCU_QSBR_MAP_H */
+/* src/urcu-defer-impl.h */
+#define alias_defer_rcu                        defer_rcu_qsbr
+#define alias_rcu_defer_register_thread        rcu_defer_register_thread_qsbr
+#define alias_rcu_defer_unregister_thread      \
+               rcu_defer_unregister_thread_qsbr
+#define alias_rcu_defer_barrier                rcu_defer_barrier_qsbr
+#define alias_rcu_defer_barrier_thread rcu_defer_barrier_thread_qsbr
+#define alias_rcu_defer_exit           rcu_defer_exit_qsbr
diff --git a/include/urcu/map/urcu-signal.h b/include/urcu/map/urcu-signal.h
new file mode 100644 (file)
index 0000000..842a14f
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * urcu/map/urcu-signal.h
+ *
+ * Userspace RCU header -- name mapping to allow multiple flavors to be
+ * used in the same executable.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#define rcu_read_lock                  urcu_signal_read_lock
+#define _rcu_read_lock                 _urcu_signal_read_lock
+#define rcu_read_unlock                        urcu_signal_read_unlock
+#define _rcu_read_unlock               _urcu_signal_read_unlock
+#define rcu_read_ongoing               urcu_signal_read_ongoing
+#define _rcu_read_ongoing              _urcu_signal_read_ongoing
+#define rcu_quiescent_state            urcu_signal_quiescent_state
+#define _rcu_quiescent_state           _urcu_signal_quiescent_state
+#define rcu_thread_offline             urcu_signal_thread_offline
+#define rcu_thread_online              urcu_signal_thread_online
+#define rcu_register_thread            urcu_signal_register_thread
+#define rcu_unregister_thread          urcu_signal_unregister_thread
+#define rcu_init                       urcu_signal_init
+#define rcu_exit                       urcu_signal_exit
+#define synchronize_rcu                        urcu_signal_synchronize_rcu
+#define rcu_reader                     urcu_signal_reader
+#define rcu_gp                         urcu_signal_gp
+
+#define get_cpu_call_rcu_data          urcu_signal_get_cpu_call_rcu_data
+#define get_call_rcu_thread            urcu_signal_get_call_rcu_thread
+#define create_call_rcu_data           urcu_signal_create_call_rcu_data
+#define set_cpu_call_rcu_data          urcu_signal_set_cpu_call_rcu_data
+#define get_default_call_rcu_data      urcu_signal_get_default_call_rcu_data
+#define get_call_rcu_data              urcu_signal_get_call_rcu_data
+#define get_thread_call_rcu_data       urcu_signal_get_thread_call_rcu_data
+#define set_thread_call_rcu_data       urcu_signal_set_thread_call_rcu_data
+#define create_all_cpu_call_rcu_data   urcu_signal_create_all_cpu_call_rcu_data
+#define free_all_cpu_call_rcu_data     urcu_signal_free_all_cpu_call_rcu_data
+#define call_rcu                       urcu_signal_call_rcu
+#define call_rcu_data_free             urcu_signal_call_rcu_data_free
+#define call_rcu_before_fork           urcu_signal_call_rcu_before_fork
+#define call_rcu_after_fork_parent     urcu_signal_call_rcu_after_fork_parent
+#define call_rcu_after_fork_child      urcu_signal_call_rcu_after_fork_child
+#define rcu_barrier                    urcu_signal_barrier
+
+#define defer_rcu                      urcu_signal_defer_rcu
+#define rcu_defer_register_thread      urcu_signal_defer_register_thread
+#define rcu_defer_unregister_thread    urcu_signal_defer_unregister_thread
+#define rcu_defer_barrier              urcu_signal_defer_barrier
+#define rcu_defer_barrier_thread       urcu_signal_defer_barrier_thread
+#define rcu_defer_exit                 urcu_signal_defer_exit
+
+#define rcu_flavor                     urcu_signal_flavor
+
+#define urcu_register_rculfhash_atfork         \
+               urcu_signal_register_rculfhash_atfork
+#define urcu_unregister_rculfhash_atfork       \
+               urcu_signal_unregister_rculfhash_atfork
+
+
+/* Aliases for ABI(6) compat */
+
+#define alias_rcu_flavor               rcu_flavor_sig
+
+/* src/urcu.c */
+#define alias_rcu_read_lock            rcu_read_lock_sig
+#define alias_rcu_read_unlock          rcu_read_unlock_sig
+#define alias_rcu_read_ongoing         rcu_read_ongoing_sig
+#define alias_rcu_register_thread      rcu_register_thread_sig
+#define alias_rcu_unregister_thread    rcu_unregister_thread_sig
+#define alias_rcu_init                 rcu_init_sig
+#define alias_rcu_exit                 rcu_exit_sig
+#define alias_synchronize_rcu          synchronize_rcu_sig
+#define alias_rcu_reader               rcu_reader_sig
+#define alias_rcu_gp                   rcu_gp_sig
+
+/* src/urcu-call-rcu-impl.h */
+#define alias_get_cpu_call_rcu_data    get_cpu_call_rcu_data_sig
+#define alias_get_call_rcu_thread      get_call_rcu_thread_sig
+#define alias_create_call_rcu_data     create_call_rcu_data_sig
+#define alias_set_cpu_call_rcu_data    set_cpu_call_rcu_data_sig
+#define alias_get_default_call_rcu_data        get_default_call_rcu_data_sig
+#define alias_get_call_rcu_data                get_call_rcu_data_sig
+#define alias_get_thread_call_rcu_data get_thread_call_rcu_data_sig
+#define alias_set_thread_call_rcu_data set_thread_call_rcu_data_sig
+#define alias_create_all_cpu_call_rcu_data     \
+               create_all_cpu_call_rcu_data_sig
+#define alias_free_all_cpu_call_rcu_data       \
+               free_all_cpu_call_rcu_data_sig
+#define alias_call_rcu                 call_rcu_sig
+#define alias_call_rcu_data_free       call_rcu_data_free_sig
+#define alias_call_rcu_before_fork     call_rcu_before_fork_sig
+#define alias_call_rcu_after_fork_parent       \
+               call_rcu_after_fork_parent_sig
+#define alias_call_rcu_after_fork_child        call_rcu_after_fork_child_sig
+#define alias_rcu_barrier              rcu_barrier_sig
+
+#define alias_urcu_register_rculfhash_atfork   \
+               urcu_register_rculfhash_atfork_sig
+#define alias_urcu_unregister_rculfhash_atfork \
+               urcu_unregister_rculfhash_atfork_sig
+
+/* src/urcu-defer-impl.h */
+#define alias_defer_rcu                        defer_rcu_sig
+#define alias_rcu_defer_register_thread        rcu_defer_register_thread_sig
+#define alias_rcu_defer_unregister_thread      \
+               rcu_defer_unregister_thread_sig
+#define alias_rcu_defer_barrier                rcu_defer_barrier_sig
+#define alias_rcu_defer_barrier_thread rcu_defer_barrier_thread_sig
+#define alias_rcu_defer_exit           rcu_defer_exit_sig
index b12fa74..a2fb7c8 100644 (file)
@@ -1,6 +1,3 @@
-#ifndef _URCU_MAP_H
-#define _URCU_MAP_H
-
 /*
  * urcu-map.h
  *
  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
  */
 
-/* Mapping macros to allow multiple flavors in a single binary. */
-
-#if !defined(RCU_MEMBARRIER) && !defined(RCU_SIGNAL) && !defined(RCU_MB)
-#define RCU_MEMBARRIER
-#endif
-
 #ifdef RCU_MEMBARRIER
-
-#define rcu_read_lock                  rcu_read_lock_memb
-#define _rcu_read_lock                 _rcu_read_lock_memb
-#define rcu_read_unlock                        rcu_read_unlock_memb
-#define _rcu_read_unlock               _rcu_read_unlock_memb
-#define rcu_read_ongoing               rcu_read_ongoing_memb
-#define _rcu_read_ongoing              _rcu_read_ongoing_memb
-#define rcu_register_thread            rcu_register_thread_memb
-#define rcu_unregister_thread          rcu_unregister_thread_memb
-#define rcu_init                       rcu_init_memb
-#define rcu_exit                       rcu_exit_memb
-#define synchronize_rcu                        synchronize_rcu_memb
-#define rcu_reader                     rcu_reader_memb
-#define rcu_gp                         rcu_gp_memb
-
-#define get_cpu_call_rcu_data          get_cpu_call_rcu_data_memb
-#define get_call_rcu_thread            get_call_rcu_thread_memb
-#define create_call_rcu_data           create_call_rcu_data_memb
-#define set_cpu_call_rcu_data          set_cpu_call_rcu_data_memb
-#define get_default_call_rcu_data      get_default_call_rcu_data_memb
-#define get_call_rcu_data              get_call_rcu_data_memb
-#define get_thread_call_rcu_data       get_thread_call_rcu_data_memb
-#define set_thread_call_rcu_data       set_thread_call_rcu_data_memb
-#define create_all_cpu_call_rcu_data   create_all_cpu_call_rcu_data_memb
-#define free_all_cpu_call_rcu_data     free_all_cpu_call_rcu_data_memb
-#define call_rcu                       call_rcu_memb
-#define call_rcu_data_free             call_rcu_data_free_memb
-#define call_rcu_before_fork           call_rcu_before_fork_memb
-#define call_rcu_after_fork_parent     call_rcu_after_fork_parent_memb
-#define call_rcu_after_fork_child      call_rcu_after_fork_child_memb
-#define rcu_barrier                    rcu_barrier_memb
-
-#define defer_rcu                      defer_rcu_memb
-#define rcu_defer_register_thread      rcu_defer_register_thread_memb
-#define rcu_defer_unregister_thread    rcu_defer_unregister_thread_memb
-#define rcu_defer_barrier              rcu_defer_barrier_memb
-#define rcu_defer_barrier_thread       rcu_defer_barrier_thread_memb
-#define rcu_defer_exit                 rcu_defer_exit_memb
-
-#define rcu_flavor                     rcu_flavor_memb
-
-#define urcu_register_rculfhash_atfork         \
-               urcu_register_rculfhash_atfork_memb
-#define urcu_unregister_rculfhash_atfork       \
-               urcu_unregister_rculfhash_atfork_memb
-
+#include <urcu/map/urcu-memb.h>
 #elif defined(RCU_SIGNAL)
-
-#define rcu_read_lock                  rcu_read_lock_sig
-#define _rcu_read_lock                 _rcu_read_lock_sig
-#define rcu_read_unlock                        rcu_read_unlock_sig
-#define _rcu_read_unlock               _rcu_read_unlock_sig
-#define rcu_read_ongoing               rcu_read_ongoing_sig
-#define _rcu_read_ongoing              _rcu_read_ongoing_sig
-#define rcu_register_thread            rcu_register_thread_sig
-#define rcu_unregister_thread          rcu_unregister_thread_sig
-#define rcu_init                       rcu_init_sig
-#define rcu_exit                       rcu_exit_sig
-#define synchronize_rcu                        synchronize_rcu_sig
-#define rcu_reader                     rcu_reader_sig
-#define rcu_gp                         rcu_gp_sig
-
-#define get_cpu_call_rcu_data          get_cpu_call_rcu_data_sig
-#define get_call_rcu_thread            get_call_rcu_thread_sig
-#define create_call_rcu_data           create_call_rcu_data_sig
-#define set_cpu_call_rcu_data          set_cpu_call_rcu_data_sig
-#define get_default_call_rcu_data      get_default_call_rcu_data_sig
-#define get_call_rcu_data              get_call_rcu_data_sig
-#define get_thread_call_rcu_data       get_thread_call_rcu_data_sig
-#define set_thread_call_rcu_data       set_thread_call_rcu_data_sig
-#define create_all_cpu_call_rcu_data   create_all_cpu_call_rcu_data_sig
-#define free_all_cpu_call_rcu_data     free_all_cpu_call_rcu_data_sig
-#define call_rcu                       call_rcu_sig
-#define call_rcu_data_free             call_rcu_data_free_sig
-#define call_rcu_before_fork           call_rcu_before_fork_sig
-#define call_rcu_after_fork_parent     call_rcu_after_fork_parent_sig
-#define call_rcu_after_fork_child      call_rcu_after_fork_child_sig
-#define rcu_barrier                    rcu_barrier_sig
-
-#define defer_rcu                      defer_rcu_sig
-#define rcu_defer_register_thread      rcu_defer_register_thread_sig
-#define rcu_defer_unregister_thread    rcu_defer_unregister_thread_sig
-#define rcu_defer_barrier              rcu_defer_barrier_sig
-#define rcu_defer_barrier_thread       rcu_defer_barrier_thread_sig
-#define rcu_defer_exit                 rcu_defer_exit_sig
-
-#define rcu_flavor                     rcu_flavor_sig
-
-#define urcu_register_rculfhash_atfork         \
-               urcu_register_rculfhash_atfork_sig
-#define urcu_unregister_rculfhash_atfork       \
-               urcu_unregister_rculfhash_atfork_sig
-
+#include <urcu/map/urcu-signal.h>
 #elif defined(RCU_MB)
-
-#define rcu_read_lock                  rcu_read_lock_mb
-#define _rcu_read_lock                 _rcu_read_lock_mb
-#define rcu_read_unlock                        rcu_read_unlock_mb
-#define _rcu_read_unlock               _rcu_read_unlock_mb
-#define rcu_read_ongoing               rcu_read_ongoing_mb
-#define _rcu_read_ongoing              _rcu_read_ongoing_mb
-#define rcu_register_thread            rcu_register_thread_mb
-#define rcu_unregister_thread          rcu_unregister_thread_mb
-#define rcu_init                       rcu_init_mb
-#define rcu_exit                       rcu_exit_mb
-#define synchronize_rcu                        synchronize_rcu_mb
-#define rcu_reader                     rcu_reader_mb
-#define rcu_gp                         rcu_gp_mb
-
-#define get_cpu_call_rcu_data          get_cpu_call_rcu_data_mb
-#define get_call_rcu_thread            get_call_rcu_thread_mb
-#define create_call_rcu_data           create_call_rcu_data_mb
-#define set_cpu_call_rcu_data          set_cpu_call_rcu_data_mb
-#define get_default_call_rcu_data      get_default_call_rcu_data_mb
-#define get_call_rcu_data              get_call_rcu_data_mb
-#define get_thread_call_rcu_data       get_thread_call_rcu_data_mb
-#define set_thread_call_rcu_data       set_thread_call_rcu_data_mb
-#define create_all_cpu_call_rcu_data   create_all_cpu_call_rcu_data_mb
-#define free_all_cpu_call_rcu_data     free_all_cpu_call_rcu_data_mb
-#define call_rcu                       call_rcu_mb
-#define call_rcu_data_free             call_rcu_data_free_mb
-#define call_rcu_before_fork           call_rcu_before_fork_mb
-#define call_rcu_after_fork_parent     call_rcu_after_fork_parent_mb
-#define call_rcu_after_fork_child      call_rcu_after_fork_child_mb
-#define rcu_barrier                    rcu_barrier_mb
-
-#define defer_rcu                      defer_rcu_mb
-#define rcu_defer_register_thread      rcu_defer_register_thread_mb
-#define rcu_defer_unregister_thread    rcu_defer_unregister_thread_mb
-#define rcu_defer_barrier              rcu_defer_barrier_mb
-#define rcu_defer_barrier_thread       rcu_defer_barrier_thread_mb
-#define rcu_defer_exit                 rcu_defer_exit_mb
-
-#define rcu_flavor                     rcu_flavor_mb
-
-#define urcu_register_rculfhash_atfork         \
-               urcu_register_rculfhash_atfork_mb
-#define urcu_unregister_rculfhash_atfork       \
-               urcu_unregister_rculfhash_atfork_mb
-
+#include <urcu/map/urcu-mb.h>
 #else
-
 #error "Undefined selection"
-
 #endif
-
-#endif /* _URCU_MAP_H */
diff --git a/include/urcu/pointer.h b/include/urcu/pointer.h
new file mode 100644 (file)
index 0000000..dc1a0da
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _URCU_POINTER_H
+#define _URCU_POINTER_H
+
+/*
+ * urcu-pointer.h
+ *
+ * Userspace RCU header. Operations on pointers.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+#include <urcu/uatomic.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)
+
+#include <urcu/static/urcu-pointer.h>
+
+/*
+ * rcu_dereference(ptr)
+ *
+ * Fetch a RCU-protected pointer. Typically used to copy the variable ptr to a
+ * local variable.
+ */
+#define rcu_dereference                _rcu_dereference
+
+/*
+ * type *rcu_cmpxchg_pointer(type **ptr, type *new, type *old)
+ * type *rcu_xchg_pointer(type **ptr, type *new)
+ * void rcu_set_pointer(type **ptr, type *new)
+ *
+ * RCU pointer updates.
+ * @ptr: address of the pointer to modify
+ * @new: new pointer value
+ * @old: old pointer value (expected)
+ *
+ * return: old pointer value
+ */
+#define rcu_cmpxchg_pointer    _rcu_cmpxchg_pointer
+#define rcu_xchg_pointer       _rcu_xchg_pointer
+#define rcu_set_pointer                _rcu_set_pointer
+
+#else /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
+
+extern void *rcu_dereference_sym(void *p);
+#define rcu_dereference(p)                                                  \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(p) _________p1 =     URCU_FORCE_CAST(__typeof__(p), \
+                       rcu_dereference_sym(URCU_FORCE_CAST(void *, p)));    \
+               (_________p1);                                               \
+       })
+
+extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new);
+#define rcu_cmpxchg_pointer(p, old, _new)                                   \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(*(p)) _________pold = (old);                      \
+               __typeof__(*(p)) _________pnew = (_new);                     \
+               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
+                       rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), \
+                                               _________pold,               \
+                                               _________pnew));             \
+               (_________p1);                                               \
+       })
+
+extern void *rcu_xchg_pointer_sym(void **p, void *v);
+#define rcu_xchg_pointer(p, v)                                              \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(*(p)) _________pv = (v);                          \
+               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
+                       rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p),    \
+                                            _________pv));                  \
+               (_________p1);                                               \
+       })
+
+/*
+ * Note: rcu_set_pointer_sym returns @v because we don't want to break
+ * the ABI. At the API level, rcu_set_pointer() now returns void. Use of
+ * the return value is therefore deprecated, and will cause a build
+ * error.
+ */
+extern void *rcu_set_pointer_sym(void **p, void *v);
+#define rcu_set_pointer(p, v)                                               \
+       do {                                                                 \
+               __typeof__(*(p)) _________pv = (v);                          \
+               (void) rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p),      \
+                                           _________pv);                    \
+       } while (0)
+
+#endif /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
+
+/*
+ * void rcu_assign_pointer(type *ptr, type *new)
+ *
+ * Same as rcu_set_pointer, but takes the pointer to assign to rather than its
+ * address as first parameter. Provided for compatibility with the Linux kernel
+ * RCU semantic.
+ */
+#define rcu_assign_pointer(p, v)       rcu_set_pointer((&p), (v))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_POINTER_H */
index 6bcfab4..8614d68 100644 (file)
 extern "C" {
 #endif
 
-enum rcu_state {
-       RCU_READER_ACTIVE_CURRENT,
-       RCU_READER_ACTIVE_OLD,
-       RCU_READER_INACTIVE,
+enum urcu_bp_state {
+       URCU_BP_READER_ACTIVE_CURRENT,
+       URCU_BP_READER_ACTIVE_OLD,
+       URCU_BP_READER_INACTIVE,
 };
 
 /*
- * The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we can use a
+ * The trick here is that URCU_BP_GP_CTR_PHASE must be a multiple of 8 so we can use a
  * full 8-bits, 16-bits or 32-bits bitmask for the lower order bits.
  */
-#define RCU_GP_COUNT           (1UL << 0)
+#define URCU_BP_GP_COUNT               (1UL << 0)
 /* Use the amount of bits equal to half of the architecture long size */
-#define RCU_GP_CTR_PHASE               (1UL << (sizeof(long) << 2))
-#define RCU_GP_CTR_NEST_MASK   (RCU_GP_CTR_PHASE - 1)
+#define URCU_BP_GP_CTR_PHASE           (1UL << (sizeof(long) << 2))
+#define URCU_BP_GP_CTR_NEST_MASK       (URCU_BP_GP_CTR_PHASE - 1)
 
 /*
- * Used internally by _rcu_read_lock.
+ * Used internally by _urcu_bp_read_lock.
  */
-extern void rcu_bp_register(void);
+extern void urcu_bp_register(void);
 
-struct rcu_gp {
+struct urcu_bp_gp {
        /*
         * Global grace period counter.
-        * Contains the current RCU_GP_CTR_PHASE.
-        * Also has a RCU_GP_COUNT of 1, to accelerate the reader fast path.
+        * Contains the current URCU_BP_GP_CTR_PHASE.
+        * Also has a URCU_BP_GP_COUNT of 1, to accelerate the reader fast path.
         * Written to only by writer with mutex taken.
         * Read by both writer and readers.
         */
        unsigned long ctr;
 } __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
 
-extern struct rcu_gp rcu_gp;
+extern struct urcu_bp_gp urcu_bp_gp;
 
-struct rcu_reader {
-       /* Data used by both reader and synchronize_rcu() */
+struct urcu_bp_reader {
+       /* Data used by both reader and urcu_bp_synchronize_rcu() */
        unsigned long ctr;
        /* Data used for registry */
        struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
@@ -101,7 +101,7 @@ struct rcu_reader {
  * Adds a pointer dereference on the read-side, but won't require to unregister
  * the reader thread.
  */
-extern DECLARE_URCU_TLS(struct rcu_reader *, rcu_reader);
+extern DECLARE_URCU_TLS(struct urcu_bp_reader *, urcu_bp_reader);
 
 #ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
 #define urcu_bp_has_sys_membarrier     1
@@ -117,60 +117,60 @@ static inline void urcu_bp_smp_mb_slave(void)
                cmm_smp_mb();
 }
 
-static inline enum rcu_state rcu_reader_state(unsigned long *ctr)
+static inline enum urcu_bp_state urcu_bp_reader_state(unsigned long *ctr)
 {
        unsigned long v;
 
        if (ctr == NULL)
-               return RCU_READER_INACTIVE;
+               return URCU_BP_READER_INACTIVE;
        /*
         * Make sure both tests below are done on the same version of *value
         * to insure consistency.
         */
        v = CMM_LOAD_SHARED(*ctr);
-       if (!(v & RCU_GP_CTR_NEST_MASK))
-               return RCU_READER_INACTIVE;
-       if (!((v ^ rcu_gp.ctr) & RCU_GP_CTR_PHASE))
-               return RCU_READER_ACTIVE_CURRENT;
-       return RCU_READER_ACTIVE_OLD;
+       if (!(v & URCU_BP_GP_CTR_NEST_MASK))
+               return URCU_BP_READER_INACTIVE;
+       if (!((v ^ urcu_bp_gp.ctr) & URCU_BP_GP_CTR_PHASE))
+               return URCU_BP_READER_ACTIVE_CURRENT;
+       return URCU_BP_READER_ACTIVE_OLD;
 }
 
 /*
- * Helper for _rcu_read_lock().  The format of rcu_gp.ctr (as well as
+ * Helper for _urcu_bp_read_lock().  The format of urcu_bp_gp.ctr (as well as
  * the per-thread rcu_reader.ctr) has the upper bits containing a count of
- * _rcu_read_lock() nesting, and a lower-order bit that contains either zero
- * or RCU_GP_CTR_PHASE.  The smp_mb_slave() ensures that the accesses in
- * _rcu_read_lock() happen before the subsequent read-side critical section.
+ * _urcu_bp_read_lock() nesting, and a lower-order bit that contains either zero
+ * or URCU_BP_GP_CTR_PHASE.  The smp_mb_slave() ensures that the accesses in
+ * _urcu_bp_read_lock() happen before the subsequent read-side critical section.
  */
-static inline void _rcu_read_lock_update(unsigned long tmp)
+static inline void _urcu_bp_read_lock_update(unsigned long tmp)
 {
-       if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader)->ctr, _CMM_LOAD_SHARED(rcu_gp.ctr));
+       if (caa_likely(!(tmp & URCU_BP_GP_CTR_NEST_MASK))) {
+               _CMM_STORE_SHARED(URCU_TLS(urcu_bp_reader)->ctr, _CMM_LOAD_SHARED(urcu_bp_gp.ctr));
                urcu_bp_smp_mb_slave();
        } else
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader)->ctr, tmp + RCU_GP_COUNT);
+               _CMM_STORE_SHARED(URCU_TLS(urcu_bp_reader)->ctr, tmp + URCU_BP_GP_COUNT);
 }
 
 /*
  * Enter an RCU read-side critical section.
  *
  * The first cmm_barrier() call ensures that the compiler does not reorder
- * the body of _rcu_read_lock() with a mutex.
+ * the body of _urcu_bp_read_lock() with a mutex.
  *
  * This function and its helper are both less than 10 lines long.  The
  * intent is that this function meets the 10-line criterion in LGPL,
  * allowing this function to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_lock(void)
+static inline void _urcu_bp_read_lock(void)
 {
        unsigned long tmp;
 
-       if (caa_unlikely(!URCU_TLS(rcu_reader)))
-               rcu_bp_register(); /* If not yet registered. */
+       if (caa_unlikely(!URCU_TLS(urcu_bp_reader)))
+               urcu_bp_register(); /* If not yet registered. */
        cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
-       tmp = URCU_TLS(rcu_reader)->ctr;
-       urcu_assert((tmp & RCU_GP_CTR_NEST_MASK) != RCU_GP_CTR_NEST_MASK);
-       _rcu_read_lock_update(tmp);
+       tmp = URCU_TLS(urcu_bp_reader)->ctr;
+       urcu_assert((tmp & URCU_BP_GP_CTR_NEST_MASK) != URCU_BP_GP_CTR_NEST_MASK);
+       _urcu_bp_read_lock_update(tmp);
 }
 
 /*
@@ -178,15 +178,15 @@ static inline void _rcu_read_lock(void)
  * 10 lines of code, and is intended to be usable by non-LGPL code, as
  * called out in LGPL.
  */
-static inline void _rcu_read_unlock(void)
+static inline void _urcu_bp_read_unlock(void)
 {
        unsigned long tmp;
 
-       tmp = URCU_TLS(rcu_reader)->ctr;
-       urcu_assert(tmp & RCU_GP_CTR_NEST_MASK);
+       tmp = URCU_TLS(urcu_bp_reader)->ctr;
+       urcu_assert(tmp & URCU_BP_GP_CTR_NEST_MASK);
        /* Finish using rcu before decrementing the pointer. */
        urcu_bp_smp_mb_slave();
-       _CMM_STORE_SHARED(URCU_TLS(rcu_reader)->ctr, tmp - RCU_GP_COUNT);
+       _CMM_STORE_SHARED(URCU_TLS(urcu_bp_reader)->ctr, tmp - URCU_BP_GP_COUNT);
        cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
 }
 
@@ -197,11 +197,11 @@ static inline void _rcu_read_unlock(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline int _rcu_read_ongoing(void)
+static inline int _urcu_bp_read_ongoing(void)
 {
-       if (caa_unlikely(!URCU_TLS(rcu_reader)))
-               rcu_bp_register(); /* If not yet registered. */
-       return URCU_TLS(rcu_reader)->ctr & RCU_GP_CTR_NEST_MASK;
+       if (caa_unlikely(!URCU_TLS(urcu_bp_reader)))
+               urcu_bp_register(); /* If not yet registered. */
+       return URCU_TLS(urcu_bp_reader)->ctr & URCU_BP_GP_CTR_NEST_MASK;
 }
 
 #ifdef __cplusplus
diff --git a/include/urcu/static/urcu-common.h b/include/urcu/static/urcu-common.h
new file mode 100644 (file)
index 0000000..28d3160
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef _URCU_COMMON_STATIC_H
+#define _URCU_COMMON_STATIC_H
+
+/*
+ * urcu-common-static.h
+ *
+ * Userspace RCU header.
+ *
+ * TO BE INCLUDED ONLY IN CODE THAT IS TO BE RECOMPILED ON EACH LIBURCU
+ * RELEASE. See urcu.h for linking dynamically with the userspace rcu library.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <urcu/config.h>
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+#include <urcu/system.h>
+#include <urcu/uatomic.h>
+#include <urcu/list.h>
+#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
+#include <urcu/debug.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum urcu_state {
+       URCU_READER_ACTIVE_CURRENT,
+       URCU_READER_ACTIVE_OLD,
+       URCU_READER_INACTIVE,
+};
+
+/*
+ * The trick here is that URCU_GP_CTR_PHASE must be a multiple of 8 so
+ * we can use a full 8-bits, 16-bits or 32-bits bitmask for the lower
+ * order bits.
+ */
+#define URCU_GP_COUNT          (1UL << 0)
+/* Use the amount of bits equal to half of the architecture long size */
+#define URCU_GP_CTR_PHASE      (1UL << (sizeof(unsigned long) << 2))
+#define URCU_GP_CTR_NEST_MASK  (URCU_GP_CTR_PHASE - 1)
+
+struct urcu_gp {
+       /*
+        * Global grace period counter.
+        * Contains the current URCU_GP_CTR_PHASE.
+        * Also has a URCU_GP_COUNT of 1, to accelerate the reader fast path.
+        * Written to only by writer with mutex taken.
+        * Read by both writer and readers.
+        */
+       unsigned long ctr;
+
+       int32_t futex;
+} __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
+
+struct urcu_reader {
+       /* Data used by both reader and synchronize_rcu() */
+       unsigned long ctr;
+       char need_mb;
+       /* Data used for registry */
+       struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
+       pthread_t tid;
+       /* Reader registered flag, for internal checks. */
+       unsigned int registered:1;
+};
+
+/*
+ * Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
+ */
+static inline void urcu_common_wake_up_gp(struct urcu_gp *gp)
+{
+       if (caa_unlikely(uatomic_read(&gp->futex) == -1)) {
+               uatomic_set(&gp->futex, 0);
+               /*
+                * Ignoring return value until we can make this function
+                * return something (because urcu_die() is not publicly
+                * exposed).
+                */
+               (void) futex_async(&gp->futex, FUTEX_WAKE, 1,
+                               NULL, NULL, 0);
+       }
+}
+
+static inline enum urcu_state urcu_common_reader_state(struct urcu_gp *gp,
+               unsigned long *ctr)
+{
+       unsigned long v;
+
+       /*
+        * Make sure both tests below are done on the same version of *value
+        * to insure consistency.
+        */
+       v = CMM_LOAD_SHARED(*ctr);
+       if (!(v & URCU_GP_CTR_NEST_MASK))
+               return URCU_READER_INACTIVE;
+       if (!((v ^ gp->ctr) & URCU_GP_CTR_PHASE))
+               return URCU_READER_ACTIVE_CURRENT;
+       return URCU_READER_ACTIVE_OLD;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_COMMON_STATIC_H */
diff --git a/include/urcu/static/urcu-mb.h b/include/urcu/static/urcu-mb.h
new file mode 100644 (file)
index 0000000..0dd7d42
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef _URCU_MB_STATIC_H
+#define _URCU_MB_STATIC_H
+
+/*
+ * urcu-mb-static.h
+ *
+ * Userspace RCU header.
+ *
+ * TO BE INCLUDED ONLY IN CODE THAT IS TO BE RECOMPILED ON EACH LIBURCU
+ * RELEASE. See urcu.h for linking dynamically with the userspace rcu library.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <urcu/config.h>
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+#include <urcu/system.h>
+#include <urcu/uatomic.h>
+#include <urcu/list.h>
+#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
+#include <urcu/debug.h>
+#include <urcu/static/urcu-common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This code section can only be included in LGPL 2.1 compatible source code.
+ * See below for the function call wrappers which can be used in code meant to
+ * be only linked with the Userspace RCU library. This comes with a small
+ * performance degradation on the read-side due to the added function calls.
+ * This is required to permit relinking with newer versions of the library.
+ */
+
+extern struct urcu_gp urcu_mb_gp;
+
+extern DECLARE_URCU_TLS(struct urcu_reader, urcu_mb_reader);
+
+/*
+ * Helper for _urcu_mb_read_lock().  The format of urcu_mb_gp.ctr (as well as
+ * the per-thread rcu_reader.ctr) has the upper bits containing a count of
+ * _urcu_mb_read_lock() nesting, and a lower-order bit that contains either zero
+ * or URCU_GP_CTR_PHASE.  The cmm_smp_mb() ensures that the accesses in
+ * _urcu_mb_read_lock() happen before the subsequent read-side critical section.
+ */
+static inline void _urcu_mb_read_lock_update(unsigned long tmp)
+{
+       if (caa_likely(!(tmp & URCU_GP_CTR_NEST_MASK))) {
+               _CMM_STORE_SHARED(URCU_TLS(urcu_mb_reader).ctr, _CMM_LOAD_SHARED(urcu_mb_gp.ctr));
+               cmm_smp_mb();
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_mb_reader).ctr, tmp + URCU_GP_COUNT);
+}
+
+/*
+ * Enter an RCU read-side critical section.
+ *
+ * The first cmm_barrier() call ensures that the compiler does not reorder
+ * the body of _urcu_mb_read_lock() with a mutex.
+ *
+ * This function and its helper are both less than 10 lines long.  The
+ * intent is that this function meets the 10-line criterion in LGPL,
+ * allowing this function to be invoked directly from non-LGPL code.
+ */
+static inline void _urcu_mb_read_lock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_mb_reader).registered);
+       cmm_barrier();
+       tmp = URCU_TLS(urcu_mb_reader).ctr;
+       urcu_assert((tmp & URCU_GP_CTR_NEST_MASK) != URCU_GP_CTR_NEST_MASK);
+       _urcu_mb_read_lock_update(tmp);
+}
+
+/*
+ * This is a helper function for _urcu_mb_read_unlock().
+ *
+ * The first cmm_smp_mb() call ensures that the critical section is
+ * seen to precede the store to rcu_reader.ctr.
+ * The second cmm_smp_mb() call ensures that we write to rcu_reader.ctr
+ * before reading the update-side futex.
+ */
+static inline void _urcu_mb_read_unlock_update_and_wakeup(unsigned long tmp)
+{
+       if (caa_likely((tmp & URCU_GP_CTR_NEST_MASK) == URCU_GP_COUNT)) {
+               cmm_smp_mb();
+               _CMM_STORE_SHARED(URCU_TLS(urcu_mb_reader).ctr, tmp - URCU_GP_COUNT);
+               cmm_smp_mb();
+               urcu_common_wake_up_gp(&urcu_mb_gp);
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_mb_reader).ctr, tmp - URCU_GP_COUNT);
+}
+
+/*
+ * Exit an RCU read-side crtical section.  Both this function and its
+ * helper are smaller than 10 lines of code, and are intended to be
+ * usable by non-LGPL code, as called out in LGPL.
+ */
+static inline void _urcu_mb_read_unlock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_mb_reader).registered);
+       tmp = URCU_TLS(urcu_mb_reader).ctr;
+       urcu_assert(tmp & URCU_GP_CTR_NEST_MASK);
+       _urcu_mb_read_unlock_update_and_wakeup(tmp);
+       cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
+}
+
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long.  The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _urcu_mb_read_ongoing(void)
+{
+       return URCU_TLS(urcu_mb_reader).ctr & URCU_GP_CTR_NEST_MASK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_MB_STATIC_H */
diff --git a/include/urcu/static/urcu-memb.h b/include/urcu/static/urcu-memb.h
new file mode 100644 (file)
index 0000000..a64efee
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef _URCU_MEMB_STATIC_H
+#define _URCU_MEMB_STATIC_H
+
+/*
+ * urcu-memb-static.h
+ *
+ * Userspace RCU header.
+ *
+ * TO BE INCLUDED ONLY IN CODE THAT IS TO BE RECOMPILED ON EACH LIBURCU
+ * RELEASE. See urcu.h for linking dynamically with the userspace rcu library.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <urcu/config.h>
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+#include <urcu/system.h>
+#include <urcu/uatomic.h>
+#include <urcu/list.h>
+#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
+#include <urcu/debug.h>
+#include <urcu/static/urcu-common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This code section can only be included in LGPL 2.1 compatible source code.
+ * See below for the function call wrappers which can be used in code meant to
+ * be only linked with the Userspace RCU library. This comes with a small
+ * performance degradation on the read-side due to the added function calls.
+ * This is required to permit relinking with newer versions of the library.
+ */
+
+/*
+ * Slave barriers are only guaranteed to be ordered wrt master barriers.
+ *
+ * The pair ordering is detailed as (O: ordered, X: not ordered) :
+ *               slave  master
+ *        slave    X      O
+ *        master   O      O
+ */
+
+#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
+#define urcu_memb_has_sys_membarrier           1
+#else
+extern int urcu_memb_has_sys_membarrier;
+#endif
+
+static inline void urcu_memb_smp_mb_slave(void)
+{
+       if (caa_likely(urcu_memb_has_sys_membarrier))
+               cmm_barrier();
+       else
+               cmm_smp_mb();
+}
+
+extern struct urcu_gp urcu_memb_gp;
+
+extern DECLARE_URCU_TLS(struct urcu_reader, urcu_memb_reader);
+
+/*
+ * Helper for _rcu_read_lock().  The format of urcu_memb_gp.ctr (as well as
+ * the per-thread rcu_reader.ctr) has the upper bits containing a count of
+ * _rcu_read_lock() nesting, and a lower-order bit that contains either zero
+ * or URCU_GP_CTR_PHASE.  The smp_mb_slave() ensures that the accesses in
+ * _rcu_read_lock() happen before the subsequent read-side critical section.
+ */
+static inline void _urcu_memb_read_lock_update(unsigned long tmp)
+{
+       if (caa_likely(!(tmp & URCU_GP_CTR_NEST_MASK))) {
+               _CMM_STORE_SHARED(URCU_TLS(urcu_memb_reader).ctr, _CMM_LOAD_SHARED(urcu_memb_gp.ctr));
+               urcu_memb_smp_mb_slave();
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_memb_reader).ctr, tmp + URCU_GP_COUNT);
+}
+
+/*
+ * Enter an RCU read-side critical section.
+ *
+ * The first cmm_barrier() call ensures that the compiler does not reorder
+ * the body of _rcu_read_lock() with a mutex.
+ *
+ * This function and its helper are both less than 10 lines long.  The
+ * intent is that this function meets the 10-line criterion in LGPL,
+ * allowing this function to be invoked directly from non-LGPL code.
+ */
+static inline void _urcu_memb_read_lock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_memb_reader).registered);
+       cmm_barrier();
+       tmp = URCU_TLS(urcu_memb_reader).ctr;
+       urcu_assert((tmp & URCU_GP_CTR_NEST_MASK) != URCU_GP_CTR_NEST_MASK);
+       _urcu_memb_read_lock_update(tmp);
+}
+
+/*
+ * This is a helper function for _rcu_read_unlock().
+ *
+ * The first smp_mb_slave() call ensures that the critical section is
+ * seen to precede the store to rcu_reader.ctr.
+ * The second smp_mb_slave() call ensures that we write to rcu_reader.ctr
+ * before reading the update-side futex.
+ */
+static inline void _urcu_memb_read_unlock_update_and_wakeup(unsigned long tmp)
+{
+       if (caa_likely((tmp & URCU_GP_CTR_NEST_MASK) == URCU_GP_COUNT)) {
+               urcu_memb_smp_mb_slave();
+               _CMM_STORE_SHARED(URCU_TLS(urcu_memb_reader).ctr, tmp - URCU_GP_COUNT);
+               urcu_memb_smp_mb_slave();
+               urcu_common_wake_up_gp(&urcu_memb_gp);
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_memb_reader).ctr, tmp - URCU_GP_COUNT);
+}
+
+/*
+ * Exit an RCU read-side crtical section.  Both this function and its
+ * helper are smaller than 10 lines of code, and are intended to be
+ * usable by non-LGPL code, as called out in LGPL.
+ */
+static inline void _urcu_memb_read_unlock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_memb_reader).registered);
+       tmp = URCU_TLS(urcu_memb_reader).ctr;
+       urcu_assert(tmp & URCU_GP_CTR_NEST_MASK);
+       _urcu_memb_read_unlock_update_and_wakeup(tmp);
+       cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
+}
+
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long.  The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _urcu_memb_read_ongoing(void)
+{
+       return URCU_TLS(urcu_memb_reader).ctr & URCU_GP_CTR_NEST_MASK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_MEMB_STATIC_H */
index 8d5fd03..a6063e2 100644 (file)
@@ -43,6 +43,7 @@
 #include <urcu/futex.h>
 #include <urcu/tls-compat.h>
 #include <urcu/debug.h>
+#include <urcu/static/urcu-common.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -56,29 +57,12 @@ extern "C" {
  * This is required to permit relinking with newer versions of the library.
  */
 
-enum rcu_state {
-       RCU_READER_ACTIVE_CURRENT,
-       RCU_READER_ACTIVE_OLD,
-       RCU_READER_INACTIVE,
-};
-
-#define RCU_GP_ONLINE          (1UL << 0)
-#define RCU_GP_CTR             (1UL << 1)
-
-struct rcu_gp {
-       /*
-        * Global quiescent period counter with low-order bits unused.
-        * Using a int rather than a char to eliminate false register
-        * dependencies causing stalls on some architectures.
-        */
-       unsigned long ctr;
-
-       int32_t futex;
-} __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
+#define URCU_QSBR_GP_ONLINE            (1UL << 0)
+#define URCU_QSBR_GP_CTR               (1UL << 1)
 
-extern struct rcu_gp rcu_gp;
+extern struct urcu_gp urcu_qsbr_gp;
 
-struct rcu_reader {
+struct urcu_qsbr_reader {
        /* Data used by both reader and synchronize_rcu() */
        unsigned long ctr;
        /* Data used for registry */
@@ -89,39 +73,39 @@ struct rcu_reader {
        unsigned int registered:1;
 };
 
-extern DECLARE_URCU_TLS(struct rcu_reader, rcu_reader);
+extern DECLARE_URCU_TLS(struct urcu_qsbr_reader, urcu_qsbr_reader);
 
 /*
  * Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
  */
-static inline void wake_up_gp(void)
+static inline void urcu_qsbr_wake_up_gp(void)
 {
-       if (caa_unlikely(_CMM_LOAD_SHARED(URCU_TLS(rcu_reader).waiting))) {
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader).waiting, 0);
+       if (caa_unlikely(_CMM_LOAD_SHARED(URCU_TLS(urcu_qsbr_reader).waiting))) {
+               _CMM_STORE_SHARED(URCU_TLS(urcu_qsbr_reader).waiting, 0);
                cmm_smp_mb();
-               if (uatomic_read(&rcu_gp.futex) != -1)
+               if (uatomic_read(&urcu_qsbr_gp.futex) != -1)
                        return;
-               uatomic_set(&rcu_gp.futex, 0);
+               uatomic_set(&urcu_qsbr_gp.futex, 0);
                /*
                 * Ignoring return value until we can make this function
                 * return something (because urcu_die() is not publicly
                 * exposed).
                 */
-               (void) futex_noasync(&rcu_gp.futex, FUTEX_WAKE, 1,
+               (void) futex_noasync(&urcu_qsbr_gp.futex, FUTEX_WAKE, 1,
                                NULL, NULL, 0);
        }
 }
 
-static inline enum rcu_state rcu_reader_state(unsigned long *ctr)
+static inline enum urcu_state urcu_qsbr_reader_state(unsigned long *ctr)
 {
        unsigned long v;
 
        v = CMM_LOAD_SHARED(*ctr);
        if (!v)
-               return RCU_READER_INACTIVE;
-       if (v == rcu_gp.ctr)
-               return RCU_READER_ACTIVE_CURRENT;
-       return RCU_READER_ACTIVE_OLD;
+               return URCU_READER_INACTIVE;
+       if (v == urcu_qsbr_gp.ctr)
+               return URCU_READER_ACTIVE_CURRENT;
+       return URCU_READER_ACTIVE_OLD;
 }
 
 /*
@@ -131,9 +115,9 @@ static inline enum rcu_state rcu_reader_state(unsigned long *ctr)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_lock(void)
+static inline void _urcu_qsbr_read_lock(void)
 {
-       urcu_assert(URCU_TLS(rcu_reader).ctr);
+       urcu_assert(URCU_TLS(urcu_qsbr_reader).ctr);
 }
 
 /*
@@ -143,9 +127,9 @@ static inline void _rcu_read_lock(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_read_unlock(void)
+static inline void _urcu_qsbr_read_unlock(void)
 {
-       urcu_assert(URCU_TLS(rcu_reader).ctr);
+       urcu_assert(URCU_TLS(urcu_qsbr_reader).ctr);
 }
 
 /*
@@ -155,26 +139,26 @@ static inline void _rcu_read_unlock(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline int _rcu_read_ongoing(void)
+static inline int _urcu_qsbr_read_ongoing(void)
 {
-       return URCU_TLS(rcu_reader).ctr;
+       return URCU_TLS(urcu_qsbr_reader).ctr;
 }
 
 /*
  * This is a helper function for _rcu_quiescent_state().
  * The first cmm_smp_mb() ensures memory accesses in the prior read-side
  * critical sections are not reordered with store to
- * URCU_TLS(rcu_reader).ctr, and ensures that mutexes held within an
+ * URCU_TLS(urcu_qsbr_reader).ctr, and ensures that mutexes held within an
  * offline section that would happen to end with this
- * rcu_quiescent_state() call are not reordered with
- * store to URCU_TLS(rcu_reader).ctr.
+ * urcu_qsbr_quiescent_state() call are not reordered with
+ * store to URCU_TLS(urcu_qsbr_reader).ctr.
  */
-static inline void _rcu_quiescent_state_update_and_wakeup(unsigned long gp_ctr)
+static inline void _urcu_qsbr_quiescent_state_update_and_wakeup(unsigned long gp_ctr)
 {
        cmm_smp_mb();
-       _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, gp_ctr);
-       cmm_smp_mb();   /* write URCU_TLS(rcu_reader).ctr before read futex */
-       wake_up_gp();
+       _CMM_STORE_SHARED(URCU_TLS(urcu_qsbr_reader).ctr, gp_ctr);
+       cmm_smp_mb();   /* write URCU_TLS(urcu_qsbr_reader).ctr before read futex */
+       urcu_qsbr_wake_up_gp();
        cmm_smp_mb();
 }
 
@@ -186,18 +170,18 @@ static inline void _rcu_quiescent_state_update_and_wakeup(unsigned long gp_ctr)
  * to be invoked directly from non-LGPL code.
  *
  * We skip the memory barriers and gp store if our local ctr already
- * matches the global rcu_gp.ctr value: this is OK because a prior
+ * matches the global urcu_qsbr_gp.ctr value: this is OK because a prior
  * _rcu_quiescent_state() or _rcu_thread_online() already updated it
  * within our thread, so we have no quiescent state to report.
  */
-static inline void _rcu_quiescent_state(void)
+static inline void _urcu_qsbr_quiescent_state(void)
 {
        unsigned long gp_ctr;
 
-       urcu_assert(URCU_TLS(rcu_reader).registered);
-       if ((gp_ctr = CMM_LOAD_SHARED(rcu_gp.ctr)) == URCU_TLS(rcu_reader).ctr)
+       urcu_assert(URCU_TLS(urcu_qsbr_reader).registered);
+       if ((gp_ctr = CMM_LOAD_SHARED(urcu_qsbr_gp.ctr)) == URCU_TLS(urcu_qsbr_reader).ctr)
                return;
-       _rcu_quiescent_state_update_and_wakeup(gp_ctr);
+       _urcu_qsbr_quiescent_state_update_and_wakeup(gp_ctr);
 }
 
 /*
@@ -208,13 +192,13 @@ static inline void _rcu_quiescent_state(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_thread_offline(void)
+static inline void _urcu_qsbr_thread_offline(void)
 {
-       urcu_assert(URCU_TLS(rcu_reader).registered);
+       urcu_assert(URCU_TLS(urcu_qsbr_reader).registered);
        cmm_smp_mb();
-       CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, 0);
-       cmm_smp_mb();   /* write URCU_TLS(rcu_reader).ctr before read futex */
-       wake_up_gp();
+       CMM_STORE_SHARED(URCU_TLS(urcu_qsbr_reader).ctr, 0);
+       cmm_smp_mb();   /* write URCU_TLS(urcu_qsbr_reader).ctr before read futex */
+       urcu_qsbr_wake_up_gp();
        cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
 }
 
@@ -226,11 +210,11 @@ static inline void _rcu_thread_offline(void)
  * function meets the 10-line criterion for LGPL, allowing this function
  * to be invoked directly from non-LGPL code.
  */
-static inline void _rcu_thread_online(void)
+static inline void _urcu_qsbr_thread_online(void)
 {
-       urcu_assert(URCU_TLS(rcu_reader).registered);
+       urcu_assert(URCU_TLS(urcu_qsbr_reader).registered);
        cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
-       _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, CMM_LOAD_SHARED(rcu_gp.ctr));
+       _CMM_STORE_SHARED(URCU_TLS(urcu_qsbr_reader).ctr, CMM_LOAD_SHARED(urcu_qsbr_gp.ctr));
        cmm_smp_mb();
 }
 
diff --git a/include/urcu/static/urcu-signal.h b/include/urcu/static/urcu-signal.h
new file mode 100644 (file)
index 0000000..385e6f5
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef _URCU_SIGNAL_STATIC_H
+#define _URCU_SIGNAL_STATIC_H
+
+/*
+ * urcu-signal-static.h
+ *
+ * Userspace RCU header.
+ *
+ * TO BE INCLUDED ONLY IN CODE THAT IS TO BE RECOMPILED ON EACH LIBURCU
+ * RELEASE. See urcu.h for linking dynamically with the userspace rcu library.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdint.h>
+
+#include <urcu/config.h>
+#include <urcu/compiler.h>
+#include <urcu/arch.h>
+#include <urcu/system.h>
+#include <urcu/uatomic.h>
+#include <urcu/list.h>
+#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
+#include <urcu/debug.h>
+#include <urcu/static/urcu-common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This code section can only be included in LGPL 2.1 compatible source code.
+ * See below for the function call wrappers which can be used in code meant to
+ * be only linked with the Userspace RCU library. This comes with a small
+ * performance degradation on the read-side due to the added function calls.
+ * This is required to permit relinking with newer versions of the library.
+ */
+
+/*
+ * The signal number used by the RCU library can be overridden with
+ * -DSIGRCU= when compiling the library.
+ * Provide backward compatibility for liburcu 0.3.x SIGURCU.
+ */
+#ifdef SIGURCU
+#define SIGRCU SIGURCU
+#endif
+
+#ifndef SIGRCU
+#define SIGRCU SIGUSR1
+#endif
+
+extern struct urcu_gp urcu_signal_gp;
+
+extern DECLARE_URCU_TLS(struct urcu_reader, urcu_signal_reader);
+
+/*
+ * Helper for _rcu_read_lock().  The format of urcu_signal_gp.ctr (as well as
+ * the per-thread rcu_reader.ctr) has the upper bits containing a count of
+ * _rcu_read_lock() nesting, and a lower-order bit that contains either zero
+ * or URCU_GP_CTR_PHASE.  The cmm_barrier() ensures that the accesses in
+ * _rcu_read_lock() happen before the subsequent read-side critical section.
+ */
+static inline void _urcu_signal_read_lock_update(unsigned long tmp)
+{
+       if (caa_likely(!(tmp & URCU_GP_CTR_NEST_MASK))) {
+               _CMM_STORE_SHARED(URCU_TLS(urcu_signal_reader).ctr, _CMM_LOAD_SHARED(urcu_signal_gp.ctr));
+               cmm_barrier();
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_signal_reader).ctr, tmp + URCU_GP_COUNT);
+}
+
+/*
+ * Enter an RCU read-side critical section.
+ *
+ * The first cmm_barrier() call ensures that the compiler does not reorder
+ * the body of _rcu_read_lock() with a mutex.
+ *
+ * This function and its helper are both less than 10 lines long.  The
+ * intent is that this function meets the 10-line criterion in LGPL,
+ * allowing this function to be invoked directly from non-LGPL code.
+ */
+static inline void _urcu_signal_read_lock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_signal_reader).registered);
+       cmm_barrier();
+       tmp = URCU_TLS(urcu_signal_reader).ctr;
+       urcu_assert((tmp & URCU_GP_CTR_NEST_MASK) != URCU_GP_CTR_NEST_MASK);
+       _urcu_signal_read_lock_update(tmp);
+}
+
+/*
+ * This is a helper function for _rcu_read_unlock().
+ *
+ * The first cmm_barrier() call ensures that the critical section is
+ * seen to precede the store to rcu_reader.ctr.
+ * The second cmm_barrier() call ensures that we write to rcu_reader.ctr
+ * before reading the update-side futex.
+ */
+static inline void _urcu_signal_read_unlock_update_and_wakeup(unsigned long tmp)
+{
+       if (caa_likely((tmp & URCU_GP_CTR_NEST_MASK) == URCU_GP_COUNT)) {
+               cmm_barrier();
+               _CMM_STORE_SHARED(URCU_TLS(urcu_signal_reader).ctr, tmp - URCU_GP_COUNT);
+               cmm_barrier();
+               urcu_common_wake_up_gp(&urcu_signal_gp);
+       } else
+               _CMM_STORE_SHARED(URCU_TLS(urcu_signal_reader).ctr, tmp - URCU_GP_COUNT);
+}
+
+/*
+ * Exit an RCU read-side crtical section.  Both this function and its
+ * helper are smaller than 10 lines of code, and are intended to be
+ * usable by non-LGPL code, as called out in LGPL.
+ */
+static inline void _urcu_signal_read_unlock(void)
+{
+       unsigned long tmp;
+
+       urcu_assert(URCU_TLS(urcu_signal_reader).registered);
+       tmp = URCU_TLS(urcu_signal_reader).ctr;
+       urcu_assert(tmp & URCU_GP_CTR_NEST_MASK);
+       _urcu_signal_read_unlock_update_and_wakeup(tmp);
+       cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
+}
+
+/*
+ * Returns whether within a RCU read-side critical section.
+ *
+ * This function is less than 10 lines long.  The intent is that this
+ * function meets the 10-line criterion for LGPL, allowing this function
+ * to be invoked directly from non-LGPL code.
+ */
+static inline int _urcu_signal_read_ongoing(void)
+{
+       return URCU_TLS(urcu_signal_reader).ctr & URCU_GP_CTR_NEST_MASK;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _URCU_SIGNAL_STATIC_H */
index 20fc864..b83e72b 100644 (file)
  * IBM's contributions to this file may be relicensed under LGPLv2 or later.
  */
 
-#include <stdlib.h>
-#include <pthread.h>
-#include <unistd.h>
-#include <stdint.h>
-
-#include <urcu/config.h>
-#include <urcu/compiler.h>
-#include <urcu/arch.h>
-#include <urcu/system.h>
-#include <urcu/uatomic.h>
-#include <urcu/list.h>
-#include <urcu/futex.h>
-#include <urcu/tls-compat.h>
-#include <urcu/debug.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /* Default is RCU_MEMBARRIER */
 #if !defined(RCU_MEMBARRIER) && !defined(RCU_MB) && !defined(RCU_SIGNAL)
 #define RCU_MEMBARRIER
 #endif
 
-/*
- * This code section can only be included in LGPL 2.1 compatible source code.
- * See below for the function call wrappers which can be used in code meant to
- * be only linked with the Userspace RCU library. This comes with a small
- * performance degradation on the read-side due to the added function calls.
- * This is required to permit relinking with newer versions of the library.
- */
-
-/*
- * The signal number used by the RCU library can be overridden with
- * -DSIGRCU= when compiling the library.
- * Provide backward compatibility for liburcu 0.3.x SIGURCU.
- */
-#ifdef SIGURCU
-#define SIGRCU SIGURCU
-#endif
-
-#ifndef SIGRCU
-#define SIGRCU SIGUSR1
-#endif
-
-enum rcu_state {
-       RCU_READER_ACTIVE_CURRENT,
-       RCU_READER_ACTIVE_OLD,
-       RCU_READER_INACTIVE,
-};
-
-/*
- * Slave barriers are only guaranteed to be ordered wrt master barriers.
- *
- * The pair ordering is detailed as (O: ordered, X: not ordered) :
- *               slave  master
- *        slave    X      O
- *        master   O      O
- */
-
 #ifdef RCU_MEMBARRIER
-#ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
-#define rcu_has_sys_membarrier_memb    1
-#else
-extern int rcu_has_sys_membarrier_memb;
-#endif
-
-static inline void smp_mb_slave(void)
-{
-       if (caa_likely(rcu_has_sys_membarrier_memb))
-               cmm_barrier();
-       else
-               cmm_smp_mb();
-}
+#include <urcu/static/urcu-memb.h>
 #endif
 
 #ifdef RCU_MB
-static inline void smp_mb_slave(void)
-{
-       cmm_smp_mb();
-}
+#include <urcu/static/urcu-mb.h>
 #endif
 
 #ifdef RCU_SIGNAL
-static inline void smp_mb_slave(void)
-{
-       cmm_barrier();
-}
-#endif
-
-/*
- * The trick here is that RCU_GP_CTR_PHASE must be a multiple of 8 so we can use
- * a full 8-bits, 16-bits or 32-bits bitmask for the lower order bits.
- */
-#define RCU_GP_COUNT           (1UL << 0)
-/* Use the amount of bits equal to half of the architecture long size */
-#define RCU_GP_CTR_PHASE       (1UL << (sizeof(unsigned long) << 2))
-#define RCU_GP_CTR_NEST_MASK   (RCU_GP_CTR_PHASE - 1)
-
-struct rcu_gp {
-       /*
-        * Global grace period counter.
-        * Contains the current RCU_GP_CTR_PHASE.
-        * Also has a RCU_GP_COUNT of 1, to accelerate the reader fast path.
-        * Written to only by writer with mutex taken.
-        * Read by both writer and readers.
-        */
-       unsigned long ctr;
-
-       int32_t futex;
-} __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
-
-extern struct rcu_gp rcu_gp;
-
-struct rcu_reader {
-       /* Data used by both reader and synchronize_rcu() */
-       unsigned long ctr;
-       char need_mb;
-       /* Data used for registry */
-       struct cds_list_head node __attribute__((aligned(CAA_CACHE_LINE_SIZE)));
-       pthread_t tid;
-       /* Reader registered flag, for internal checks. */
-       unsigned int registered:1;
-};
-
-extern DECLARE_URCU_TLS(struct rcu_reader, rcu_reader);
-
-/*
- * Wake-up waiting synchronize_rcu(). Called from many concurrent threads.
- */
-static inline void wake_up_gp(void)
-{
-       if (caa_unlikely(uatomic_read(&rcu_gp.futex) == -1)) {
-               uatomic_set(&rcu_gp.futex, 0);
-               /*
-                * Ignoring return value until we can make this function
-                * return something (because urcu_die() is not publicly
-                * exposed).
-                */
-               (void) futex_async(&rcu_gp.futex, FUTEX_WAKE, 1,
-                               NULL, NULL, 0);
-       }
-}
-
-static inline enum rcu_state rcu_reader_state(unsigned long *ctr)
-{
-       unsigned long v;
-
-       /*
-        * Make sure both tests below are done on the same version of *value
-        * to insure consistency.
-        */
-       v = CMM_LOAD_SHARED(*ctr);
-       if (!(v & RCU_GP_CTR_NEST_MASK))
-               return RCU_READER_INACTIVE;
-       if (!((v ^ rcu_gp.ctr) & RCU_GP_CTR_PHASE))
-               return RCU_READER_ACTIVE_CURRENT;
-       return RCU_READER_ACTIVE_OLD;
-}
-
-/*
- * Helper for _rcu_read_lock().  The format of rcu_gp.ctr (as well as
- * the per-thread rcu_reader.ctr) has the upper bits containing a count of
- * _rcu_read_lock() nesting, and a lower-order bit that contains either zero
- * or RCU_GP_CTR_PHASE.  The smp_mb_slave() ensures that the accesses in
- * _rcu_read_lock() happen before the subsequent read-side critical section.
- */
-static inline void _rcu_read_lock_update(unsigned long tmp)
-{
-       if (caa_likely(!(tmp & RCU_GP_CTR_NEST_MASK))) {
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, _CMM_LOAD_SHARED(rcu_gp.ctr));
-               smp_mb_slave();
-       } else
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, tmp + RCU_GP_COUNT);
-}
-
-/*
- * Enter an RCU read-side critical section.
- *
- * The first cmm_barrier() call ensures that the compiler does not reorder
- * the body of _rcu_read_lock() with a mutex.
- *
- * This function and its helper are both less than 10 lines long.  The
- * intent is that this function meets the 10-line criterion in LGPL,
- * allowing this function to be invoked directly from non-LGPL code.
- */
-static inline void _rcu_read_lock(void)
-{
-       unsigned long tmp;
-
-       urcu_assert(URCU_TLS(rcu_reader).registered);
-       cmm_barrier();
-       tmp = URCU_TLS(rcu_reader).ctr;
-       urcu_assert((tmp & RCU_GP_CTR_NEST_MASK) != RCU_GP_CTR_NEST_MASK);
-       _rcu_read_lock_update(tmp);
-}
-
-/*
- * This is a helper function for _rcu_read_unlock().
- *
- * The first smp_mb_slave() call ensures that the critical section is
- * seen to precede the store to rcu_reader.ctr.
- * The second smp_mb_slave() call ensures that we write to rcu_reader.ctr
- * before reading the update-side futex.
- */
-static inline void _rcu_read_unlock_update_and_wakeup(unsigned long tmp)
-{
-       if (caa_likely((tmp & RCU_GP_CTR_NEST_MASK) == RCU_GP_COUNT)) {
-               smp_mb_slave();
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, tmp - RCU_GP_COUNT);
-               smp_mb_slave();
-               wake_up_gp();
-       } else
-               _CMM_STORE_SHARED(URCU_TLS(rcu_reader).ctr, tmp - RCU_GP_COUNT);
-}
-
-/*
- * Exit an RCU read-side crtical section.  Both this function and its
- * helper are smaller than 10 lines of code, and are intended to be
- * usable by non-LGPL code, as called out in LGPL.
- */
-static inline void _rcu_read_unlock(void)
-{
-       unsigned long tmp;
-
-       urcu_assert(URCU_TLS(rcu_reader).registered);
-       tmp = URCU_TLS(rcu_reader).ctr;
-       urcu_assert(tmp & RCU_GP_CTR_NEST_MASK);
-       _rcu_read_unlock_update_and_wakeup(tmp);
-       cmm_barrier();  /* Ensure the compiler does not reorder us with mutex */
-}
-
-/*
- * Returns whether within a RCU read-side critical section.
- *
- * This function is less than 10 lines long.  The intent is that this
- * function meets the 10-line criterion for LGPL, allowing this function
- * to be invoked directly from non-LGPL code.
- */
-static inline int _rcu_read_ongoing(void)
-{
-       return URCU_TLS(rcu_reader).ctr & RCU_GP_CTR_NEST_MASK;
-}
-
-#ifdef __cplusplus
-}
+#include <urcu/static/urcu-signal.h>
 #endif
 
 #endif /* _URCU_STATIC_H */
diff --git a/include/urcu/urcu-bp.h b/include/urcu/urcu-bp.h
new file mode 100644 (file)
index 0000000..7b00aaa
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef _URCU_BP_H
+#define _URCU_BP_H
+
+/*
+ * urcu-bp.h
+ *
+ * Userspace RCU header, "bulletproof" version.
+ *
+ * Slower RCU read-side adapted for tracing library. Does not require thread
+ * registration nor unregistration. Also signal-safe.
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <urcu/map/urcu-bp.h>
+
+/*
+ * Important !
+ *
+ * Each thread containing read-side critical sections must be registered
+ * with rcu_register_thread() before calling rcu_read_lock().
+ * rcu_unregister_thread() should be called before the thread exits.
+ */
+
+/*
+ * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
+ * publication headers.
+ */
+#include <urcu-pointer.h>
+
+#ifdef _LGPL_SOURCE
+
+#include <urcu/static/urcu-bp.h>
+
+/*
+ * Mappings for static use of the userspace RCU library.
+ * Should only be used in LGPL-compatible code.
+ */
+
+/*
+ * rcu_read_lock()
+ * rcu_read_unlock()
+ *
+ * Mark the beginning and end of a read-side critical section.
+ */
+#define urcu_bp_read_lock              _urcu_bp_read_lock
+#define urcu_bp_read_unlock            _urcu_bp_read_unlock
+#define urcu_bp_read_ongoing           _urcu_bp_read_ongoing
+
+#define urcu_bp_dereference            rcu_dereference
+#define urcu_bp_cmpxchg_pointer                rcu_cmpxchg_pointer
+#define urcu_bp_xchg_pointer           rcu_xchg_pointer
+#define urcu_bp_set_pointer            rcu_set_pointer
+
+#else /* !_LGPL_SOURCE */
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ * See LGPL-only urcu/static/urcu-pointer.h for documentation.
+ */
+
+extern void urcu_bp_read_lock(void);
+extern void urcu_bp_read_unlock(void);
+extern int urcu_bp_read_ongoing(void);
+
+extern void *urcu_bp_dereference_sym(void *p);
+#define urcu_bp_dereference(p)                                              \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p),   \
+                       urcu_bp_dereference_sym(URCU_FORCE_CAST(void *, p))); \
+               (_________p1);                                               \
+       })
+
+extern void *urcu_bp_cmpxchg_pointer_sym(void **p, void *old, void *_new);
+#define urcu_bp_cmpxchg_pointer(p, old, _new)                               \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(*(p)) _________pold = (old);                      \
+               __typeof__(*(p)) _________pnew = (_new);                     \
+               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
+                       urcu_bp_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), \
+                                               _________pold,               \
+                                               _________pnew));             \
+               (_________p1);                                               \
+       })
+
+extern void *urcu_bp_xchg_pointer_sym(void **p, void *v);
+#define urcu_bp_xchg_pointer(p, v)                                          \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(*(p)) _________pv = (v);                          \
+               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)),\
+                       urcu_bp_xchg_pointer_sym(URCU_FORCE_CAST(void **, p), \
+                                            _________pv));                  \
+               (_________p1);                                               \
+       })
+
+extern void *urcu_bp_set_pointer_sym(void **p, void *v);
+#define urcu_bp_set_pointer(p, v)                                           \
+       __extension__                                                        \
+       ({                                                                   \
+               __typeof__(*(p)) _________pv = (v);                          \
+               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
+                       urcu_bp_set_pointer_sym(URCU_FORCE_CAST(void **, p), \
+                                           _________pv));                   \
+               (_________p1);                                               \
+       })
+
+#endif /* !_LGPL_SOURCE */
+
+extern void urcu_bp_synchronize_rcu(void);
+
+/*
+ * urcu_bp_before_fork, urcu_bp_after_fork_parent and urcu_bp_after_fork_child
+ * should be called around fork() system calls when the child process is not
+ * expected to immediately perform an exec(). For pthread users, see
+ * pthread_atfork(3).
+ */
+extern void urcu_bp_before_fork(void);
+extern void urcu_bp_after_fork_parent(void);
+extern void urcu_bp_after_fork_child(void);
+
+/*
+ * In the bulletproof version, the following functions are no-ops.
+ */
+static inline void urcu_bp_register_thread(void)
+{
+}
+
+static inline void urcu_bp_unregister_thread(void)
+{
+}
+
+static inline void urcu_bp_init(void)
+{
+}
+
+/*
+ * Q.S. reporting are no-ops for these URCU flavors.
+ */
+static inline void urcu_bp_quiescent_state(void)
+{
+}
+
+static inline void urcu_bp_thread_offline(void)
+{
+}
+
+static inline void urcu_bp_thread_online(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <urcu-call-rcu.h>
+#include <urcu-defer.h>
+#include <urcu-flavor.h>
+
+#ifndef URCU_API_MAP
+#include <urcu/map/clear.h>
+#endif
+
+#endif /* _URCU_BP_H */
diff --git a/include/urcu/urcu-mb.h b/include/urcu/urcu-mb.h
new file mode 100644 (file)
index 0000000..2000375
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _URCU_MB_H
+#define _URCU_MB_H
+
+/*
+ * urcu-mb.h
+ *
+ * Userspace RCU header
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/*
+ * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
+ * publication headers.
+ */
+#include <urcu-pointer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <urcu/map/urcu-mb.h>
+
+/*
+ * Important !
+ *
+ * Each thread containing read-side critical sections must be registered
+ * with rcu_register_thread_mb() before calling rcu_read_lock_mb().
+ * rcu_unregister_thread_mb() should be called before the thread exits.
+ */
+
+#ifdef _LGPL_SOURCE
+
+#include <urcu/static/urcu-mb.h>
+
+/*
+ * Mappings for static use of the userspace RCU library.
+ * Should only be used in LGPL-compatible code.
+ */
+
+/*
+ * rcu_read_lock()
+ * rcu_read_unlock()
+ *
+ * Mark the beginning and end of a read-side critical section.
+ * DON'T FORGET TO USE RCU_REGISTER/UNREGISTER_THREAD() FOR EACH THREAD WITH
+ * READ-SIDE CRITICAL SECTION.
+ */
+#define urcu_mb_read_lock              _urcu_mb_read_lock
+#define urcu_mb_read_unlock            _urcu_mb_read_unlock
+#define urcu_mb_read_ongoing           _urcu_mb_read_ongoing
+
+#else /* !_LGPL_SOURCE */
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ * See LGPL-only urcu/static/urcu-pointer.h for documentation.
+ */
+
+extern void urcu_mb_read_lock(void);
+extern void urcu_mb_read_unlock(void);
+extern int urcu_mb_read_ongoing(void);
+
+#endif /* !_LGPL_SOURCE */
+
+extern void urcu_mb_synchronize_rcu(void);
+
+/*
+ * Reader thread registration.
+ */
+extern void urcu_mb_register_thread(void);
+extern void urcu_mb_unregister_thread(void);
+
+/*
+ * Explicit rcu initialization, for "early" use within library constructors.
+ */
+extern void urcu_mb_init(void);
+
+/*
+ * Q.S. reporting are no-ops for these URCU flavors.
+ */
+static inline void urcu_mb_quiescent_state(void)
+{
+}
+
+static inline void urcu_mb_thread_offline(void)
+{
+}
+
+static inline void urcu_mb_thread_online(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <urcu-call-rcu.h>
+#include <urcu-defer.h>
+#include <urcu-flavor.h>
+
+#ifndef URCU_API_MAP
+#include <urcu/map/clear.h>
+#endif
+
+#endif /* _URCU_MB_H */
diff --git a/include/urcu/urcu-memb.h b/include/urcu/urcu-memb.h
new file mode 100644 (file)
index 0000000..c0fffe8
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _URCU_MEMB_H
+#define _URCU_MEMB_H
+
+/*
+ * urcu-memb.h
+ *
+ * Userspace RCU header
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/*
+ * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
+ * publication headers.
+ */
+#include <urcu-pointer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <urcu/map/urcu-memb.h>
+
+/*
+ * Important !
+ *
+ * Each thread containing read-side critical sections must be registered
+ * with rcu_register_thread_mb() before calling rcu_read_lock_mb().
+ * rcu_unregister_thread_mb() should be called before the thread exits.
+ */
+
+#ifdef _LGPL_SOURCE
+
+#include <urcu/static/urcu-memb.h>
+
+/*
+ * Mappings for static use of the userspace RCU library.
+ * Should only be used in LGPL-compatible code.
+ */
+
+/*
+ * rcu_read_lock()
+ * rcu_read_unlock()
+ *
+ * Mark the beginning and end of a read-side critical section.
+ * DON'T FORGET TO USE RCU_REGISTER/UNREGISTER_THREAD() FOR EACH THREAD WITH
+ * READ-SIDE CRITICAL SECTION.
+ */
+#define urcu_memb_read_lock            _urcu_memb_read_lock
+#define urcu_memb_read_unlock          _urcu_memb_read_unlock
+#define urcu_memb_read_ongoing         _urcu_memb_read_ongoing
+
+#else /* !_LGPL_SOURCE */
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ * See LGPL-only urcu/static/urcu-pointer.h for documentation.
+ */
+
+extern void urcu_memb_read_lock(void);
+extern void urcu_memb_read_unlock(void);
+extern int urcu_memb_read_ongoing(void);
+
+#endif /* !_LGPL_SOURCE */
+
+extern void urcu_memb_synchronize_rcu(void);
+
+/*
+ * Reader thread registration.
+ */
+extern void urcu_memb_register_thread(void);
+extern void urcu_memb_unregister_thread(void);
+
+/*
+ * Explicit rcu initialization, for "early" use within library constructors.
+ */
+extern void urcu_memb_init(void);
+
+/*
+ * Q.S. reporting are no-ops for these URCU flavors.
+ */
+static inline void urcu_memb_quiescent_state(void)
+{
+}
+
+static inline void urcu_memb_thread_offline(void)
+{
+}
+
+static inline void urcu_memb_thread_online(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <urcu-call-rcu.h>
+#include <urcu-defer.h>
+#include <urcu-flavor.h>
+
+#ifndef URCU_API_MAP
+#include <urcu/map/clear.h>
+#endif
+
+#endif /* _URCU_MEMB_H */
diff --git a/include/urcu/urcu-qsbr.h b/include/urcu/urcu-qsbr.h
new file mode 100644 (file)
index 0000000..041db21
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef _URCU_QSBR_H
+#define _URCU_QSBR_H
+
+/*
+ * urcu-qsbr.h
+ *
+ * Userspace RCU QSBR header.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/*
+ * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
+ * publication headers.
+ */
+#include <urcu-pointer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <urcu/map/urcu-qsbr.h>
+
+#ifdef RCU_DEBUG       /* For backward compatibility */
+#define DEBUG_RCU
+#endif
+
+/*
+ * Important !
+ *
+ * Each thread containing read-side critical sections must be registered
+ * with rcu_register_thread() before calling rcu_read_lock().
+ * rcu_unregister_thread() should be called before the thread exits.
+ */
+
+#ifdef _LGPL_SOURCE
+
+#include <urcu/static/urcu-qsbr.h>
+
+/*
+ * Mappings for static use of the userspace RCU library.
+ * Should only be used in LGPL-compatible code.
+ */
+
+/*
+ * rcu_read_lock()
+ * rcu_read_unlock()
+ *
+ * Mark the beginning and end of a read-side critical section.
+ * DON'T FORGET TO USE rcu_register_thread/rcu_unregister_thread()
+ * FOR EACH THREAD WITH READ-SIDE CRITICAL SECTION.
+ */
+#define urcu_qsbr_read_lock            _urcu_qsbr_read_lock
+#define urcu_qsbr_read_unlock          _urcu_qsbr_read_unlock
+#define urcu_qsbr_read_ongoing         _urcu_qsbr_read_ongoing
+
+#define urcu_qsbr_quiescent_state      _urcu_qsbr_quiescent_state
+#define urcu_qsbr_thread_offline       _urcu_qsbr_thread_offline
+#define urcu_qsbr_thread_online                _urcu_qsbr_thread_online
+
+#else /* !_LGPL_SOURCE */
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ */
+
+/*
+ * QSBR read lock/unlock are guaranteed to be no-ops. Therefore, we expose them
+ * in the LGPL header for any code to use. However, the debug version is not
+ * nops and may contain sanity checks. To activate it, applications must be
+ * recompiled with -DDEBUG_RCU (even non-LGPL/GPL applications), or
+ * compiled against a urcu/config.h that has CONFIG_RCU_DEBUG defined.
+ * This is the best trade-off between license/performance/code
+ * triviality and library debugging & tracing features we could come up
+ * with.
+ */
+
+#if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG))
+
+static inline void urcu_qsbr_read_lock(void)
+{
+}
+
+static inline void urcu_qsbr_read_unlock(void)
+{
+}
+
+#else /* #if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG)) */
+
+extern void urcu_qsbr_read_lock(void);
+extern void urcu_qsbr_read_unlock(void);
+
+#endif /* #else #if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG)) */
+
+extern int urcu_qsbr_read_ongoing(void);
+extern void urcu_qsbr_quiescent_state(void);
+extern void urcu_qsbr_thread_offline(void);
+extern void urcu_qsbr_thread_online(void);
+
+#endif /* !_LGPL_SOURCE */
+
+extern void urcu_qsbr_synchronize_rcu(void);
+
+/*
+ * Reader thread registration.
+ */
+extern void urcu_qsbr_register_thread(void);
+extern void urcu_qsbr_unregister_thread(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <urcu-call-rcu.h>
+#include <urcu-defer.h>
+#include <urcu-flavor.h>
+
+#ifndef URCU_API_MAP
+#include <urcu/map/clear.h>
+#endif
+
+#endif /* _URCU_QSBR_H */
diff --git a/include/urcu/urcu-signal.h b/include/urcu/urcu-signal.h
new file mode 100644 (file)
index 0000000..8c36450
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef _URCU_SIGNAL_H
+#define _URCU_SIGNAL_H
+
+/*
+ * urcu-signal.h
+ *
+ * Userspace RCU header
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/*
+ * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
+ * publication headers.
+ */
+#include <urcu-pointer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <urcu/map/urcu-signal.h>
+
+/*
+ * Important !
+ *
+ * Each thread containing read-side critical sections must be registered
+ * with rcu_register_thread_mb() before calling rcu_read_lock_mb().
+ * rcu_unregister_thread_mb() should be called before the thread exits.
+ */
+
+#ifdef _LGPL_SOURCE
+
+#include <urcu/static/urcu-signal.h>
+
+/*
+ * Mappings for static use of the userspace RCU library.
+ * Should only be used in LGPL-compatible code.
+ */
+
+/*
+ * rcu_read_lock()
+ * rcu_read_unlock()
+ *
+ * Mark the beginning and end of a read-side critical section.
+ * DON'T FORGET TO USE RCU_REGISTER/UNREGISTER_THREAD() FOR EACH THREAD WITH
+ * READ-SIDE CRITICAL SECTION.
+ */
+#define urcu_signal_read_lock          _urcu_signal_read_lock
+#define urcu_signal_read_unlock                _urcu_signal_read_unlock
+#define urcu_signal_read_ongoing       _urcu_signal_read_ongoing
+
+#else /* !_LGPL_SOURCE */
+
+/*
+ * library wrappers to be used by non-LGPL compatible source code.
+ * See LGPL-only urcu/static/urcu-pointer.h for documentation.
+ */
+
+extern void urcu_signal_read_lock(void);
+extern void urcu_signal_read_unlock(void);
+extern int urcu_signal_read_ongoing(void);
+
+#endif /* !_LGPL_SOURCE */
+
+extern void urcu_signal_synchronize_rcu(void);
+
+/*
+ * Reader thread registration.
+ */
+extern void urcu_signal_register_thread(void);
+extern void urcu_signal_unregister_thread(void);
+
+/*
+ * Explicit rcu initialization, for "early" use within library constructors.
+ */
+extern void urcu_signal_init(void);
+
+/*
+ * Q.S. reporting are no-ops for these URCU flavors.
+ */
+static inline void urcu_signal_quiescent_state(void)
+{
+}
+
+static inline void urcu_signal_thread_offline(void)
+{
+}
+
+static inline void urcu_signal_thread_online(void)
+{
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <urcu-call-rcu.h>
+#include <urcu-defer.h>
+#include <urcu-flavor.h>
+
+#ifndef URCU_API_MAP
+#include <urcu/map/clear.h>
+#endif
+
+#endif /* _URCU_SIGNAL_H */
diff --git a/include/urcu/urcu.h b/include/urcu/urcu.h
new file mode 100644 (file)
index 0000000..79cf590
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef _URCU_H
+#define _URCU_H
+
+/*
+ * urcu.h
+ *
+ * Userspace RCU header
+ *
+ * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
+ *
+ * LGPL-compatible code should include this header with :
+ *
+ * #define _LGPL_SOURCE
+ * #include <urcu.h>
+ *
+ * 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
+ *
+ * IBM's contributions to this file may be relicensed under LGPLv2 or later.
+ */
+
+#if !defined(RCU_MEMBARRIER) && !defined(RCU_SIGNAL) && !defined(RCU_MB)
+#define RCU_MEMBARRIER
+#endif
+
+#ifdef RCU_MEMBARRIER
+#include <urcu/urcu-memb.h>
+#elif defined(RCU_SIGNAL)
+#include <urcu/urcu-signal.h>
+#elif defined(RCU_MB)
+#include <urcu/urcu-mb.h>
+#else
+#error "Unknown urcu flavor"
+#endif
+
+#endif /* _URCU_H */
index 60b833d..88ccc1f 100644 (file)
@@ -7,12 +7,8 @@ if USE_CYGWIN
 AM_LDFLAGS+=-no-undefined
 endif
 
-include_HEADERS = urcu.h urcu-bp.h urcu-call-rcu.h urcu-defer.h \
-               urcu-pointer.h urcu-qsbr.h urcu-flavor.h
-
 dist_noinst_HEADERS = urcu-die.h urcu-wait.h compat-getcpu.h \
-       compat-rand.h
-
+       compat-rand.h urcu-utils.h
 
 if COMPAT_ARCH
 COMPAT=compat_arch_@ARCHTYPE@.c
@@ -28,7 +24,7 @@ RCULFHASH = rculfhash.c rculfhash-mm-order.c rculfhash-mm-chunk.c \
 lib_LTLIBRARIES = liburcu-common.la \
                liburcu.la liburcu-qsbr.la \
                liburcu-mb.la liburcu-signal.la liburcu-bp.la \
-               liburcu-cds.la
+               liburcu-memb.la liburcu-cds.la
 
 #
 # liburcu-common contains wait-free queues (needed by call_rcu) as well
@@ -37,9 +33,15 @@ lib_LTLIBRARIES = liburcu-common.la \
 liburcu_common_la_SOURCES = wfqueue.c wfcqueue.c wfstack.c $(COMPAT)
 
 liburcu_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
+liburcu_la_CFLAGS = -DRCU_MEMBARRIER $(AM_CFLAGS)
 liburcu_la_LIBADD = liburcu-common.la
 
+liburcu_memb_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
+liburcu_memb_la_CFLAGS = -DRCU_MEMBARRIER $(AM_CFLAGS)
+liburcu_memb_la_LIBADD = liburcu-common.la
+
 liburcu_qsbr_la_SOURCES = urcu-qsbr.c urcu-pointer.c $(COMPAT)
+liburcu_qsbr_la_CFLAGS = -DRCU_QSBR $(AM_CFLAGS)
 liburcu_qsbr_la_LIBADD = liburcu-common.la
 
 liburcu_mb_la_SOURCES = urcu.c urcu-pointer.c $(COMPAT)
index 5d07f04..66c877a 100644 (file)
 #include <stdbool.h>
 #include <sys/mman.h>
 
-#include "urcu/arch.h"
-#include "urcu/wfcqueue.h"
-#include "urcu/map/urcu-bp.h"
-#include "urcu/static/urcu-bp.h"
-#include "urcu-pointer.h"
-#include "urcu/tls-compat.h"
+#include <urcu/arch.h>
+#include <urcu/wfcqueue.h>
+#include <urcu/map/urcu-bp.h>
+#include <urcu/static/urcu-bp.h>
+#include <urcu/pointer.h>
+#include <urcu/tls-compat.h>
 
 #include "urcu-die.h"
 
+#define URCU_API_MAP
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #undef _LGPL_SOURCE
-#include "urcu-bp.h"
+#include <urcu/urcu-bp.h>
 #define _LGPL_SOURCE
 
 #ifndef MAP_ANONYMOUS
@@ -85,7 +86,7 @@ void *mremap_wrapper(void *old_address, size_t old_size,
 #define INIT_NR_THREADS                8
 #define ARENA_INIT_ALLOC               \
        sizeof(struct registry_chunk)   \
-       + INIT_NR_THREADS * sizeof(struct rcu_reader)
+       + INIT_NR_THREADS * sizeof(struct urcu_bp_reader)
 
 /*
  * Active attempts to check for reader Q.S. before calling sleep().
@@ -93,7 +94,7 @@ void *mremap_wrapper(void *old_address, size_t old_size,
 #define RCU_QS_ACTIVE_ATTEMPTS 100
 
 static
-int rcu_bp_refcount;
+int urcu_bp_refcount;
 
 /* If the headers do not support membarrier system call, fall back smp_mb. */
 #ifdef __NR_membarrier
@@ -112,9 +113,9 @@ enum membarrier_cmd {
 };
 
 static
-void __attribute__((constructor)) rcu_bp_init(void);
+void __attribute__((constructor)) _urcu_bp_init(void);
 static
-void __attribute__((destructor)) rcu_bp_exit(void);
+void __attribute__((destructor)) urcu_bp_exit(void);
 
 #ifndef CONFIG_RCU_FORCE_SYS_MEMBARRIER
 int urcu_bp_has_sys_membarrier;
@@ -141,13 +142,16 @@ static int initialized;
 
 static pthread_key_t urcu_bp_key;
 
-struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT };
+struct urcu_bp_gp urcu_bp_gp = { .ctr = URCU_BP_GP_COUNT };
+__attribute__((alias("urcu_bp_gp"))) extern struct urcu_bp_gp rcu_gp_bp;
 
 /*
  * Pointer to registry elements. Written to only by each individual reader. Read
  * by both the reader and the writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader *, rcu_reader);
+DEFINE_URCU_TLS(struct urcu_bp_reader *, urcu_bp_reader);
+__attribute__((alias("urcu_bp_reader")))
+extern struct urcu_bp_reader *rcu_reader_bp;
 
 static CDS_LIST_HEAD(registry);
 
@@ -214,10 +218,10 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        struct cds_list_head *qsreaders)
 {
        unsigned int wait_loops = 0;
-       struct rcu_reader *index, *tmp;
+       struct urcu_bp_reader *index, *tmp;
 
        /*
-        * Wait for each thread URCU_TLS(rcu_reader).ctr to either
+        * Wait for each thread URCU_TLS(urcu_bp_reader).ctr to either
         * indicate quiescence (not nested), or observe the current
         * rcu_gp.ctr value.
         */
@@ -226,18 +230,18 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        wait_loops++;
 
                cds_list_for_each_entry_safe(index, tmp, input_readers, node) {
-                       switch (rcu_reader_state(&index->ctr)) {
-                       case RCU_READER_ACTIVE_CURRENT:
+                       switch (urcu_bp_reader_state(&index->ctr)) {
+                       case URCU_BP_READER_ACTIVE_CURRENT:
                                if (cur_snap_readers) {
                                        cds_list_move(&index->node,
                                                cur_snap_readers);
                                        break;
                                }
                                /* Fall-through */
-                       case RCU_READER_INACTIVE:
+                       case URCU_BP_READER_INACTIVE:
                                cds_list_move(&index->node, qsreaders);
                                break;
-                       case RCU_READER_ACTIVE_OLD:
+                       case URCU_BP_READER_ACTIVE_OLD:
                                /*
                                 * Old snapshot. Leaving node in
                                 * input_readers will make us busy-loop
@@ -263,7 +267,7 @@ static void wait_for_readers(struct cds_list_head *input_readers,
        }
 }
 
-void synchronize_rcu(void)
+void urcu_bp_synchronize_rcu(void)
 {
        CDS_LIST_HEAD(cur_snap_readers);
        CDS_LIST_HEAD(qsreaders);
@@ -302,7 +306,7 @@ void synchronize_rcu(void)
        cmm_smp_mb();
 
        /* Switch parity: 0 -> 1, 1 -> 0 */
-       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ RCU_GP_CTR_PHASE);
+       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ URCU_BP_GP_CTR_PHASE);
 
        /*
         * Must commit qparity update to memory before waiting for other parity
@@ -341,25 +345,29 @@ out:
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
        assert(!ret);
 }
+__attribute__((alias("urcu_bp_synchronize_rcu"))) void synchronize_rcu_bp();
 
 /*
  * library wrappers to be used by non-LGPL compatible source code.
  */
 
-void rcu_read_lock(void)
+void urcu_bp_read_lock(void)
 {
-       _rcu_read_lock();
+       _urcu_bp_read_lock();
 }
+__attribute__((alias("urcu_bp_read_lock"))) void rcu_read_lock_bp();
 
-void rcu_read_unlock(void)
+void urcu_bp_read_unlock(void)
 {
-       _rcu_read_unlock();
+       _urcu_bp_read_unlock();
 }
+__attribute__((alias("urcu_bp_read_unlock"))) void rcu_read_unlock_bp();
 
-int rcu_read_ongoing(void)
+int urcu_bp_read_ongoing(void)
 {
-       return _rcu_read_ongoing();
+       return _urcu_bp_read_ongoing();
 }
+__attribute__((alias("urcu_bp_read_ongoing"))) int rcu_read_ongoing_bp();
 
 /*
  * Only grow for now. If empty, allocate a ARENA_INIT_ALLOC sized chunk.
@@ -484,7 +492,7 @@ void add_thread(void)
         * Reader threads are pointing to the reader registry. This is
         * why its memory should never be relocated.
         */
-       URCU_TLS(rcu_reader) = rcu_reader_reg;
+       URCU_TLS(urcu_bp_reader) = rcu_reader_reg;
 }
 
 /* Called with mutex locked */
@@ -519,11 +527,11 @@ static
 void remove_thread(struct rcu_reader *rcu_reader_reg)
 {
        cleanup_thread(find_chunk(rcu_reader_reg), rcu_reader_reg);
-       URCU_TLS(rcu_reader) = NULL;
+       URCU_TLS(urcu_bp_reader) = NULL;
 }
 
 /* Disable signals, take mutex, add to registry */
-void rcu_bp_register(void)
+void urcu_bp_register(void)
 {
        sigset_t newmask, oldmask;
        int ret;
@@ -539,13 +547,13 @@ void rcu_bp_register(void)
         * Check if a signal concurrently registered our thread since
         * the check in rcu_read_lock().
         */
-       if (URCU_TLS(rcu_reader))
+       if (URCU_TLS(urcu_bp_reader))
                goto end;
 
        /*
         * Take care of early registration before urcu_bp constructor.
         */
-       rcu_bp_init();
+       _urcu_bp_init();
 
        mutex_lock(&rcu_registry_lock);
        add_thread();
@@ -555,10 +563,11 @@ end:
        if (ret)
                abort();
 }
+__attribute__((alias("urcu_bp_register"))) void rcu_bp_register();
 
 /* Disable signals, take mutex, remove from registry */
 static
-void rcu_bp_unregister(struct rcu_reader *rcu_reader_reg)
+void urcu_bp_unregister(struct rcu_reader *rcu_reader_reg)
 {
        sigset_t newmask, oldmask;
        int ret;
@@ -576,7 +585,7 @@ void rcu_bp_unregister(struct rcu_reader *rcu_reader_reg)
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
        if (ret)
                abort();
-       rcu_bp_exit();
+       urcu_bp_exit();
 }
 
 /*
@@ -586,19 +595,19 @@ void rcu_bp_unregister(struct rcu_reader *rcu_reader_reg)
 static
 void urcu_bp_thread_exit_notifier(void *rcu_key)
 {
-       rcu_bp_unregister(rcu_key);
+       urcu_bp_unregister(rcu_key);
 }
 
 #ifdef CONFIG_RCU_FORCE_SYS_MEMBARRIER
 static
-void rcu_sys_membarrier_status(bool available)
+void urcu_bp_sys_membarrier_status(bool available)
 {
        if (!available)
                abort();
 }
 #else
 static
-void rcu_sys_membarrier_status(bool available)
+void urcu_bp_sys_membarrier_status(bool available)
 {
        if (!available)
                return;
@@ -607,7 +616,7 @@ void rcu_sys_membarrier_status(bool available)
 #endif
 
 static
-void rcu_sys_membarrier_init(void)
+void urcu_bp_sys_membarrier_init(void)
 {
        bool available = false;
        int mask;
@@ -620,31 +629,31 @@ void rcu_sys_membarrier_init(void)
                        available = true;
                }
        }
-       rcu_sys_membarrier_status(available);
+       urcu_bp_sys_membarrier_status(available);
 }
 
 static
-void rcu_bp_init(void)
+void _urcu_bp_init(void)
 {
        mutex_lock(&init_lock);
-       if (!rcu_bp_refcount++) {
+       if (!urcu_bp_refcount++) {
                int ret;
 
                ret = pthread_key_create(&urcu_bp_key,
                                urcu_bp_thread_exit_notifier);
                if (ret)
                        abort();
-               rcu_sys_membarrier_init();
+               urcu_bp_sys_membarrier_init();
                initialized = 1;
        }
        mutex_unlock(&init_lock);
 }
 
 static
-void rcu_bp_exit(void)
+void urcu_bp_exit(void)
 {
        mutex_lock(&init_lock);
-       if (!--rcu_bp_refcount) {
+       if (!--urcu_bp_refcount) {
                struct registry_chunk *chunk, *tmp;
                int ret;
 
@@ -667,7 +676,7 @@ void rcu_bp_exit(void)
  * any of those locks held. This ensures that the registry and data
  * protected by rcu_gp_lock are in a coherent state in the child.
  */
-void rcu_bp_before_fork(void)
+void urcu_bp_before_fork(void)
 {
        sigset_t newmask, oldmask;
        int ret;
@@ -680,8 +689,9 @@ void rcu_bp_before_fork(void)
        mutex_lock(&rcu_registry_lock);
        saved_fork_signal_mask = oldmask;
 }
+__attribute__((alias("urcu_bp_before_fork"))) void rcu_bp_before_fork();
 
-void rcu_bp_after_fork_parent(void)
+void urcu_bp_after_fork_parent(void)
 {
        sigset_t oldmask;
        int ret;
@@ -692,6 +702,8 @@ void rcu_bp_after_fork_parent(void)
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
        assert(!ret);
 }
+__attribute__((alias("urcu_bp_after_fork_parent")))
+void rcu_bp_after_fork_parent(void);
 
 /*
  * Prune all entries from registry except our own thread. Fits the Linux
@@ -701,11 +713,11 @@ static
 void urcu_bp_prune_registry(void)
 {
        struct registry_chunk *chunk;
-       struct rcu_reader *rcu_reader_reg;
+       struct urcu_bp_reader *rcu_reader_reg;
 
        cds_list_for_each_entry(chunk, &registry_arena.chunk_list, node) {
-               for (rcu_reader_reg = (struct rcu_reader *) &chunk->data[0];
-                               rcu_reader_reg < (struct rcu_reader *) &chunk->data[chunk->data_len];
+               for (rcu_reader_reg = (struct urcu_bp_reader *) &chunk->data[0];
+                               rcu_reader_reg < (struct urcu_bp_reader *) &chunk->data[chunk->data_len];
                                rcu_reader_reg++) {
                        if (!rcu_reader_reg->alloc)
                                continue;
@@ -716,7 +728,7 @@ void urcu_bp_prune_registry(void)
        }
 }
 
-void rcu_bp_after_fork_child(void)
+void urcu_bp_after_fork_child(void)
 {
        sigset_t oldmask;
        int ret;
@@ -728,32 +740,43 @@ void rcu_bp_after_fork_child(void)
        ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
        assert(!ret);
 }
+__attribute__((alias("urcu_bp_after_fork_child")))
+void rcu_bp_after_fork_child(void);
 
-void *rcu_dereference_sym_bp(void *p)
+void *urcu_bp_dereference_sym(void *p)
 {
        return _rcu_dereference(p);
 }
+__attribute__((alias("urcu_bp_dereference_sym")))
+void *rcu_dereference_sym_bp();
 
-void *rcu_set_pointer_sym_bp(void **p, void *v)
+void *urcu_bp_set_pointer_sym(void **p, void *v)
 {
        cmm_wmb();
        uatomic_set(p, v);
        return v;
 }
+__attribute__((alias("urcu_bp_set_pointer_sym")))
+void *rcu_set_pointer_sym_bp();
 
-void *rcu_xchg_pointer_sym_bp(void **p, void *v)
+void *urcu_bp_xchg_pointer_sym(void **p, void *v)
 {
        cmm_wmb();
        return uatomic_xchg(p, v);
 }
+__attribute__((alias("urcu_bp_xchg_pointer_sym")))
+void *rcu_xchg_pointer_sym_bp();
 
-void *rcu_cmpxchg_pointer_sym_bp(void **p, void *old, void *_new)
+void *urcu_bp_cmpxchg_pointer_sym(void **p, void *old, void *_new)
 {
        cmm_wmb();
        return uatomic_cmpxchg(p, old, _new);
 }
+__attribute__((alias("urcu_bp_cmpxchg_pointer_sym")))
+void *rcu_cmpxchg_pointer_sym_bp();
 
 DEFINE_RCU_FLAVOR(rcu_flavor);
+DEFINE_RCU_FLAVOR_ALIAS(rcu_flavor, alias_rcu_flavor);
 
 #include "urcu-call-rcu-impl.h"
 #include "urcu-defer-impl.h"
diff --git a/src/urcu-bp.h b/src/urcu-bp.h
deleted file mode 100644 (file)
index 7a265dc..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#ifndef _URCU_BP_H
-#define _URCU_BP_H
-
-/*
- * urcu-bp.h
- *
- * Userspace RCU header, "bulletproof" version.
- *
- * Slower RCU read-side adapted for tracing library. Does not require thread
- * registration nor unregistration. Also signal-safe.
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- *
- * LGPL-compatible code should include this header with :
- *
- * #define _LGPL_SOURCE
- * #include <urcu.h>
- *
- * 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
- *
- * IBM's contributions to this file may be relicensed under LGPLv2 or later.
- */
-
-#include <stdlib.h>
-#include <pthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <urcu/map/urcu-bp.h>
-
-/*
- * Important !
- *
- * Each thread containing read-side critical sections must be registered
- * with rcu_register_thread() before calling rcu_read_lock().
- * rcu_unregister_thread() should be called before the thread exits.
- */
-
-/*
- * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
- * publication headers.
- */
-#include <urcu-pointer.h>
-
-#ifdef _LGPL_SOURCE
-
-#include <urcu/static/urcu-bp.h>
-
-/*
- * Mappings for static use of the userspace RCU library.
- * Should only be used in LGPL-compatible code.
- */
-
-/*
- * rcu_read_lock()
- * rcu_read_unlock()
- *
- * Mark the beginning and end of a read-side critical section.
- */
-#define rcu_read_lock_bp               _rcu_read_lock
-#define rcu_read_unlock_bp             _rcu_read_unlock
-#define rcu_read_ongoing_bp            _rcu_read_ongoing
-
-#define rcu_dereference_bp             rcu_dereference
-#define rcu_cmpxchg_pointer_bp         rcu_cmpxchg_pointer
-#define rcu_xchg_pointer_bp            rcu_xchg_pointer
-#define rcu_set_pointer_bp             rcu_set_pointer
-
-#else /* !_LGPL_SOURCE */
-
-/*
- * library wrappers to be used by non-LGPL compatible source code.
- * See LGPL-only urcu/static/urcu-pointer.h for documentation.
- */
-
-extern void rcu_read_lock(void);
-extern void rcu_read_unlock(void);
-extern int rcu_read_ongoing(void);
-
-extern void *rcu_dereference_sym_bp(void *p);
-#define rcu_dereference_bp(p)                                               \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(p) _________p1 = URCU_FORCE_CAST(__typeof__(p),   \
-                       rcu_dereference_sym_bp(URCU_FORCE_CAST(void *, p))); \
-               (_________p1);                                               \
-       })
-
-extern void *rcu_cmpxchg_pointer_sym_bp(void **p, void *old, void *_new);
-#define rcu_cmpxchg_pointer_bp(p, old, _new)                                \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(*(p)) _________pold = (old);                      \
-               __typeof__(*(p)) _________pnew = (_new);                     \
-               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
-                       rcu_cmpxchg_pointer_sym_bp(URCU_FORCE_CAST(void **, p), \
-                                               _________pold,               \
-                                               _________pnew));             \
-               (_________p1);                                               \
-       })
-
-extern void *rcu_xchg_pointer_sym_bp(void **p, void *v);
-#define rcu_xchg_pointer_bp(p, v)                                           \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(*(p)) _________pv = (v);                          \
-               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)),\
-                       rcu_xchg_pointer_sym_bp(URCU_FORCE_CAST(void **, p), \
-                                            _________pv));                  \
-               (_________p1);                                               \
-       })
-
-extern void *rcu_set_pointer_sym_bp(void **p, void *v);
-#define rcu_set_pointer_bp(p, v)                                            \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(*(p)) _________pv = (v);                          \
-               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
-                       rcu_set_pointer_sym_bp(URCU_FORCE_CAST(void **, p),  \
-                                           _________pv));                   \
-               (_________p1);                                               \
-       })
-
-#endif /* !_LGPL_SOURCE */
-
-extern void synchronize_rcu(void);
-
-/*
- * rcu_bp_before_fork, rcu_bp_after_fork_parent and rcu_bp_after_fork_child
- * should be called around fork() system calls when the child process is not
- * expected to immediately perform an exec(). For pthread users, see
- * pthread_atfork(3).
- */
-extern void rcu_bp_before_fork(void);
-extern void rcu_bp_after_fork_parent(void);
-extern void rcu_bp_after_fork_child(void);
-
-/*
- * In the bulletproof version, the following functions are no-ops.
- */
-static inline void rcu_register_thread(void)
-{
-}
-
-static inline void rcu_unregister_thread(void)
-{
-}
-
-static inline void rcu_init(void)
-{
-}
-
-/*
- * Q.S. reporting are no-ops for these URCU flavors.
- */
-static inline void rcu_quiescent_state(void)
-{
-}
-
-static inline void rcu_thread_offline(void)
-{
-}
-
-static inline void rcu_thread_online(void)
-{
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#include <urcu-call-rcu.h>
-#include <urcu-defer.h>
-#include <urcu-flavor.h>
-
-#endif /* _URCU_BP_H */
index 4562ba4..f7844cc 100644 (file)
 #include <sched.h>
 
 #include "compat-getcpu.h"
-#include "urcu/wfcqueue.h"
-#include "urcu-call-rcu.h"
-#include "urcu-pointer.h"
-#include "urcu/list.h"
-#include "urcu/futex.h"
-#include "urcu/tls-compat.h"
-#include "urcu/ref.h"
+#include <urcu/wfcqueue.h>
+#include <urcu/call-rcu.h>
+#include <urcu/pointer.h>
+#include <urcu/list.h>
+#include <urcu/futex.h>
+#include <urcu/tls-compat.h>
+#include <urcu/ref.h>
 #include "urcu-die.h"
+#include "urcu-utils.h"
 
 #define SET_AFFINITY_CHECK_PERIOD              (1U << 8)       /* 256 */
 #define SET_AFFINITY_CHECK_PERIOD_MASK         (SET_AFFINITY_CHECK_PERIOD - 1)
@@ -464,6 +465,8 @@ struct call_rcu_data *get_cpu_call_rcu_data(int cpu)
                return NULL;
        return rcu_dereference(pcpu_crdp[cpu]);
 }
+__attribute__((alias(urcu_stringify(get_cpu_call_rcu_data))))
+struct call_rcu_data *alias_get_cpu_call_rcu_data();
 
 /*
  * Return the tid corresponding to the call_rcu thread whose
@@ -474,6 +477,8 @@ pthread_t get_call_rcu_thread(struct call_rcu_data *crdp)
 {
        return crdp->tid;
 }
+__attribute__((alias(urcu_stringify(get_call_rcu_thread))))
+pthread_t alias_get_call_rcu_thread();
 
 /*
  * Create a call_rcu_data structure (with thread) and return a pointer.
@@ -488,6 +493,8 @@ static struct call_rcu_data *__create_call_rcu_data(unsigned long flags,
        return crdp;
 }
 
+__attribute__((alias(urcu_stringify(create_call_rcu_data))))
+struct call_rcu_data *alias_create_call_rcu_data();
 struct call_rcu_data *create_call_rcu_data(unsigned long flags,
                                           int cpu_affinity)
 {
@@ -544,6 +551,8 @@ int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp)
        call_rcu_unlock(&call_rcu_mutex);
        return 0;
 }
+__attribute__((alias(urcu_stringify(set_cpu_call_rcu_data))))
+int alias_set_cpu_call_rcu_data();
 
 /*
  * Return a pointer to the default call_rcu_data structure, creating
@@ -564,6 +573,8 @@ struct call_rcu_data *get_default_call_rcu_data(void)
        call_rcu_unlock(&call_rcu_mutex);
        return default_call_rcu_data;
 }
+__attribute__((alias(urcu_stringify(get_default_call_rcu_data))))
+struct call_rcu_data *alias_get_default_call_rcu_data();
 
 /*
  * Return the call_rcu_data structure that applies to the currently
@@ -591,6 +602,8 @@ struct call_rcu_data *get_call_rcu_data(void)
 
        return get_default_call_rcu_data();
 }
+__attribute__((alias(urcu_stringify(get_call_rcu_data))))
+struct call_rcu_data *alias_get_call_rcu_data();
 
 /*
  * Return a pointer to this task's call_rcu_data if there is one.
@@ -600,6 +613,8 @@ struct call_rcu_data *get_thread_call_rcu_data(void)
 {
        return URCU_TLS(thread_call_rcu_data);
 }
+__attribute__((alias(urcu_stringify(get_thread_call_rcu_data))))
+struct call_rcu_data *alias_get_thread_call_rcu_data();
 
 /*
  * Set this task's call_rcu_data structure as specified, regardless
@@ -616,6 +631,8 @@ void set_thread_call_rcu_data(struct call_rcu_data *crdp)
 {
        URCU_TLS(thread_call_rcu_data) = crdp;
 }
+__attribute__((alias(urcu_stringify(set_thread_call_rcu_data))))
+void alias_set_thread_call_rcu_data();
 
 /*
  * Create a separate call_rcu thread for each CPU.  This does not
@@ -667,6 +684,8 @@ int create_all_cpu_call_rcu_data(unsigned long flags)
        }
        return 0;
 }
+__attribute__((alias(urcu_stringify(create_all_cpu_call_rcu_data))))
+int alias_create_all_cpu_call_rcu_data();
 
 /*
  * Wake up the call_rcu thread corresponding to the specified
@@ -714,6 +733,7 @@ void call_rcu(struct rcu_head *head,
        _call_rcu(head, func, crdp);
        _rcu_read_unlock();
 }
+__attribute__((alias(urcu_stringify(call_rcu)))) void alias_call_rcu();
 
 /*
  * Free up the specified call_rcu_data structure, terminating the
@@ -769,6 +789,8 @@ void call_rcu_data_free(struct call_rcu_data *crdp)
 
        free(crdp);
 }
+__attribute__((alias(urcu_stringify(call_rcu_data_free))))
+void alias_call_rcu_data_free();
 
 /*
  * Clean up all the per-CPU call_rcu threads.
@@ -809,6 +831,16 @@ void free_all_cpu_call_rcu_data(void)
        }
        free(crdp);
 }
+#ifdef RCU_QSBR
+/* ABI6 has a non-namespaced free_all_cpu_call_rcu_data for qsbr */
+#undef free_all_cpu_call_rcu_data
+__attribute__((alias("urcu_qsbr_free_all_cpu_call_rcu_data")))
+void free_all_cpu_call_rcu_data();
+#define free_all_cpu_call_rcu_data urcu_qsbr_free_all_cpu_call_rcu_data
+#else
+__attribute__((alias(urcu_stringify(free_all_cpu_call_rcu_data))))
+void alias_free_all_cpu_call_rcu_data();
+#endif
 
 static
 void free_completion(struct urcu_ref *ref)
@@ -900,6 +932,8 @@ online:
        if (was_online)
                rcu_thread_online();
 }
+__attribute__((alias(urcu_stringify(rcu_barrier))))
+void alias_rcu_barrier();
 
 /*
  * Acquire the call_rcu_mutex in order to ensure that the child sees
@@ -928,6 +962,8 @@ void call_rcu_before_fork(void)
                        (void) poll(NULL, 0, 1);
        }
 }
+__attribute__((alias(urcu_stringify(call_rcu_before_fork))))
+void alias_call_rcu_before_fork();
 
 /*
  * Clean up call_rcu data structures in the parent of a successful fork()
@@ -950,6 +986,8 @@ void call_rcu_after_fork_parent(void)
                atfork->after_fork_parent(atfork->priv);
        call_rcu_unlock(&call_rcu_mutex);
 }
+__attribute__((alias(urcu_stringify(call_rcu_after_fork_parent))))
+void alias_call_rcu_after_fork_parent();
 
 /*
  * Clean up call_rcu data structures in the child of a successful fork()
@@ -997,6 +1035,8 @@ void call_rcu_after_fork_child(void)
                call_rcu_data_free(crdp);
        }
 }
+__attribute__((alias(urcu_stringify(call_rcu_after_fork_child))))
+void alias_call_rcu_after_fork_child();
 
 void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork)
 {
@@ -1007,6 +1047,8 @@ void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork)
 end:
        call_rcu_unlock(&call_rcu_mutex);
 }
+__attribute__((alias(urcu_stringify(urcu_register_rculfhash_atfork))))
+void alias_urcu_register_rculfhash_atfork();
 
 void urcu_unregister_rculfhash_atfork(struct urcu_atfork *atfork)
 {
@@ -1017,3 +1059,5 @@ void urcu_unregister_rculfhash_atfork(struct urcu_atfork *atfork)
 end:
        call_rcu_unlock(&call_rcu_mutex);
 }
+__attribute__((alias(urcu_stringify(urcu_unregister_rculfhash_atfork))))
+void alias_urcu_unregister_rculfhash_atfork();
diff --git a/src/urcu-call-rcu.h b/src/urcu-call-rcu.h
deleted file mode 100644 (file)
index 339ebac..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef _URCU_CALL_RCU_H
-#define _URCU_CALL_RCU_H
-
-/*
- * urcu-call-rcu.h
- *
- * Userspace RCU header - deferred execution
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- *
- * LGPL-compatible code should include this header with :
- *
- * #define _LGPL_SOURCE
- * #include <urcu-defer.h>
- *
- * 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 <stdlib.h>
-#include <pthread.h>
-
-#include <urcu/wfcqueue.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Note that struct call_rcu_data is opaque to callers. */
-
-struct call_rcu_data;
-
-/* Flag values. */
-
-#define URCU_CALL_RCU_RT       (1U << 0)
-#define URCU_CALL_RCU_RUNNING  (1U << 1)
-#define URCU_CALL_RCU_STOP     (1U << 2)
-#define URCU_CALL_RCU_STOPPED  (1U << 3)
-#define URCU_CALL_RCU_PAUSE    (1U << 4)
-#define URCU_CALL_RCU_PAUSED   (1U << 5)
-
-/*
- * The rcu_head data structure is placed in the structure to be freed
- * via call_rcu().
- */
-
-struct rcu_head {
-       struct cds_wfcq_node next;
-       void (*func)(struct rcu_head *head);
-};
-
-/*
- * Exported functions
- *
- * Important: see rcu-api.md in userspace-rcu documentation for
- * call_rcu family of functions usage detail, including the surrounding
- * RCU usage required when using these primitives.
- */
-
-void call_rcu(struct rcu_head *head,
-             void (*func)(struct rcu_head *head));
-
-struct call_rcu_data *create_call_rcu_data(unsigned long flags,
-                                          int cpu_affinity);
-void call_rcu_data_free(struct call_rcu_data *crdp);
-
-struct call_rcu_data *get_default_call_rcu_data(void);
-struct call_rcu_data *get_cpu_call_rcu_data(int cpu);
-struct call_rcu_data *get_thread_call_rcu_data(void);
-struct call_rcu_data *get_call_rcu_data(void);
-pthread_t get_call_rcu_thread(struct call_rcu_data *crdp);
-
-void set_thread_call_rcu_data(struct call_rcu_data *crdp);
-int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp);
-
-int create_all_cpu_call_rcu_data(unsigned long flags);
-void free_all_cpu_call_rcu_data(void);
-
-void call_rcu_before_fork(void);
-void call_rcu_after_fork_parent(void);
-void call_rcu_after_fork_child(void);
-
-void rcu_barrier(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _URCU_CALL_RCU_H */
index f965533..58ca1ab 100644 (file)
@@ -50,6 +50,7 @@
 #include <urcu/system.h>
 #include <urcu/tls-compat.h>
 #include "urcu-die.h"
+#include "urcu-utils.h"
 
 /*
  * Number of entries in the per-thread defer queue. Must be power of 2.
@@ -107,7 +108,7 @@ struct defer_queue {
 };
 
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
-#include "urcu-defer.h"
+#include <urcu/defer.h>
 
 void __attribute__((destructor)) rcu_defer_exit(void);
 
@@ -264,6 +265,8 @@ void rcu_defer_barrier_thread(void)
        _rcu_defer_barrier_thread();
        mutex_unlock(&rcu_defer_mutex);
 }
+__attribute__((alias(urcu_stringify(rcu_defer_barrier_thread))))
+void alias_rcu_defer_barrier_thread();
 
 /*
  * rcu_defer_barrier - Execute all queued rcu callbacks.
@@ -304,6 +307,8 @@ void rcu_defer_barrier(void)
 end:
        mutex_unlock(&rcu_defer_mutex);
 }
+__attribute__((alias(urcu_stringify(rcu_defer_barrier))))
+void alias_rcu_defer_barrier();
 
 /*
  * _defer_rcu - Queue a RCU callback.
@@ -396,6 +401,7 @@ void defer_rcu(void (*fct)(void *p), void *p)
 {
        _defer_rcu(fct, p);
 }
+__attribute__((alias(urcu_stringify(defer_rcu)))) void alias_defer_rcu();
 
 static void start_defer_thread(void)
 {
@@ -444,6 +450,8 @@ int rcu_defer_register_thread(void)
        mutex_unlock(&defer_thread_mutex);
        return 0;
 }
+__attribute__((alias(urcu_stringify(rcu_defer_register_thread))))
+int alias_rcu_defer_register_thread();
 
 void rcu_defer_unregister_thread(void)
 {
@@ -462,10 +470,14 @@ void rcu_defer_unregister_thread(void)
                stop_defer_thread();
        mutex_unlock(&defer_thread_mutex);
 }
+__attribute__((alias(urcu_stringify(rcu_defer_unregister_thread))))
+void alias_rcu_defer_unregister_thread();
 
 void rcu_defer_exit(void)
 {
        assert(cds_list_empty(&registry_defer));
 }
+__attribute__((alias(urcu_stringify(rcu_defer_exit))))
+void alias_rcu_defer_exit();
 
 #endif /* _URCU_DEFER_IMPL_H */
diff --git a/src/urcu-defer.h b/src/urcu-defer.h
deleted file mode 100644 (file)
index 43eca34..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef _URCU_BATCH_H
-#define _URCU_BATCH_H
-
-/*
- * urcu-defer.h
- *
- * Userspace RCU header - deferred execution
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- *
- * LGPL-compatible code should include this header with :
- *
- * #define _LGPL_SOURCE
- * #include <urcu-defer.h>
- *
- * 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 <stdlib.h>
-#include <pthread.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * Note: the defer_rcu() API is currently EXPERIMENTAL. It may change in the
- * future.
- *
- * Important !
- *
- * Each thread queuing memory reclamation must be registered with
- * rcu_defer_register_thread(). rcu_defer_unregister_thread() should be
- * called before the thread exits.
- *
- * *NEVER* use defer_rcu() within a RCU read-side critical section, because this
- * primitive need to call synchronize_rcu() if the thread queue is full.
- */
-
-extern void defer_rcu(void (*fct)(void *p), void *p);
-
-/*
- * Thread registration for reclamation.
- */
-extern int rcu_defer_register_thread(void);
-extern void rcu_defer_unregister_thread(void);
-extern void rcu_defer_barrier(void);
-extern void rcu_defer_barrier_thread(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _URCU_BATCH_H */
diff --git a/src/urcu-flavor.h b/src/urcu-flavor.h
deleted file mode 100644 (file)
index 9cfbd6a..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef _URCU_FLAVOR_H
-#define _URCU_FLAVOR_H
-
-/*
- * urcu-flavor.h
- *
- * Userspace RCU header - rcu flavor declarations
- *
- * Copyright (c) 2011 Lai Jiangshan <laijs@cn.fujitsu.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
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct urcu_atfork {
-       void (*before_fork)(void *priv);
-       void (*after_fork_parent)(void *priv);
-       void (*after_fork_child)(void *priv);
-       void *priv;
-};
-
-void urcu_register_rculfhash_atfork(struct urcu_atfork *atfork);
-void urcu_unregister_rculfhash_atfork(struct urcu_atfork *atfork);
-
-struct rcu_flavor_struct {
-       void (*read_lock)(void);
-       void (*read_unlock)(void);
-       int (*read_ongoing)(void);
-       void (*read_quiescent_state)(void);
-       void (*update_call_rcu)(struct rcu_head *head,
-                               void (*func)(struct rcu_head *head));
-       void (*update_synchronize_rcu)(void);
-       void (*update_defer_rcu)(void (*fct)(void *p), void *p);
-
-       void (*thread_offline)(void);
-       void (*thread_online)(void);
-       void (*register_thread)(void);
-       void (*unregister_thread)(void);
-
-       void (*barrier)(void);
-
-       void (*register_rculfhash_atfork)(struct urcu_atfork *atfork);
-       void (*unregister_rculfhash_atfork)(struct urcu_atfork *atfork);
-};
-
-#define DEFINE_RCU_FLAVOR(x)                           \
-const struct rcu_flavor_struct x = {                   \
-       .read_lock              = rcu_read_lock,        \
-       .read_unlock            = rcu_read_unlock,      \
-       .read_ongoing           = rcu_read_ongoing,     \
-       .read_quiescent_state   = rcu_quiescent_state,  \
-       .update_call_rcu        = call_rcu,             \
-       .update_synchronize_rcu = synchronize_rcu,      \
-       .update_defer_rcu       = defer_rcu,            \
-       .thread_offline         = rcu_thread_offline,   \
-       .thread_online          = rcu_thread_online,    \
-       .register_thread        = rcu_register_thread,  \
-       .unregister_thread      = rcu_unregister_thread,\
-       .barrier                = rcu_barrier,          \
-       .register_rculfhash_atfork = urcu_register_rculfhash_atfork,    \
-       .unregister_rculfhash_atfork = urcu_unregister_rculfhash_atfork,\
-}
-
-extern const struct rcu_flavor_struct rcu_flavor;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _URCU_FLAVOR_H */
diff --git a/src/urcu-pointer.h b/src/urcu-pointer.h
deleted file mode 100644 (file)
index dc1a0da..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef _URCU_POINTER_H
-#define _URCU_POINTER_H
-
-/*
- * urcu-pointer.h
- *
- * Userspace RCU header. Operations on pointers.
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- *
- * 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
- *
- * IBM's contributions to this file may be relicensed under LGPLv2 or later.
- */
-
-#include <urcu/compiler.h>
-#include <urcu/arch.h>
-#include <urcu/uatomic.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)
-
-#include <urcu/static/urcu-pointer.h>
-
-/*
- * rcu_dereference(ptr)
- *
- * Fetch a RCU-protected pointer. Typically used to copy the variable ptr to a
- * local variable.
- */
-#define rcu_dereference                _rcu_dereference
-
-/*
- * type *rcu_cmpxchg_pointer(type **ptr, type *new, type *old)
- * type *rcu_xchg_pointer(type **ptr, type *new)
- * void rcu_set_pointer(type **ptr, type *new)
- *
- * RCU pointer updates.
- * @ptr: address of the pointer to modify
- * @new: new pointer value
- * @old: old pointer value (expected)
- *
- * return: old pointer value
- */
-#define rcu_cmpxchg_pointer    _rcu_cmpxchg_pointer
-#define rcu_xchg_pointer       _rcu_xchg_pointer
-#define rcu_set_pointer                _rcu_set_pointer
-
-#else /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
-
-extern void *rcu_dereference_sym(void *p);
-#define rcu_dereference(p)                                                  \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(p) _________p1 =     URCU_FORCE_CAST(__typeof__(p), \
-                       rcu_dereference_sym(URCU_FORCE_CAST(void *, p)));    \
-               (_________p1);                                               \
-       })
-
-extern void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new);
-#define rcu_cmpxchg_pointer(p, old, _new)                                   \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(*(p)) _________pold = (old);                      \
-               __typeof__(*(p)) _________pnew = (_new);                     \
-               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
-                       rcu_cmpxchg_pointer_sym(URCU_FORCE_CAST(void **, p), \
-                                               _________pold,               \
-                                               _________pnew));             \
-               (_________p1);                                               \
-       })
-
-extern void *rcu_xchg_pointer_sym(void **p, void *v);
-#define rcu_xchg_pointer(p, v)                                              \
-       __extension__                                                        \
-       ({                                                                   \
-               __typeof__(*(p)) _________pv = (v);                          \
-               __typeof__(*(p)) _________p1 = URCU_FORCE_CAST(__typeof__(*(p)), \
-                       rcu_xchg_pointer_sym(URCU_FORCE_CAST(void **, p),    \
-                                            _________pv));                  \
-               (_________p1);                                               \
-       })
-
-/*
- * Note: rcu_set_pointer_sym returns @v because we don't want to break
- * the ABI. At the API level, rcu_set_pointer() now returns void. Use of
- * the return value is therefore deprecated, and will cause a build
- * error.
- */
-extern void *rcu_set_pointer_sym(void **p, void *v);
-#define rcu_set_pointer(p, v)                                               \
-       do {                                                                 \
-               __typeof__(*(p)) _________pv = (v);                          \
-               (void) rcu_set_pointer_sym(URCU_FORCE_CAST(void **, p),      \
-                                           _________pv);                    \
-       } while (0)
-
-#endif /* !(defined(_LGPL_SOURCE) || defined(URCU_INLINE_SMALL_FUNCTIONS)) */
-
-/*
- * void rcu_assign_pointer(type *ptr, type *new)
- *
- * Same as rcu_set_pointer, but takes the pointer to assign to rather than its
- * address as first parameter. Provided for compatibility with the Linux kernel
- * RCU semantic.
- */
-#define rcu_assign_pointer(p, v)       rcu_set_pointer((&p), (v))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _URCU_POINTER_H */
index e029ace..346748b 100644 (file)
 #include <errno.h>
 #include <poll.h>
 
-#include "urcu/wfcqueue.h"
-#include "urcu/map/urcu-qsbr.h"
+#include <urcu/wfcqueue.h>
+#include <urcu/map/urcu-qsbr.h>
 #define BUILD_QSBR_LIB
-#include "urcu/static/urcu-qsbr.h"
-#include "urcu-pointer.h"
-#include "urcu/tls-compat.h"
+#include <urcu/static/urcu-qsbr.h>
+#include <urcu/pointer.h>
+#include <urcu/tls-compat.h>
 
 #include "urcu-die.h"
 #include "urcu-wait.h"
 
+#define URCU_API_MAP
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #undef _LGPL_SOURCE
-#include "urcu-qsbr.h"
+#include <urcu/urcu-qsbr.h>
 #define _LGPL_SOURCE
 
-void __attribute__((destructor)) rcu_exit(void);
+void __attribute__((destructor)) urcu_qsbr_exit(void);
 
 /*
  * rcu_gp_lock ensures mutual exclusion between threads calling
@@ -66,7 +67,8 @@ static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
  * rcu_registry_lock may nest inside rcu_gp_lock.
  */
 static pthread_mutex_t rcu_registry_lock = PTHREAD_MUTEX_INITIALIZER;
-struct rcu_gp rcu_gp = { .ctr = RCU_GP_ONLINE };
+struct urcu_gp urcu_qsbr_gp = { .ctr = URCU_QSBR_GP_ONLINE };
+__attribute__((alias("urcu_qsbr_gp"))) extern struct urcu_gp rcu_gp_qsbr;
 
 /*
  * Active attempts to check for reader Q.S. before calling futex().
@@ -77,7 +79,9 @@ struct rcu_gp rcu_gp = { .ctr = RCU_GP_ONLINE };
  * Written to only by each individual reader. Read by both the reader and the
  * writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader, rcu_reader);
+DEFINE_URCU_TLS(struct urcu_qsbr_reader, urcu_qsbr_reader);
+__attribute__((alias("urcu_qsbr_reader")))
+extern struct urcu_qsbr_reader rcu_reader_qsbr;
 
 static CDS_LIST_HEAD(registry);
 
@@ -120,9 +124,9 @@ static void wait_gp(void)
 {
        /* Read reader_gp before read futex */
        cmm_smp_rmb();
-       if (uatomic_read(&rcu_gp.futex) != -1)
+       if (uatomic_read(&urcu_qsbr_gp.futex) != -1)
                return;
-       while (futex_noasync(&rcu_gp.futex, FUTEX_WAIT, -1,
+       while (futex_noasync(&urcu_qsbr_gp.futex, FUTEX_WAIT, -1,
                        NULL, NULL, 0)) {
                switch (errno) {
                case EWOULDBLOCK:
@@ -147,18 +151,18 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        struct cds_list_head *qsreaders)
 {
        unsigned int wait_loops = 0;
-       struct rcu_reader *index, *tmp;
+       struct urcu_qsbr_reader *index, *tmp;
 
        /*
-        * Wait for each thread URCU_TLS(rcu_reader).ctr to either
+        * Wait for each thread URCU_TLS(urcu_qsbr_reader).ctr to either
         * indicate quiescence (offline), or for them to observe the
-        * current rcu_gp.ctr value.
+        * current urcu_qsbr_gp.ctr value.
         */
        for (;;) {
                if (wait_loops < RCU_QS_ACTIVE_ATTEMPTS)
                        wait_loops++;
                if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) {
-                       uatomic_set(&rcu_gp.futex, -1);
+                       uatomic_set(&urcu_qsbr_gp.futex, -1);
                        /*
                         * Write futex before write waiting (the other side
                         * reads them in the opposite order).
@@ -171,18 +175,18 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        cmm_smp_mb();
                }
                cds_list_for_each_entry_safe(index, tmp, input_readers, node) {
-                       switch (rcu_reader_state(&index->ctr)) {
-                       case RCU_READER_ACTIVE_CURRENT:
+                       switch (urcu_qsbr_reader_state(&index->ctr)) {
+                       case URCU_READER_ACTIVE_CURRENT:
                                if (cur_snap_readers) {
                                        cds_list_move(&index->node,
                                                cur_snap_readers);
                                        break;
                                }
                                /* Fall-through */
-                       case RCU_READER_INACTIVE:
+                       case URCU_READER_INACTIVE:
                                cds_list_move(&index->node, qsreaders);
                                break;
-                       case RCU_READER_ACTIVE_OLD:
+                       case URCU_READER_ACTIVE_OLD:
                                /*
                                 * Old snapshot. Leaving node in
                                 * input_readers will make us busy-loop
@@ -197,7 +201,7 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        if (wait_loops >= RCU_QS_ACTIVE_ATTEMPTS) {
                                /* Read reader_gp before write futex */
                                cmm_smp_mb();
-                               uatomic_set(&rcu_gp.futex, 0);
+                               uatomic_set(&urcu_qsbr_gp.futex, 0);
                        }
                        break;
                } else {
@@ -224,7 +228,7 @@ static void wait_for_readers(struct cds_list_head *input_readers,
  */
 
 #if (CAA_BITS_PER_LONG < 64)
-void synchronize_rcu(void)
+void urcu_qsbr_synchronize_rcu(void)
 {
        CDS_LIST_HEAD(cur_snap_readers);
        CDS_LIST_HEAD(qsreaders);
@@ -232,7 +236,7 @@ void synchronize_rcu(void)
        DEFINE_URCU_WAIT_NODE(wait, URCU_WAIT_WAITING);
        struct urcu_waiters waiters;
 
-       was_online = rcu_read_ongoing();
+       was_online = urcu_qsbr_read_ongoing();
 
        /* All threads should read qparity before accessing data structure
         * where new ptr points to.  In the "then" case, rcu_thread_offline
@@ -243,7 +247,7 @@ void synchronize_rcu(void)
         * in threads registered as readers.
         */
        if (was_online)
-               rcu_thread_offline();
+               urcu_qsbr_thread_offline();
        else
                cmm_smp_mb();
 
@@ -281,11 +285,11 @@ void synchronize_rcu(void)
 
        /*
         * Must finish waiting for quiescent state for original parity
-        * before committing next rcu_gp.ctr update to memory. Failure
+        * before committing next urcu_qsbr_gp.ctr update to memory. Failure
         * to do so could result in the writer waiting forever while new
         * readers are always accessing data (no progress).  Enforce
-        * compiler-order of load URCU_TLS(rcu_reader).ctr before store
-        * to rcu_gp.ctr.
+        * compiler-order of load URCU_TLS(urcu_qsbr_reader).ctr before store
+        * to urcu_qsbr_gp.ctr.
         */
        cmm_barrier();
 
@@ -297,14 +301,14 @@ void synchronize_rcu(void)
        cmm_smp_mb();
 
        /* Switch parity: 0 -> 1, 1 -> 0 */
-       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ RCU_GP_CTR);
+       CMM_STORE_SHARED(urcu_qsbr_gp.ctr, urcu_qsbr_gp.ctr ^ URCU_QSBR_GP_CTR);
 
        /*
-        * Must commit rcu_gp.ctr update to memory before waiting for
+        * Must commit urcu_qsbr_gp.ctr update to memory before waiting for
         * quiescent state. Failure to do so could result in the writer
         * waiting forever while new readers are always accessing data
-        * (no progress). Enforce compiler-order of store to rcu_gp.ctr
-        * before load URCU_TLS(rcu_reader).ctr.
+        * (no progress). Enforce compiler-order of store to urcu_qsbr_gp.ctr
+        * before load URCU_TLS(urcu_qsbr_reader).ctr.
         */
        cmm_barrier();
 
@@ -336,19 +340,19 @@ gp_end:
         * freed.
         */
        if (was_online)
-               rcu_thread_online();
+               urcu_qsbr_thread_online();
        else
                cmm_smp_mb();
 }
 #else /* !(CAA_BITS_PER_LONG < 64) */
-void synchronize_rcu(void)
+void urcu_qsbr_synchronize_rcu(void)
 {
        CDS_LIST_HEAD(qsreaders);
        unsigned long was_online;
        DEFINE_URCU_WAIT_NODE(wait, URCU_WAIT_WAITING);
        struct urcu_waiters waiters;
 
-       was_online = rcu_read_ongoing();
+       was_online = urcu_qsbr_read_ongoing();
 
        /*
         * Mark the writer thread offline to make sure we don't wait for
@@ -356,7 +360,7 @@ void synchronize_rcu(void)
         * in threads registered as readers.
         */
        if (was_online)
-               rcu_thread_offline();
+               urcu_qsbr_thread_offline();
        else
                cmm_smp_mb();
 
@@ -386,14 +390,14 @@ void synchronize_rcu(void)
                goto out;
 
        /* Increment current G.P. */
-       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr + RCU_GP_CTR);
+       CMM_STORE_SHARED(urcu_qsbr_gp.ctr, urcu_qsbr_gp.ctr + URCU_QSBR_GP_CTR);
 
        /*
-        * Must commit rcu_gp.ctr update to memory before waiting for
+        * Must commit urcu_qsbr_gp.ctr update to memory before waiting for
         * quiescent state. Failure to do so could result in the writer
         * waiting forever while new readers are always accessing data
-        * (no progress). Enforce compiler-order of store to rcu_gp.ctr
-        * before load URCU_TLS(rcu_reader).ctr.
+        * (no progress). Enforce compiler-order of store to urcu_qsbr_gp.ctr
+        * before load URCU_TLS(urcu_qsbr_reader).ctr.
         */
        cmm_barrier();
 
@@ -421,74 +425,90 @@ out:
        urcu_wake_all_waiters(&waiters);
 gp_end:
        if (was_online)
-               rcu_thread_online();
+               urcu_qsbr_thread_online();
        else
                cmm_smp_mb();
 }
 #endif  /* !(CAA_BITS_PER_LONG < 64) */
+__attribute__((alias("urcu_qsbr_synchronize_rcu")))
+void synchronize_rcu_qsbr();
 
 /*
  * library wrappers to be used by non-LGPL compatible source code.
  */
 
-void rcu_read_lock(void)
+void urcu_qsbr_read_lock(void)
 {
-       _rcu_read_lock();
+       _urcu_qsbr_read_lock();
 }
+__attribute__((alias("urcu_qsbr_read_lock"))) void rcu_read_lock_qsbr();
 
-void rcu_read_unlock(void)
+void urcu_qsbr_read_unlock(void)
 {
-       _rcu_read_unlock();
+       _urcu_qsbr_read_unlock();
 }
+__attribute__((alias("urcu_qsbr_read_unlock"))) void rcu_read_unlock_qsbr();
 
-int rcu_read_ongoing(void)
+int urcu_qsbr_read_ongoing(void)
 {
-       return _rcu_read_ongoing();
+       return _urcu_qsbr_read_ongoing();
 }
+__attribute__((alias("urcu_qsbr_read_ongoing")))
+void rcu_read_ongoing_qsbr();
 
-void rcu_quiescent_state(void)
+void urcu_qsbr_quiescent_state(void)
 {
-       _rcu_quiescent_state();
+       _urcu_qsbr_quiescent_state();
 }
+__attribute__((alias("urcu_qsbr_quiescent_state")))
+void rcu_quiescent_state_qsbr();
 
-void rcu_thread_offline(void)
+void urcu_qsbr_thread_offline(void)
 {
-       _rcu_thread_offline();
+       _urcu_qsbr_thread_offline();
 }
+__attribute__((alias("urcu_qsbr_thread_offline")))
+void rcu_thread_offline_qsbr();
 
-void rcu_thread_online(void)
+void urcu_qsbr_thread_online(void)
 {
-       _rcu_thread_online();
+       _urcu_qsbr_thread_online();
 }
+__attribute__((alias("urcu_qsbr_thread_online")))
+void rcu_thread_online_qsbr();
 
-void rcu_register_thread(void)
+void urcu_qsbr_register_thread(void)
 {
-       URCU_TLS(rcu_reader).tid = pthread_self();
-       assert(URCU_TLS(rcu_reader).ctr == 0);
+       URCU_TLS(urcu_qsbr_reader).tid = pthread_self();
+       assert(URCU_TLS(urcu_qsbr_reader).ctr == 0);
 
        mutex_lock(&rcu_registry_lock);
-       assert(!URCU_TLS(rcu_reader).registered);
-       URCU_TLS(rcu_reader).registered = 1;
-       cds_list_add(&URCU_TLS(rcu_reader).node, &registry);
+       assert(!URCU_TLS(urcu_qsbr_reader).registered);
+       URCU_TLS(urcu_qsbr_reader).registered = 1;
+       cds_list_add(&URCU_TLS(urcu_qsbr_reader).node, &registry);
        mutex_unlock(&rcu_registry_lock);
-       _rcu_thread_online();
+       _urcu_qsbr_thread_online();
 }
+__attribute__((alias("urcu_qsbr_register_thread")))
+void rcu_register_thread_qsbr();
 
-void rcu_unregister_thread(void)
+void urcu_qsbr_unregister_thread(void)
 {
        /*
         * We have to make the thread offline otherwise we end up dealocking
         * with a waiting writer.
         */
-       _rcu_thread_offline();
-       assert(URCU_TLS(rcu_reader).registered);
-       URCU_TLS(rcu_reader).registered = 0;
+       _urcu_qsbr_thread_offline();
+       assert(URCU_TLS(urcu_qsbr_reader).registered);
+       URCU_TLS(urcu_qsbr_reader).registered = 0;
        mutex_lock(&rcu_registry_lock);
-       cds_list_del(&URCU_TLS(rcu_reader).node);
+       cds_list_del(&URCU_TLS(urcu_qsbr_reader).node);
        mutex_unlock(&rcu_registry_lock);
 }
+__attribute__((alias("urcu_qsbr_unregister_thread")))
+void rcu_unregister_thread_qsbr();
 
-void rcu_exit(void)
+void urcu_qsbr_exit(void)
 {
        /*
         * Assertion disabled because call_rcu threads are now rcu
@@ -496,8 +516,10 @@ void rcu_exit(void)
         * assert(cds_list_empty(&registry));
         */
 }
+__attribute__((alias("urcu_qsbr_exit"))) void rcu_exit_qsbr();
 
 DEFINE_RCU_FLAVOR(rcu_flavor);
+DEFINE_RCU_FLAVOR_ALIAS(rcu_flavor, alias_rcu_flavor);
 
 #include "urcu-call-rcu-impl.h"
 #include "urcu-defer-impl.h"
diff --git a/src/urcu-qsbr.h b/src/urcu-qsbr.h
deleted file mode 100644 (file)
index 5e47ad6..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef _URCU_QSBR_H
-#define _URCU_QSBR_H
-
-/*
- * urcu-qsbr.h
- *
- * Userspace RCU QSBR header.
- *
- * LGPL-compatible code should include this header with :
- *
- * #define _LGPL_SOURCE
- * #include <urcu.h>
- *
- * 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
- *
- * IBM's contributions to this file may be relicensed under LGPLv2 or later.
- */
-
-#include <stdlib.h>
-#include <pthread.h>
-
-/*
- * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
- * publication headers.
- */
-#include <urcu-pointer.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <urcu/map/urcu-qsbr.h>
-
-#ifdef RCU_DEBUG       /* For backward compatibility */
-#define DEBUG_RCU
-#endif
-
-/*
- * Important !
- *
- * Each thread containing read-side critical sections must be registered
- * with rcu_register_thread() before calling rcu_read_lock().
- * rcu_unregister_thread() should be called before the thread exits.
- */
-
-#ifdef _LGPL_SOURCE
-
-#include <urcu/static/urcu-qsbr.h>
-
-/*
- * Mappings for static use of the userspace RCU library.
- * Should only be used in LGPL-compatible code.
- */
-
-/*
- * rcu_read_lock()
- * rcu_read_unlock()
- *
- * Mark the beginning and end of a read-side critical section.
- * DON'T FORGET TO USE rcu_register_thread/rcu_unregister_thread()
- * FOR EACH THREAD WITH READ-SIDE CRITICAL SECTION.
- */
-#define rcu_read_lock_qsbr             _rcu_read_lock
-#define rcu_read_unlock_qsbr           _rcu_read_unlock
-#define rcu_read_ongoing_qsbr          _rcu_read_ongoing
-
-#define rcu_quiescent_state_qsbr       _rcu_quiescent_state
-#define rcu_thread_offline_qsbr                _rcu_thread_offline
-#define rcu_thread_online_qsbr         _rcu_thread_online
-
-#else /* !_LGPL_SOURCE */
-
-/*
- * library wrappers to be used by non-LGPL compatible source code.
- */
-
-/*
- * QSBR read lock/unlock are guaranteed to be no-ops. Therefore, we expose them
- * in the LGPL header for any code to use. However, the debug version is not
- * nops and may contain sanity checks. To activate it, applications must be
- * recompiled with -DDEBUG_RCU (even non-LGPL/GPL applications), or
- * compiled against a urcu/config.h that has CONFIG_RCU_DEBUG defined.
- * This is the best trade-off between license/performance/code
- * triviality and library debugging & tracing features we could come up
- * with.
- */
-
-#if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG))
-
-static inline void rcu_read_lock(void)
-{
-}
-
-static inline void rcu_read_unlock(void)
-{
-}
-
-#else /* #if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG)) */
-
-extern void rcu_read_lock(void);
-extern void rcu_read_unlock(void);
-
-#endif /* #else #if (!defined(BUILD_QSBR_LIB) && !defined(DEBUG_RCU) && !defined(CONFIG_RCU_DEBUG)) */
-
-extern int rcu_read_ongoing(void);
-extern void rcu_quiescent_state(void);
-extern void rcu_thread_offline(void);
-extern void rcu_thread_online(void);
-
-#endif /* !_LGPL_SOURCE */
-
-extern void synchronize_rcu(void);
-
-/*
- * Reader thread registration.
- */
-extern void rcu_register_thread(void);
-extern void rcu_unregister_thread(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#include <urcu-call-rcu.h>
-#include <urcu-defer.h>
-#include <urcu-flavor.h>
-
-#endif /* _URCU_QSBR_H */
diff --git a/src/urcu-utils.h b/src/urcu-utils.h
new file mode 100644 (file)
index 0000000..1d91bc9
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _URCU_UTILS_H
+#define _URCU_UTILS_H
+
+/*
+ * urcu-utils.h
+ *
+ * Userspace RCU library internal utils
+ *
+ * Copyright (c) 2018 Michael Jeanson <mjeanson@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
+ */
+
+#define urcu_stringify(a) _urcu_stringify(a)
+#define _urcu_stringify(a) #a
+
+#endif /* _URCU_UTILS_H */
index c47f51b..c36119a 100644 (file)
 #include <stdbool.h>
 #include <poll.h>
 
-#include "urcu/arch.h"
-#include "urcu/wfcqueue.h"
-#include "urcu/map/urcu.h"
-#include "urcu/static/urcu.h"
-#include "urcu-pointer.h"
-#include "urcu/tls-compat.h"
+#include <urcu/arch.h>
+#include <urcu/wfcqueue.h>
+#include <urcu/map/urcu.h>
+#include <urcu/static/urcu.h>
+#include <urcu/pointer.h>
+#include <urcu/tls-compat.h>
 
 #include "urcu-die.h"
 #include "urcu-wait.h"
+#include "urcu-utils.h"
 
+#define URCU_API_MAP
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #undef _LGPL_SOURCE
-#include "urcu.h"
+#include <urcu/urcu.h>
 #define _LGPL_SOURCE
 
 /*
@@ -82,10 +84,16 @@ enum membarrier_cmd {
 
 #ifdef RCU_MEMBARRIER
 static int init_done;
-static int has_sys_membarrier_private_expedited;
+static int urcu_memb_has_sys_membarrier_private_expedited;
 
 #ifndef CONFIG_RCU_FORCE_SYS_MEMBARRIER
-int rcu_has_sys_membarrier_memb;
+/*
+ * Explicitly initialize to zero because we can't alias a non-static
+ * uninitialized variable.
+ */
+int urcu_memb_has_sys_membarrier = 0;
+__attribute__((alias("urcu_memb_has_sys_membarrier")))
+extern int rcu_has_sys_membarrier_memb;
 #endif
 
 void __attribute__((constructor)) rcu_init(void);
@@ -95,6 +103,8 @@ void __attribute__((constructor)) rcu_init(void);
 void rcu_init(void)
 {
 }
+__attribute__((alias(urcu_stringify(rcu_init))))
+void alias_rcu_init(void);
 #endif
 
 #ifdef RCU_SIGNAL
@@ -119,13 +129,17 @@ static pthread_mutex_t rcu_gp_lock = PTHREAD_MUTEX_INITIALIZER;
  * rcu_registry_lock may nest inside rcu_gp_lock.
  */
 static pthread_mutex_t rcu_registry_lock = PTHREAD_MUTEX_INITIALIZER;
-struct rcu_gp rcu_gp = { .ctr = RCU_GP_COUNT };
+struct urcu_gp rcu_gp = { .ctr = URCU_GP_COUNT };
+__attribute__((alias(urcu_stringify(rcu_gp))))
+extern struct urcu_gp alias_rcu_gp;
 
 /*
  * Written to only by each individual reader. Read by both the reader and the
  * writers.
  */
-DEFINE_URCU_TLS(struct rcu_reader, rcu_reader);
+DEFINE_URCU_TLS(struct urcu_reader, rcu_reader);
+__attribute__((alias(urcu_stringify(rcu_reader))))
+extern struct urcu_reader alias_rcu_reader;
 
 static CDS_LIST_HEAD(registry);
 
@@ -169,8 +183,8 @@ static void mutex_unlock(pthread_mutex_t *mutex)
 #ifdef RCU_MEMBARRIER
 static void smp_mb_master(void)
 {
-       if (caa_likely(rcu_has_sys_membarrier_memb)) {
-               if (membarrier(has_sys_membarrier_private_expedited ?
+       if (caa_likely(urcu_memb_has_sys_membarrier)) {
+               if (membarrier(urcu_memb_has_sys_membarrier_private_expedited ?
                                MEMBARRIER_CMD_PRIVATE_EXPEDITED :
                                MEMBARRIER_CMD_SHARED, 0))
                        urcu_die(errno);
@@ -190,7 +204,7 @@ static void smp_mb_master(void)
 #ifdef RCU_SIGNAL
 static void force_mb_all_readers(void)
 {
-       struct rcu_reader *index;
+       struct urcu_reader *index;
 
        /*
         * Ask for each threads to execute a cmm_smp_mb() so we can consider the
@@ -283,7 +297,7 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                        struct cds_list_head *qsreaders)
 {
        unsigned int wait_loops = 0;
-       struct rcu_reader *index, *tmp;
+       struct urcu_reader *index, *tmp;
 #ifdef HAS_INCOHERENT_CACHES
        unsigned int wait_gp_loops = 0;
 #endif /* HAS_INCOHERENT_CACHES */
@@ -303,18 +317,18 @@ static void wait_for_readers(struct cds_list_head *input_readers,
                }
 
                cds_list_for_each_entry_safe(index, tmp, input_readers, node) {
-                       switch (rcu_reader_state(&index->ctr)) {
-                       case RCU_READER_ACTIVE_CURRENT:
+                       switch (urcu_common_reader_state(&rcu_gp, &index->ctr)) {
+                       case URCU_READER_ACTIVE_CURRENT:
                                if (cur_snap_readers) {
                                        cds_list_move(&index->node,
                                                cur_snap_readers);
                                        break;
                                }
                                /* Fall-through */
-                       case RCU_READER_INACTIVE:
+                       case URCU_READER_INACTIVE:
                                cds_list_move(&index->node, qsreaders);
                                break;
-                       case RCU_READER_ACTIVE_OLD:
+                       case URCU_READER_ACTIVE_OLD:
                                /*
                                 * Old snapshot. Leaving node in
                                 * input_readers will make us busy-loop
@@ -454,7 +468,7 @@ void synchronize_rcu(void)
        cmm_smp_mb();
 
        /* Switch parity: 0 -> 1, 1 -> 0 */
-       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ RCU_GP_CTR_PHASE);
+       CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr ^ URCU_GP_CTR_PHASE);
 
        /*
         * Must commit rcu_gp.ctr update to memory before waiting for quiescent
@@ -501,6 +515,8 @@ out:
         */
        urcu_wake_all_waiters(&waiters);
 }
+__attribute__((alias(urcu_stringify(synchronize_rcu))))
+void alias_synchronize_rcu();
 
 /*
  * library wrappers to be used by non-LGPL compatible source code.
@@ -510,22 +526,28 @@ void rcu_read_lock(void)
 {
        _rcu_read_lock();
 }
+__attribute__((alias(urcu_stringify(rcu_read_lock))))
+void alias_rcu_read_lock();
 
 void rcu_read_unlock(void)
 {
        _rcu_read_unlock();
 }
+__attribute__((alias(urcu_stringify(rcu_read_unlock))))
+void alias_rcu_read_unlock();
 
 int rcu_read_ongoing(void)
 {
        return _rcu_read_ongoing();
 }
+__attribute__((alias(urcu_stringify(rcu_read_ongoing))))
+void alias_rcu_read_ongoing();
 
 void rcu_register_thread(void)
 {
        URCU_TLS(rcu_reader).tid = pthread_self();
        assert(URCU_TLS(rcu_reader).need_mb == 0);
-       assert(!(URCU_TLS(rcu_reader).ctr & RCU_GP_CTR_NEST_MASK));
+       assert(!(URCU_TLS(rcu_reader).ctr & URCU_GP_CTR_NEST_MASK));
 
        mutex_lock(&rcu_registry_lock);
        assert(!URCU_TLS(rcu_reader).registered);
@@ -534,6 +556,8 @@ void rcu_register_thread(void)
        cds_list_add(&URCU_TLS(rcu_reader).node, &registry);
        mutex_unlock(&rcu_registry_lock);
 }
+__attribute__((alias(urcu_stringify(rcu_register_thread))))
+void alias_rcu_register_thread();
 
 void rcu_unregister_thread(void)
 {
@@ -543,6 +567,8 @@ void rcu_unregister_thread(void)
        cds_list_del(&URCU_TLS(rcu_reader).node);
        mutex_unlock(&rcu_registry_lock);
 }
+__attribute__((alias(urcu_stringify(rcu_unregister_thread))))
+void alias_rcu_unregister_thread();
 
 #ifdef RCU_MEMBARRIER
 
@@ -559,7 +585,7 @@ void rcu_sys_membarrier_status(bool available)
 {
        if (!available)
                return;
-       rcu_has_sys_membarrier_memb = 1;
+       urcu_memb_has_sys_membarrier = 1;
 }
 #endif
 
@@ -574,7 +600,7 @@ void rcu_sys_membarrier_init(void)
                if (mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED) {
                        if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0))
                                urcu_die(errno);
-                       has_sys_membarrier_private_expedited = 1;
+                       urcu_memb_has_sys_membarrier_private_expedited = 1;
                        available = true;
                } else if (mask & MEMBARRIER_CMD_SHARED) {
                        available = true;
@@ -590,6 +616,8 @@ void rcu_init(void)
        init_done = 1;
        rcu_sys_membarrier_init();
 }
+__attribute__((alias(urcu_stringify(rcu_init))))
+void alias_rcu_init(void);
 #endif
 
 #ifdef RCU_SIGNAL
@@ -629,6 +657,8 @@ void rcu_init(void)
        if (ret)
                urcu_die(errno);
 }
+__attribute__((alias(urcu_stringify(rcu_init))))
+void alias_rcu_init(void);
 
 void rcu_exit(void)
 {
@@ -641,10 +671,13 @@ void rcu_exit(void)
         * assert(cds_list_empty(&registry));
         */
 }
+__attribute__((alias(urcu_stringify(rcu_exit))))
+void alias_rcu_exit(void);
 
 #endif /* #ifdef RCU_SIGNAL */
 
 DEFINE_RCU_FLAVOR(rcu_flavor);
+DEFINE_RCU_FLAVOR_ALIAS(rcu_flavor, alias_rcu_flavor);
 
 #include "urcu-call-rcu-impl.h"
 #include "urcu-defer-impl.h"
diff --git a/src/urcu.h b/src/urcu.h
deleted file mode 100644 (file)
index 85d4a4c..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-#ifndef _URCU_H
-#define _URCU_H
-
-/*
- * urcu.h
- *
- * Userspace RCU header
- *
- * Copyright (c) 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- * Copyright (c) 2009 Paul E. McKenney, IBM Corporation.
- *
- * LGPL-compatible code should include this header with :
- *
- * #define _LGPL_SOURCE
- * #include <urcu.h>
- *
- * 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
- *
- * IBM's contributions to this file may be relicensed under LGPLv2 or later.
- */
-
-#include <stdlib.h>
-#include <pthread.h>
-
-/*
- * See urcu-pointer.h and urcu/static/urcu-pointer.h for pointer
- * publication headers.
- */
-#include <urcu-pointer.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <urcu/map/urcu.h>
-
-/*
- * Important !
- *
- * Each thread containing read-side critical sections must be registered
- * with rcu_register_thread_mb() before calling rcu_read_lock_mb().
- * rcu_unregister_thread_mb() should be called before the thread exits.
- */
-
-#ifdef _LGPL_SOURCE
-
-#include <urcu/static/urcu.h>
-
-/*
- * Mappings for static use of the userspace RCU library.
- * Should only be used in LGPL-compatible code.
- */
-
-/*
- * rcu_read_lock()
- * rcu_read_unlock()
- *
- * Mark the beginning and end of a read-side critical section.
- * DON'T FORGET TO USE RCU_REGISTER/UNREGISTER_THREAD() FOR EACH THREAD WITH
- * READ-SIDE CRITICAL SECTION.
- */
-#ifdef RCU_MEMBARRIER
-#define rcu_read_lock_memb             _rcu_read_lock
-#define rcu_read_unlock_memb           _rcu_read_unlock
-#define rcu_read_ongoing_memb          _rcu_read_ongoing
-#elif defined(RCU_SIGNAL)
-#define rcu_read_lock_sig              _rcu_read_lock
-#define rcu_read_unlock_sig            _rcu_read_unlock
-#define rcu_read_ongoing_sig           _rcu_read_ongoing
-#elif defined(RCU_MB)
-#define rcu_read_lock_mb               _rcu_read_lock
-#define rcu_read_unlock_mb             _rcu_read_unlock
-#define rcu_read_ongoing_mb            _rcu_read_ongoing
-#endif
-
-#else /* !_LGPL_SOURCE */
-
-/*
- * library wrappers to be used by non-LGPL compatible source code.
- * See LGPL-only urcu/static/urcu-pointer.h for documentation.
- */
-
-extern void rcu_read_lock(void);
-extern void rcu_read_unlock(void);
-extern int rcu_read_ongoing(void);
-
-#endif /* !_LGPL_SOURCE */
-
-extern void synchronize_rcu(void);
-
-/*
- * Reader thread registration.
- */
-extern void rcu_register_thread(void);
-extern void rcu_unregister_thread(void);
-
-/*
- * Explicit rcu initialization, for "early" use within library constructors.
- */
-extern void rcu_init(void);
-
-/*
- * Q.S. reporting are no-ops for these URCU flavors.
- */
-static inline void rcu_quiescent_state(void)
-{
-}
-
-static inline void rcu_thread_offline(void)
-{
-}
-
-static inline void rcu_thread_online(void)
-{
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#include <urcu-call-rcu.h>
-#include <urcu-defer.h>
-#include <urcu-flavor.h>
-
-#endif /* _URCU_H */
This page took 0.253978 seconds and 4 git commands to generate.