From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:43409) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1edzs1-00075R-4U for qemu-devel@nongnu.org; Tue, 23 Jan 2018 09:48:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1edzrw-0002Jr-VL for qemu-devel@nongnu.org; Tue, 23 Jan 2018 09:48:17 -0500 Received: from mout.kundenserver.de ([217.72.192.73]:53116) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1edzrw-0002IY-LT for qemu-devel@nongnu.org; Tue, 23 Jan 2018 09:48:12 -0500 From: Laurent Vivier Date: Tue, 23 Jan 2018 15:47:56 +0100 Message-Id: <20180123144807.5618-3-laurent@vivier.eu> In-Reply-To: <20180123144807.5618-1-laurent@vivier.eu> References: <20180123144807.5618-1-laurent@vivier.eu> Subject: [Qemu-devel] [PULL 02/13] linux-user: wrap fork() in a start/end exclusive section List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Laurent Vivier From: Peter Maydell When we do a fork() in usermode emulation, we need to be in a start/end exclusive section, so that we can ensure that no other thread is in an RCU section. Otherwise you can get this deadlock: - fork thread: has mmap_lock, waits for rcu_sync_lock (because rcu_init_lock() is registered as a pthread_atfork() hook) - RCU thread: has rcu_sync_lock, waits for rcu_read_(un)lock - another CPU thread: in RCU critical section, waits for mmap_lock This can show up if you have a heavily multithreaded guest program that does a fork(). Signed-off-by: Peter Maydell Reported-by: Stuart Monteith Message-Id: <1512650481-1723-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index e8406917e3..2140465709 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -127,6 +127,7 @@ int cpu_get_pic_interrupt(CPUX86State *env) /* Make sure everything is in a consistent state for calling fork(). */ void fork_start(void) { + start_exclusive(); mmap_fork_start(); qemu_mutex_lock(&tb_ctx.tb_lock); cpu_list_lock(); @@ -147,9 +148,13 @@ void fork_end(int child) qemu_mutex_init(&tb_ctx.tb_lock); qemu_init_cpu_list(); gdbserver_fork(thread_cpu); + /* qemu_init_cpu_list() takes care of reinitializing the + * exclusive state, so we don't need to end_exclusive() here. + */ } else { qemu_mutex_unlock(&tb_ctx.tb_lock); cpu_list_unlock(); + end_exclusive(); } } -- 2.14.3