From patchwork Mon Nov 21 02:05:07 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Graf X-Patchwork-Id: 126678 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 23CE0B71EA for ; Mon, 21 Nov 2011 13:05:19 +1100 (EST) Received: from localhost ([::1]:33547 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RSJG0-0002vR-FR for incoming@patchwork.ozlabs.org; Sun, 20 Nov 2011 21:05:16 -0500 Received: from eggs.gnu.org ([140.186.70.92]:55027) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RSJFv-0002vL-JU for qemu-devel@nongnu.org; Sun, 20 Nov 2011 21:05:12 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RSJFu-0001XE-Dt for qemu-devel@nongnu.org; Sun, 20 Nov 2011 21:05:11 -0500 Received: from cantor2.suse.de ([195.135.220.15]:46403 helo=mx2.suse.de) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RSJFu-0001X8-4f for qemu-devel@nongnu.org; Sun, 20 Nov 2011 21:05:10 -0500 Received: from relay2.suse.de (nat.nue.novell.com [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id 222A28EE65; Mon, 21 Nov 2011 03:05:09 +0100 (CET) From: Alexander Graf Date: Mon, 21 Nov 2011 03:05:07 +0100 Message-Id: To: qemu-devel Developers Mime-Version: 1.0 (Apple Message framework v1084) X-Mailer: Apple Mail (2.1084) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 X-Received-From: 195.135.220.15 Cc: Peter Maydell , Riku Voipio Subject: [Qemu-devel] linux-user crashing in multi-threaded programs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Howdy, In an adventure to find out why yast2-core fails in its testsuite during build on ARM for us, I dove into the code for a bit and debugged it down to our old friend: multi-threaded TB invalidation. I have a nice test case at http://csgraf.de/tmp/yast2-core.tbz2 which you can easily use to reproduce the race. I run it using the following command line: qemu-arm -L yast2-core yast2-core/bin/test_thread_log.prg It breaks pretty much every single time. Apparently two threads try to modify jmp_next at the same time, rendering the whole invalidation racy. The following patch triggers while in normal single-threaded worlds it should never appear: I would advice against using it as a real fix though, as it effectively disables TB chaining, rendering all of QEMU pretty slow. Does anyone have pending patches, approaches or ideas on how to fix this? It seems to be the last big road block towards getting linux-user actually workable for us. Alex diff --git a/exec.c b/exec.c index 6b92198..0c48222 100644 --- a/exec.c +++ b/exec.c @@ -1356,6 +1356,7 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n) tb1 = (TranslationBlock *)((long)tb1 & ~3); if (n1 == 2) break; + assert(tb1); tb1 = tb1->jmp_next[n1]; } /* we are now sure now that tb jumps to tb1 */ So how do I know it's a race in the chaining code? Well, it only happens with threaded code. And it only happens when actually chaining. The following patch makes the test case work: diff --git a/exec-all.h b/exec-all.h index c211242..c8124e9 100644 --- a/exec-all.h +++ b/exec-all.h @@ -259,6 +259,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb, static inline void tb_add_jump(TranslationBlock *tb, int n, TranslationBlock *tb_next) { + if(1) return; /* NOTE: this test is only needed for thread safety */ if (!tb->jmp_next[n]) { /* patch the native jump address */