membarrier: add --enable-membarrier
Actually enable the global memory barriers if supported by the OS. Because only recent versions of Linux include the support, they are disabled by default. Note that it also has to be disabled for QEMU to run under Wine. Before this patch, rcutorture reports 85 ns/read for my machine, after the patch it reports 12.5 ns/read. On the other hand updates go from 50 *micro*seconds to 20 *milli*seconds. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
c8d3877e48
commit
a40161cbe9
42
configure
vendored
42
configure
vendored
@ -342,7 +342,7 @@ attr=""
|
|||||||
libattr=""
|
libattr=""
|
||||||
xfs=""
|
xfs=""
|
||||||
tcg="yes"
|
tcg="yes"
|
||||||
|
membarrier=""
|
||||||
vhost_net="no"
|
vhost_net="no"
|
||||||
vhost_crypto="no"
|
vhost_crypto="no"
|
||||||
vhost_scsi="no"
|
vhost_scsi="no"
|
||||||
@ -1161,6 +1161,10 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--enable-attr) attr="yes"
|
--enable-attr) attr="yes"
|
||||||
;;
|
;;
|
||||||
|
--disable-membarrier) membarrier="no"
|
||||||
|
;;
|
||||||
|
--enable-membarrier) membarrier="yes"
|
||||||
|
;;
|
||||||
--disable-blobs) blobs="no"
|
--disable-blobs) blobs="no"
|
||||||
;;
|
;;
|
||||||
--with-pkgversion=*) pkgversion="$optarg"
|
--with-pkgversion=*) pkgversion="$optarg"
|
||||||
@ -1577,6 +1581,7 @@ disabled with --disable-FEATURE, default is enabled if available:
|
|||||||
xen-pci-passthrough
|
xen-pci-passthrough
|
||||||
brlapi BrlAPI (Braile)
|
brlapi BrlAPI (Braile)
|
||||||
curl curl connectivity
|
curl curl connectivity
|
||||||
|
membarrier membarrier system call (for Linux 4.14+ or Windows)
|
||||||
fdt fdt device tree
|
fdt fdt device tree
|
||||||
bluez bluez stack connectivity
|
bluez bluez stack connectivity
|
||||||
kvm KVM acceleration support
|
kvm KVM acceleration support
|
||||||
@ -5137,6 +5142,37 @@ if compile_prog "" "" ; then
|
|||||||
have_fsxattr=yes
|
have_fsxattr=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
# check for usable membarrier system call
|
||||||
|
if test "$membarrier" = "yes"; then
|
||||||
|
have_membarrier=no
|
||||||
|
if test "$mingw32" = "yes" ; then
|
||||||
|
have_membarrier=yes
|
||||||
|
elif test "$linux" = "yes" ; then
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <linux/membarrier.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main(void) {
|
||||||
|
syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0);
|
||||||
|
syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "" "" ; then
|
||||||
|
have_membarrier=yes
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test "$have_membarrier" = "no"; then
|
||||||
|
feature_not_found "membarrier" "membarrier system call not available"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Do not enable it by default even for Mingw32, because it doesn't
|
||||||
|
# work on Wine.
|
||||||
|
membarrier=no
|
||||||
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# check if rtnetlink.h exists and is useful
|
# check if rtnetlink.h exists and is useful
|
||||||
have_rtnetlink=no
|
have_rtnetlink=no
|
||||||
@ -5763,6 +5799,7 @@ fi
|
|||||||
echo "malloc trim support $malloc_trim"
|
echo "malloc trim support $malloc_trim"
|
||||||
echo "RDMA support $rdma"
|
echo "RDMA support $rdma"
|
||||||
echo "fdt support $fdt"
|
echo "fdt support $fdt"
|
||||||
|
echo "membarrier $membarrier"
|
||||||
echo "preadv support $preadv"
|
echo "preadv support $preadv"
|
||||||
echo "fdatasync $fdatasync"
|
echo "fdatasync $fdatasync"
|
||||||
echo "madvise $madvise"
|
echo "madvise $madvise"
|
||||||
@ -6245,6 +6282,9 @@ fi
|
|||||||
if test "$fdt" = "yes" ; then
|
if test "$fdt" = "yes" ; then
|
||||||
echo "CONFIG_FDT=y" >> $config_host_mak
|
echo "CONFIG_FDT=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
if test "$membarrier" = "yes" ; then
|
||||||
|
echo "CONFIG_MEMBARRIER=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
if test "$signalfd" = "yes" ; then
|
if test "$signalfd" = "yes" ; then
|
||||||
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
|
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
@ -9,9 +9,19 @@
|
|||||||
#ifndef QEMU_SYS_MEMBARRIER_H
|
#ifndef QEMU_SYS_MEMBARRIER_H
|
||||||
#define QEMU_SYS_MEMBARRIER_H 1
|
#define QEMU_SYS_MEMBARRIER_H 1
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEMBARRIER
|
||||||
|
/* Only block reordering at the compiler level in the performance-critical
|
||||||
|
* side. The slow side forces processor-level ordering on all other cores
|
||||||
|
* through a system call.
|
||||||
|
*/
|
||||||
|
extern void smp_mb_global_init(void);
|
||||||
|
extern void smp_mb_global(void);
|
||||||
|
#define smp_mb_placeholder() barrier()
|
||||||
|
#else
|
||||||
/* Keep it simple, execute a real memory barrier on both sides. */
|
/* Keep it simple, execute a real memory barrier on both sides. */
|
||||||
static inline void smp_mb_global_init(void) {}
|
static inline void smp_mb_global_init(void) {}
|
||||||
#define smp_mb_global() smp_mb()
|
#define smp_mb_global() smp_mb()
|
||||||
#define smp_mb_placeholder() smp_mb()
|
#define smp_mb_placeholder() smp_mb()
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,6 +33,7 @@ util-obj-y += throttle.o
|
|||||||
util-obj-y += getauxval.o
|
util-obj-y += getauxval.o
|
||||||
util-obj-y += readline.o
|
util-obj-y += readline.o
|
||||||
util-obj-y += rcu.o
|
util-obj-y += rcu.o
|
||||||
|
util-obj-$(CONFIG_MEMBARRIER) += sys_membarrier.o
|
||||||
util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
|
util-obj-y += qemu-coroutine.o qemu-coroutine-lock.o qemu-coroutine-io.o
|
||||||
util-obj-y += qemu-coroutine-sleep.o
|
util-obj-y += qemu-coroutine-sleep.o
|
||||||
util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
util-obj-y += coroutine-$(CONFIG_COROUTINE_BACKEND).o
|
||||||
|
50
util/sys_membarrier.c
Normal file
50
util/sys_membarrier.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Process-global memory barriers
|
||||||
|
*
|
||||||
|
* Copyright (c) 2018 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qemu/osdep.h>
|
||||||
|
#include <qemu/sys_membarrier.h>
|
||||||
|
#include <qemu/error-report.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_LINUX
|
||||||
|
#include <linux/membarrier.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
static int
|
||||||
|
membarrier(int cmd, int flags)
|
||||||
|
{
|
||||||
|
return syscall(__NR_membarrier, cmd, flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void smp_mb_global(void)
|
||||||
|
{
|
||||||
|
#if defined CONFIG_WIN32
|
||||||
|
FlushProcessWriteBuffers();
|
||||||
|
#elif defined CONFIG_LINUX
|
||||||
|
membarrier(MEMBARRIER_CMD_SHARED, 0);
|
||||||
|
#else
|
||||||
|
#error --enable-membarrier is not supported on this operating system.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void smp_mb_global_init(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_LINUX
|
||||||
|
int ret = membarrier(MEMBARRIER_CMD_QUERY, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
error_report("This QEMU binary requires the membarrier system call.");
|
||||||
|
error_report("Please upgrade your system to a newer version of Linux");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!(ret & MEMBARRIER_CMD_SHARED)) {
|
||||||
|
error_report("This QEMU binary requires MEMBARRIER_CMD_SHARED support.");
|
||||||
|
error_report("Please upgrade your system to a newer version of Linux");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user