diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-02-25 13:31:16 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-02-25 13:31:16 +0000 |
commit | db736e0437aa6fd7c1b7e4599c17f9619ab6b837 (patch) | |
tree | d34751ef2c77e5fbc83c19e814c4413b0fa2618a /util/oslib-posix.c | |
parent | 9a8abceb5f01d1066d3a1ac5a33aabcbaeec1860 (diff) | |
parent | 9e264985ff0bc86927b44b334bd504687f78659d (diff) |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* device_del fix (Julia)
* FXAM fix (myself)
* memdev refactoring (Igor)
* memory region API cleanups (Peter, Philippe)
* ioeventfd optimization (Stefan)
* new WHPX maintainer (Sunil)
* Large guest startup optimizations (Chen)
# gpg: Signature made Tue 25 Feb 2020 12:42:24 GMT
# gpg: using RSA key BFFBD25F78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full]
# gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full]
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1
# Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83
* remotes/bonzini/tags/for-upstream: (104 commits)
WHPX: Assigning maintainer for Windows Hypervisor Platform
accel/kvm: Check ioctl(KVM_SET_USER_MEMORY_REGION) return value
target/i386: check for empty register in FXAM
qdev-monitor: Forbid repeated device_del
mem-prealloc: optimize large guest startup
memory: batch allocate ioeventfds[] in address_space_update_ioeventfds()
Avoid cpu_physical_memory_rw() with a constant is_write argument
Let cpu_[physical]_memory() calls pass a boolean 'is_write' argument
exec: Let cpu_[physical]_memory API use a boolean 'is_write' argument
Avoid address_space_rw() with a constant is_write argument
Let address_space_rw() calls pass a boolean 'is_write' argument
exec: Let address_space_unmap() use a boolean 'is_write' argument
hw/virtio: Let vhost_memory_map() use a boolean 'is_write' argument
hw/virtio: Let virtqueue_map_iovec() use a boolean 'is_write' argument
hw/ide: Let the DMAIntFunc prototype use a boolean 'is_write' argument
hw/ide/internal: Remove unused DMARestartFunc typedef
Remove unnecessary cast when using the cpu_[physical]_memory API
exec: Let the cpu_[physical]_memory API use void pointer arguments
Remove unnecessary cast when using the address_space API
hw/net: Avoid casting non-const pointer, use address_space_write()
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util/oslib-posix.c')
-rw-r--r-- | util/oslib-posix.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 5a291cc982..897e8f3ba6 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -76,6 +76,10 @@ static MemsetThread *memset_thread; static int memset_num_threads; static bool memset_thread_failed; +static QemuMutex page_mutex; +static QemuCond page_cond; +static bool threads_created_flag; + int qemu_get_thread_id(void) { #if defined(__linux__) @@ -403,6 +407,17 @@ static void *do_touch_pages(void *arg) MemsetThread *memset_args = (MemsetThread *)arg; sigset_t set, oldset; + /* + * On Linux, the page faults from the loop below can cause mmap_sem + * contention with allocation of the thread stacks. Do not start + * clearing until all threads have been created. + */ + qemu_mutex_lock(&page_mutex); + while(!threads_created_flag){ + qemu_cond_wait(&page_cond, &page_mutex); + } + qemu_mutex_unlock(&page_mutex); + /* unblock SIGBUS */ sigemptyset(&set); sigaddset(&set, SIGBUS); @@ -451,27 +466,28 @@ static inline int get_memset_num_threads(int smp_cpus) static bool touch_all_pages(char *area, size_t hpagesize, size_t numpages, int smp_cpus) { - size_t numpages_per_thread; - size_t size_per_thread; + size_t numpages_per_thread, leftover; char *addr = area; int i = 0; memset_thread_failed = false; + threads_created_flag = false; memset_num_threads = get_memset_num_threads(smp_cpus); memset_thread = g_new0(MemsetThread, memset_num_threads); - numpages_per_thread = (numpages / memset_num_threads); - size_per_thread = (hpagesize * numpages_per_thread); + numpages_per_thread = numpages / memset_num_threads; + leftover = numpages % memset_num_threads; for (i = 0; i < memset_num_threads; i++) { memset_thread[i].addr = addr; - memset_thread[i].numpages = (i == (memset_num_threads - 1)) ? - numpages : numpages_per_thread; + memset_thread[i].numpages = numpages_per_thread + (i < leftover); memset_thread[i].hpagesize = hpagesize; qemu_thread_create(&memset_thread[i].pgthread, "touch_pages", do_touch_pages, &memset_thread[i], QEMU_THREAD_JOINABLE); - addr += size_per_thread; - numpages -= numpages_per_thread; + addr += memset_thread[i].numpages * hpagesize; } + threads_created_flag = true; + qemu_cond_broadcast(&page_cond); + for (i = 0; i < memset_num_threads; i++) { qemu_thread_join(&memset_thread[i].pgthread); } |