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 <c...@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(-) diff --git a/configure b/configure index f185dd0..71c9802 100755 --- a/configure +++ b/configure @@ -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" diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 4795e28..d7ad0d5 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -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." diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h index 492d943..0aeb8f0 100644 --- a/include/qemu/rcu.h +++ b/include/qemu/rcu.h @@ -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 } diff --git a/util/Makefile.objs b/util/Makefile.objs index ceaba30..eacc4c4 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -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 -- 1.8.3