@@ -335,6 +335,7 @@ libssh2=""
vhdx=""
quorum=""
numa=""
+liburcu=""
# parse CC options first
for opt do
@@ -1129,6 +1130,10 @@ for opt do
;;
--enable-numa) numa="yes"
;;
+ --disable-liburcu) liburcu="no"
+ ;;
+ --enable-liburcu) liburcu="yes"
+ ;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -1400,6 +1405,8 @@ Advanced options (experts only):
--enable-quorum enable quorum block filter support
--disable-numa disable libnuma support
--enable-numa enable libnuma support
+ --disable-liburcu disable liburcu, use QEMU RCU instead
+ --enable-liburcu enable liburcu, the user-space RCU library
NOTE: The object files are built at the place where configure is launched
EOF
@@ -3277,6 +3284,29 @@ EOF
fi
##########################################
+# liburcu probe
+
+if test "$liburcu" != "no" ; then
+ cat > $TMPC << EOF
+char synchronize_rcu_mb();
+int main()
+{
+ return synchronize_rcu_mb ();
+}
+EOF
+
+ if compile_prog "" "-lurcu-mb" ; then
+ liburcu=yes
+ libs_softmmu="-lurcu-mb $libs_softmmu"
+ else
+ if test "$liburcu" = "yes" ; then
+ feature_not_found "liburcu" "install liburcu > v0.6, or --disable-liburcu"
+ fi
+ liburcu=no
+ fi
+fi
+
+##########################################
# signalfd probe
signalfd="no"
cat > $TMPC << EOF
@@ -4370,6 +4400,7 @@ echo "Quorum $quorum"
echo "lzo support $lzo"
echo "snappy support $snappy"
echo "NUMA host support $numa"
+echo "liburcu support $liburcu"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -5368,6 +5399,10 @@ if test "$numa" = "yes"; then
echo "CONFIG_NUMA=y" >> $config_host_mak
fi
+if test "$liburcu" = "yes"; then
+ echo "CONFIG_LIBURCU=y" >> $config_host_mak
+fi
+
# build tree in object directory in case the source is not in the current directory
DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos tests/qapi-schema tests/tcg/xtensa tests/qemu-iotests"
DIRS="$DIRS fsdev"
@@ -129,6 +129,8 @@
#define atomic_set(ptr, i) ((*(__typeof__(*ptr) volatile*) (ptr)) = (i))
#endif
+#ifndef CONFIG_LIBURCU
+
/**
* rcu_dereference - reads a RCU-protected pointer to a local variable
* into a RCU read-side critical section. The pointer can later be safely
@@ -191,6 +193,8 @@
#endif
#endif
+#endif /* !CONFIG_LIBURCU */
+
/* These have the same semantics as Java volatile variables.
* See http://gee.cs.oswego.edu/dl/jmm/cookbook.html:
* "1. Issue a StoreStore barrier (wmb) before each volatile store."
@@ -40,6 +40,29 @@
extern "C" {
#endif
+struct rcu_head;
+typedef void RCUCBFunc(struct rcu_head *head);
+
+/* The operands of the minus operator must have the same type,
+ * which must be the one that we specify in the cast.
+ */
+#define call_rcu_first_elem(head, func, field) \
+ call_rcu(({ \
+ char __attribute__((unused)) \
+ offset_must_be_zero[-offsetof(typeof(*(head)), field)], \
+ func_type_invalid = (func) - (void (*)(typeof(head)))(func); \
+ &(head)->field; \
+ }), \
+ (RCUCBFunc *)(func))
+
+#ifdef CONFIG_LIBURCU
+
+#define _LGPL_SOURCE
+#define RCU_MB
+#include <urcu.h>
+
+#else
+
/*
* Important !
*
@@ -118,9 +141,6 @@ extern void synchronize_rcu(void);
extern void rcu_register_thread(void);
extern void rcu_unregister_thread(void);
-struct rcu_head;
-typedef void RCUCBFunc(struct rcu_head *head);
-
struct rcu_head {
struct rcu_head *next;
RCUCBFunc *func;
@@ -128,17 +148,7 @@ struct rcu_head {
extern void call_rcu(struct rcu_head *head, RCUCBFunc *func);
-/* The operands of the minus operator must have the same type,
- * which must be the one that we specify in the cast.
- */
-#define call_rcu_first_elem(head, func, field) \
- call_rcu(({ \
- char __attribute__((unused)) \
- offset_must_be_zero[-offsetof(typeof(*(head)), field)], \
- func_type_invalid = (func) - (void (*)(typeof(head)))(func); \
- &(head)->field; \
- }), \
- (RCUCBFunc *)(func))
+#endif /* CONFIG_LIBURCU */
#ifdef __cplusplus
}
@@ -17,4 +17,4 @@ util-obj-y += throttle.o
util-obj-y += getauxval.o
util-obj-y += readline.o
util-obj-y += rfifolock.o
-util-obj-y += rcu.o
+util-obj-$(call lnot,$(CONFIG_LIBURCU)) += rcu.o
The default is --disable-liburcu, which means QEMU's RCU implementation is used. When building with --enable-liburcu, the memory barrier version of liburcu (urcu-mb) is linked against. We might want to make this configurable in the future for greater performance; for now we just match the liburcu flavor to the one that QEMU's RCU is using. Note that the rcutorture under test/ doesn't work with --enable-liburcu, since it relies on some internals of QEMU's RCU. liburcu is tested with the urcutorture distributed with it. Signed-off-by: Emilio G. Cota <cota@braap.org> --- configure | 35 +++++++++++++++++++++++++++++++++++ include/qemu/atomic.h | 4 ++++ include/qemu/rcu.h | 38 ++++++++++++++++++++++++-------------- util/Makefile.objs | 2 +- 4 files changed, 64 insertions(+), 15 deletions(-)