From a960d6642d39f7d255b7b2b8bda3c2ae4e4e649b Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 17 Dec 2021 14:46:09 +0100 Subject: [PATCH] util/oslib-posix: Support concurrent os_mem_prealloc() invocation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Add a mutex to protect the SIGBUS case, as we cannot mess concurrently with the sigbus handler and we have to manage the global variable sigbus_memset_context. The MADV_POPULATE_WRITE path can run concurrently. Note that page_mutex and page_cond are shared between concurrent invocations, which shouldn't be a problem. This is a preparation for future virtio-mem prealloc code, which will call os_mem_prealloc() asynchronously from an iothread when handling guest requests. Reviewed-by: Pankaj Gupta Reviewed-by: Daniel P. Berrangé Reviewed-by: Michal Privoznik Signed-off-by: David Hildenbrand Message-Id: <20211217134611.31172-7-david@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- util/oslib-posix.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/util/oslib-posix.c b/util/oslib-posix.c index efa4f96d56..9829149e4b 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -95,6 +95,7 @@ typedef struct MemsetThread MemsetThread; /* used by sigbus_handler() */ static MemsetContext *sigbus_memset_context; +static QemuMutex sigbus_mutex; static QemuMutex page_mutex; static QemuCond page_cond; @@ -625,6 +626,7 @@ static bool madv_populate_write_possible(char *area, size_t pagesize) void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, Error **errp) { + static gsize initialized; int ret; struct sigaction act, oldact; size_t hpagesize = qemu_fd_getpagesize(fd); @@ -638,6 +640,12 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, use_madv_populate_write = madv_populate_write_possible(area, hpagesize); if (!use_madv_populate_write) { + if (g_once_init_enter(&initialized)) { + qemu_mutex_init(&sigbus_mutex); + g_once_init_leave(&initialized, 1); + } + + qemu_mutex_lock(&sigbus_mutex); memset(&act, 0, sizeof(act)); act.sa_handler = &sigbus_handler; act.sa_flags = 0; @@ -665,6 +673,7 @@ void os_mem_prealloc(int fd, char *area, size_t memory, int smp_cpus, perror("os_mem_prealloc: failed to reinstall signal handler"); exit(1); } + qemu_mutex_unlock(&sigbus_mutex); } } -- 2.11.4.GIT