From patchwork Tue Feb 27 09:52:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 129755 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp1207773lja; Tue, 27 Feb 2018 02:05:30 -0800 (PST) X-Google-Smtp-Source: AG47ELsh82O0bhuLN5A68rEsmyP1J1CkUU5eO9/hwQu6/RFd9j45UR0MoxiCYlb0g6cQHHa38EvI X-Received: by 10.129.103.5 with SMTP id b5mr8735731ywc.11.1519725930374; Tue, 27 Feb 2018 02:05:30 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519725930; cv=none; d=google.com; s=arc-20160816; b=eBOD8AsOcOZZ3h0eM1O3zVP3hbuae2bU93WVeRtLvJHmAUY0hbuNs59XUdHGpSlxsQ ++9CTyNtRGWYrUfajzFtVmiISd9ch+LpoPLazQuyXQ/+WzJeoZ5GGJzRkZXr9hMLLavW ZeJueXnqiuHu04QjsCxTzxZmLnuO7I5r29UutWyvjfhQCnKf/LQ8ii4wGdwKNVa7I0bw 8S3nT7VEYddzO0VMtY8u0V5oRqgabwFRLWqHvqWqB9sCaqCWFJPZrQvUwHUOREWMCJ9a /QeNbDVPnJLSon+HE3ERKye93kxd5uL/BJPCyGQDi3daW33Qyku4M1GaK/+Iey/jc4lK y7XQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:user-agent:references :in-reply-to:message-id:date:to:from:arc-authentication-results; bh=7H0EjZx30hV9HIT9eOfk8BMNKWiX4fUWLM/DUcK98K8=; b=dB1t7bkIIrxpMHfLhNqkT/31tISQzlzig7VkeeXoXHPt1E+DXWBbmWI71hyZECdOEo hY2KNliqoxmtm7a9YqRWsTGaqHj7A4w6rA2hglR9xUC9p84hbwS/Tmby+g1gXzjcWLig q5wsJkBrx6XDHFZx226j/RqYfNbnxi5WSGnMY/YawNpRp/bZJ6TPUAJFNlU8lHQDK3Ya FfLy7ZlO9qaSQJL1L0ryCHmmna+wiBGo/CAy+y1JC+y0Kv0/8cjUr0R/QFTtuF7IVs54 mD6o8FlAVJ5Pc+4R0KgH0RZXBv6WD9ug7R0eCNhRBsmAMa6hitPX4xGM85M4wcTw2t66 3F/g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id z7-v6si1817659ybj.768.2018.02.27.02.05.30 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 27 Feb 2018 02:05:30 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:35880 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqc8X-0003Uu-OT for patch@linaro.org; Tue, 27 Feb 2018 05:05:29 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39646) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbw2-000196-AX for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:39 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqbvz-0004nX-HQ for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:34 -0500 Received: from mail.ispras.ru ([83.149.199.45]:57402) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbvz-0004nS-92 for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:31 -0500 Received: from [127.0.1.1] (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id 4DA9B54006A; Tue, 27 Feb 2018 12:52:30 +0300 (MSK) From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 12:52:31 +0300 Message-ID: <20180227095231.1060.91180.stgit@pasha-VirtualBox> In-Reply-To: <20180227095135.1060.36549.stgit@pasha-VirtualBox> References: <20180227095135.1060.36549.stgit@pasha-VirtualBox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH v7 10/22] replay/replay.c: bump REPLAY_VERSION again X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com, pavel.dovgaluk@ispras.ru, quintela@redhat.com, ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com, zuban32s@gmail.com, maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru, kraxel@redhat.com, boost.lists@gmail.com, thomas.dullien@googlemail.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This time commit 802f045a5f61b781df55e4492d896b4d20503ba7 broke the replay file format. Also add a comment about this to replay-internal.h. Signed-off-by: Alex Bennée Reviewed-off-by: Pavel Dovgalyuk Acked-by: Paolo Bonzini --- replay/replay-internal.h | 2 +- replay/replay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/replay/replay-internal.h b/replay/replay-internal.h index be96d7e..8e4c701 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -12,7 +12,7 @@ * */ - +/* Any changes to order/number of events will need to bump REPLAY_VERSION */ enum ReplayEvents { /* for instruction event */ EVENT_INSTRUCTION, diff --git a/replay/replay.c b/replay/replay.c index 7a23c62..9cddb6b 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -22,7 +22,7 @@ /* Current version of the replay mechanism. Increase it when file format changes. */ -#define REPLAY_VERSION 0xe02006 +#define REPLAY_VERSION 0xe02007 /* Size of replay log header */ #define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t)) From patchwork Tue Feb 27 09:52:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 129752 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp1198003lja; Tue, 27 Feb 2018 01:54:46 -0800 (PST) X-Google-Smtp-Source: AG47ELs/rxgR40FYOyotbjspgV3jzhw+K9p7CBt95/Yzu9jNYdCXt0QXY+KDPMp8G3OMRoe2bsKw X-Received: by 2002:a25:dcc5:: with SMTP id y188-v6mr8876588ybe.385.1519725286492; Tue, 27 Feb 2018 01:54:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519725286; cv=none; d=google.com; s=arc-20160816; b=s13POkWa1xKydeNsR1nZAUjDrZTtWmzOGEpGCqLkVafntm9K64wgaY5xRWGh+W6WSr 6Ix/DwK4ZECffwqkauBuofQESTmSOzIoI7OSvbkF3BNHqS5QJex4cfIebVlN9vzSKCtM Cz6+AXYnsabsP8XH3LsvBhfZoEKnYgqBQtF91BcmYIRc9aecqR+DCCVgOSrgM0Z58DyD K7f07bLhT64XxI6saN/0PS63lMJvjDIGewuktolaRA/GI2+nbYv2DEZCyJsSVZQ02t5K vsCVSHhvBpt9rRXcOCNy2AwNGO1SvUaC6NSICZa2090k4nZqw+xAKukBYVq4vadO0sNe 0gNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:user-agent:references :in-reply-to:message-id:date:to:from:arc-authentication-results; bh=NxMPn59v/BPXue/8zD6loH8ClpLPxi3WzX9vp/j/45w=; b=ZY9byAibtJXKgqu4GZRGemlhLkYK+zvF6JTR/ckuA4rX1XfrS73CIwWDGWlQLGFuDm 6RaqaAE9EVE5A1UfDqfXTBzML8Cu5nMuFHZ1ZyPIZk9MVAONHUEDJjheg9atgdGM/j6e VXYqEAujWU4gtsn6Xz1Q2BxP++mxVyYha0D9gkToqfLN1tfsOHG8KkmCQS+q+PJZACpn +g/h0BauGzo1/c+DSOhJfZQZdwhrOH2JYRzpxOCQ5izvzfjp7ryxEnjjVNiMkEobrR0N I+otQwY8e2Jwzcr0l9s/uVZCBRBuWE5NeNo85REwtmLNYyZ7JNbk2pA/L38ouHgU+j7R c2ig== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id d4-v6si1861008ybo.281.2018.02.27.01.54.46 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 27 Feb 2018 01:54:46 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:35817 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqby9-0002sU-Sg for patch@linaro.org; Tue, 27 Feb 2018 04:54:45 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39659) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbw6-0001Cy-12 for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqbw5-0004tS-4M for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:38 -0500 Received: from mail.ispras.ru ([83.149.199.45]:57432) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbw4-0004tB-Sd for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:37 -0500 Received: from [127.0.1.1] (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id DC27754006B; Tue, 27 Feb 2018 12:52:35 +0300 (MSK) From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 12:52:37 +0300 Message-ID: <20180227095237.1060.44661.stgit@pasha-VirtualBox> In-Reply-To: <20180227095135.1060.36549.stgit@pasha-VirtualBox> References: <20180227095135.1060.36549.stgit@pasha-VirtualBox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH v7 11/22] replay/replay-internal.c: track holding of replay_lock X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com, pavel.dovgaluk@ispras.ru, quintela@redhat.com, ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com, zuban32s@gmail.com, maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru, kraxel@redhat.com, boost.lists@gmail.com, thomas.dullien@googlemail.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This is modelled after the iothread mutex lock. We keep a TLS flag to indicate when that thread has acquired the lock and assert we don't double-lock or release when we shouldn't have. Signed-off-by: Alex Bennée Tested-by: Pavel Dovgalyuk --- replay/replay-internal.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/replay/replay-internal.c b/replay/replay-internal.c index fca8514..0d7e1d6 100644 --- a/replay/replay-internal.c +++ b/replay/replay-internal.c @@ -169,6 +169,8 @@ void replay_finish_event(void) replay_fetch_data_kind(); } +static __thread bool replay_locked; + void replay_mutex_init(void) { qemu_mutex_init(&lock); @@ -179,13 +181,22 @@ void replay_mutex_destroy(void) qemu_mutex_destroy(&lock); } +static bool replay_mutex_locked(void) +{ + return replay_locked; +} + void replay_mutex_lock(void) { + g_assert(!replay_mutex_locked()); qemu_mutex_lock(&lock); + replay_locked = true; } void replay_mutex_unlock(void) { + g_assert(replay_mutex_locked()); + replay_locked = false; qemu_mutex_unlock(&lock); } From patchwork Tue Feb 27 09:52:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 129756 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp1208207lja; Tue, 27 Feb 2018 02:05:59 -0800 (PST) X-Google-Smtp-Source: AH8x224hOqrWKfMAiC5AcgoS6hqXMHvXG4FEuZwZTG6590RZKzu7cvvnlx0WG0ab8x4kx6cHhTWS X-Received: by 10.129.156.204 with SMTP id t195mr8647704ywg.48.1519725959214; Tue, 27 Feb 2018 02:05:59 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519725959; cv=none; d=google.com; s=arc-20160816; b=M29Z7KpGwTiMDax1Iq+fkHcp8MNRCEbvP76x16EgSAi+HqiVpmLEBHqU1RIKyJXFa/ hIdFO+2Scy0lIgPCIe4fsnD4e7NjDSJOnks6L3yhqZZH4/iBmdq9bYzkxTjGQLUps+kO iGTsHAQRV6UqYTNdCuOSsGYfbxOe705cVAiB0P8NQSpJtKQaYoBO64nR7JVdFIYkMJWp AYyBWcD2juR/pp83U8b6CNNo05Z50Vwq+B9cKa6o9gMRc5qEtxu561TyqXHQ6Q26Oa8x FL1O0eqOYE7afoI5NbY09yZwvBt0ZVPNQAeempQN//LmqLJsV7j7zO7Ru7kKb5T3eXWW dOmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:user-agent:references :in-reply-to:message-id:date:to:from:arc-authentication-results; bh=LfC7D1Wv+O+LGW60lnjmA/sCspRq2IU8r9aj1pRwAuI=; b=o+gZv0bkeGFk4QlKDs8UeS1MTPy3luUe5PT2qgc/7a6TIGMLbF6kC4FZY/eFX/L/VD iSoiZpELHuuimPG/ALE6pKWM1iZh7QmxDTJinWJLwOH+6DU5GkL0CYkMWXbUmANXCZs1 nLK2sE0QbM7xWDxMe3ASb2Nwi1zoQ3wdMOQ12dsGuXhDUVmXlukAI0tHYukXqZLO0Kl3 8E28kP0Gj+hB2FlrHrovczabOxyPJEjR4FfkMY7ORXPVIPUdA22DyFK1NOfSXdnzWKvA WrXZ+KWmGM3ORG0KNAaK0qbtxUxZwpOuHak7lWIiZj/rUMlvhk+uAyrCFlMc5NS6E9r+ fEEQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id f9-v6si37288ybm.460.2018.02.27.02.05.58 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 27 Feb 2018 02:05:59 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:35891 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqc90-0004V4-7g for patch@linaro.org; Tue, 27 Feb 2018 05:05:58 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39688) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwE-0001LU-QV for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:51 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqbwA-00052G-T5 for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:46 -0500 Received: from mail.ispras.ru ([83.149.199.45]:57444) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwA-00051w-Fx for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:42 -0500 Received: from [127.0.1.1] (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id 7ECD954006A; Tue, 27 Feb 2018 12:52:41 +0300 (MSK) From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 12:52:42 +0300 Message-ID: <20180227095242.1060.16601.stgit@pasha-VirtualBox> In-Reply-To: <20180227095135.1060.36549.stgit@pasha-VirtualBox> References: <20180227095135.1060.36549.stgit@pasha-VirtualBox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH v7 12/22] replay: make locking visible outside replay code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com, pavel.dovgaluk@ispras.ru, quintela@redhat.com, ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com, zuban32s@gmail.com, maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru, kraxel@redhat.com, boost.lists@gmail.com, thomas.dullien@googlemail.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée The replay_mutex_lock/unlock/locked functions are now going to be used for ensuring lock-step behaviour between the two threads. Make them public API functions and also provide stubs for non-QEMU builds on common paths. Signed-off-by: Alex Bennée Signed-off-by: Pavel Dovgalyuk -- v7: - removed abort() from stubs to allow calling from utils - removed exported replay_mutex_locked() --- include/sysemu/replay.h | 13 +++++++++++++ replay/replay-internal.c | 2 +- replay/replay-internal.h | 6 +++--- stubs/replay.c | 8 ++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 5462555..291bcbc 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -46,6 +46,19 @@ extern ReplayMode replay_mode; /* Name of the initial VM snapshot */ extern char *replay_snapshot; +/* Replay locking + * + * The locks are needed to protect the shared structures and log file + * when doing record/replay. They also are the main sync-point between + * the main-loop thread and the vCPU thread. This was a role + * previously filled by the BQL which has been busy trying to reduce + * its impact across the code. This ensures blocks of events stay + * sequential and reproducible. + */ + +void replay_mutex_lock(void); +void replay_mutex_unlock(void); + /* Replay process control functions */ /*! Enables recording or saving event log with specified parameters */ diff --git a/replay/replay-internal.c b/replay/replay-internal.c index 0d7e1d6..7cdefea 100644 --- a/replay/replay-internal.c +++ b/replay/replay-internal.c @@ -181,7 +181,7 @@ void replay_mutex_destroy(void) qemu_mutex_destroy(&lock); } -static bool replay_mutex_locked(void) +bool replay_mutex_locked(void) { return replay_locked; } diff --git a/replay/replay-internal.h b/replay/replay-internal.h index 8e4c701..41eee66 100644 --- a/replay/replay-internal.h +++ b/replay/replay-internal.h @@ -100,12 +100,12 @@ int64_t replay_get_qword(void); void replay_get_array(uint8_t *buf, size_t *size); void replay_get_array_alloc(uint8_t **buf, size_t *size); -/* Mutex functions for protecting replay log file */ +/* Mutex functions for protecting replay log file and ensuring + * synchronisation between vCPU and main-loop threads. */ void replay_mutex_init(void); void replay_mutex_destroy(void); -void replay_mutex_lock(void); -void replay_mutex_unlock(void); +bool replay_mutex_locked(void); /*! Checks error status of the file. */ void replay_check_error(void); diff --git a/stubs/replay.c b/stubs/replay.c index 9991ee5..18ba0bb 100644 --- a/stubs/replay.c +++ b/stubs/replay.c @@ -73,3 +73,11 @@ uint64_t blkreplay_next_id(void) { return 0; } + +void replay_mutex_lock(void) +{ +} + +void replay_mutex_unlock(void) +{ +} From patchwork Tue Feb 27 09:52:48 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 129754 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp1202548lja; Tue, 27 Feb 2018 02:00:28 -0800 (PST) X-Google-Smtp-Source: AH8x227YAOmwtdVkAqz+uWq71oq055Jq0UzjhKpqVPD1fbShXM4WxFhqgMxeowSTxfwI5lKTPnXZ X-Received: by 10.129.124.138 with SMTP id x132mr8964041ywc.426.1519725627874; Tue, 27 Feb 2018 02:00:27 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519725627; cv=none; d=google.com; s=arc-20160816; b=YI3AJW9jEPnFsoBJWe+sOF8fERndNK49GDIXE+PxGNAQY73u2Uo7m2o+bBUoOaDoYa Bh/F98gEsMMd/Bt7G/QflWoVZi7DZIOOlaE4HsBnUO1a0bwL0jDf/UM6yyaUjRP+PSDf 6EcpRMB+vRfAUL8ZFAan16rNlXdgJTMnvr/zZtyCvpHYThIDcavowsJ4l//XHKgUf4RN Rh8uWh7P9USyE6mJjtHoVTS0ynlLSlopWup2XLtVGzTkXdFCPMBGZjf66bvzr2ynC//K nE6giToH3I0v+ERCE1xkAfBpvymYBt1qAxyexiaki+0R+B9jiIUOZeKuXIgm/ZvROMK1 +Hiw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:user-agent:references :in-reply-to:message-id:date:to:from:arc-authentication-results; bh=7dBVQCmbsgZDLzEdy1r+Owy1U9rXUeXZYSpOMXrqUCM=; b=KAB6kPVjSoK1tMLM1p+k9aRsNpF+ETkf3L87oXLmKJfwPY643eDaFMBgkZmKE27jWi /5S2qd6buUOGROTOOJ9kqaLpEiaMi6HrUpT9g5DgPky5QAtcFsoz/jtcis1vLcSBIg19 5jxpwgMHpKE7G6KxtiYC5WW+QyPVYrD6WqVd1J7oRzm3VW6g5w7A/IlWs9SFbJXOO+XO og+3cO9cjI8RzSlZ+gTC/A7ZSGS/gYCpg/GvoLi9dsYW5SPPpbBl0o3lXARHkWVPlvQD 130YRYIlxgBHNLBMbt5WxbGITa2zNo737+1Cn31SOH+vODyzTDmmJIrJBiXJhCmRQtXW TdqA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id m131-v6si1873672ybc.328.2018.02.27.02.00.27 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 27 Feb 2018 02:00:27 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:35850 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqc3f-0008JR-5C for patch@linaro.org; Tue, 27 Feb 2018 05:00:27 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39707) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwI-0001MS-Ts for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqbwG-00056m-Ko for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:50 -0500 Received: from mail.ispras.ru ([83.149.199.45]:57460) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwG-00056H-2z for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:52:48 -0500 Received: from [127.0.1.1] (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id 1B72D54006A; Tue, 27 Feb 2018 12:52:47 +0300 (MSK) From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 12:52:48 +0300 Message-ID: <20180227095248.1060.40374.stgit@pasha-VirtualBox> In-Reply-To: <20180227095135.1060.36549.stgit@pasha-VirtualBox> References: <20180227095135.1060.36549.stgit@pasha-VirtualBox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH v7 13/22] replay: push replay_mutex_lock up the call tree X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com, pavel.dovgaluk@ispras.ru, quintela@redhat.com, ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com, zuban32s@gmail.com, maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru, kraxel@redhat.com, boost.lists@gmail.com, thomas.dullien@googlemail.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée Now instead of using the replay_lock to guard the output of the log we now use it to protect the whole execution section. This replaces what the BQL used to do when it was held during TCG execution. We also introduce some rules for locking order - mainly that you cannot take the replay_mutex while holding the BQL. This leads to some slight sophistry during start-up and extending the replay_mutex_destroy function to unlock the mutex without checking for the BQL condition so it can be cleanly dropped in the non-replay case. Signed-off-by: Alex Bennée Signed-off-by: Pavel Dovgalyuk Tested-by: Pavel Dovgalyuk -- v6: refined lock/unlock logic due to removing the BQL patches removed replay lock/unlock from audio functions v2: updated replay_mutex_lock/unlock functions as suggested by Paolo Bonzini updated docs --- cpus.c | 24 ++++++++++++++++++++++-- docs/replay.txt | 22 ++++++++++++++++++++++ include/sysemu/replay.h | 2 ++ replay/replay-audio.c | 14 ++++---------- replay/replay-char.c | 21 ++++++++------------- replay/replay-events.c | 20 +++++++------------- replay/replay-internal.c | 27 +++++++++++++++++++-------- replay/replay-time.c | 10 +++++----- replay/replay.c | 38 ++++++++++++++++++-------------------- util/main-loop.c | 15 +++++++++++---- vl.c | 2 ++ 11 files changed, 120 insertions(+), 75 deletions(-) diff --git a/cpus.c b/cpus.c index f298b65..40ed0e6 100644 --- a/cpus.c +++ b/cpus.c @@ -1307,6 +1307,8 @@ static void prepare_icount_for_run(CPUState *cpu) insns_left = MIN(0xffff, cpu->icount_budget); cpu->icount_decr.u16.low = insns_left; cpu->icount_extra = cpu->icount_budget - insns_left; + + replay_mutex_lock(); } } @@ -1322,6 +1324,8 @@ static void process_icount_data(CPUState *cpu) cpu->icount_budget = 0; replay_account_executed_instructions(); + + replay_mutex_unlock(); } } @@ -1336,11 +1340,9 @@ static int tcg_cpu_exec(CPUState *cpu) #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif - qemu_mutex_unlock_iothread(); cpu_exec_start(cpu); ret = cpu_exec(cpu); cpu_exec_end(cpu); - qemu_mutex_lock_iothread(); #ifdef CONFIG_PROFILER tcg_time += profile_getclock() - ti; #endif @@ -1409,6 +1411,9 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) cpu->exit_request = 1; while (1) { + qemu_mutex_unlock_iothread(); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); /* Account partial waits to QEMU_CLOCK_VIRTUAL. */ qemu_account_warp_timer(); @@ -1417,6 +1422,8 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) */ handle_icount_deadline(); + replay_mutex_unlock(); + if (!cpu) { cpu = first_cpu; } @@ -1432,11 +1439,13 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg) if (cpu_can_run(cpu)) { int r; + qemu_mutex_unlock_iothread(); prepare_icount_for_run(cpu); r = tcg_cpu_exec(cpu); process_icount_data(cpu); + qemu_mutex_lock_iothread(); if (r == EXCP_DEBUG) { cpu_handle_guest_debug(cpu); @@ -1626,7 +1635,9 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) while (1) { if (cpu_can_run(cpu)) { int r; + qemu_mutex_unlock_iothread(); r = tcg_cpu_exec(cpu); + qemu_mutex_lock_iothread(); switch (r) { case EXCP_DEBUG: cpu_handle_guest_debug(cpu); @@ -1773,12 +1784,21 @@ void pause_all_vcpus(void) } } + /* We need to drop the replay_lock so any vCPU threads woken up + * can finish their replay tasks + */ + replay_mutex_unlock(); + while (!all_vcpus_paused()) { qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); CPU_FOREACH(cpu) { qemu_cpu_kick(cpu); } } + + qemu_mutex_unlock_iothread(); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); } void cpu_resume(CPUState *cpu) diff --git a/docs/replay.txt b/docs/replay.txt index c52407f..959633e 100644 --- a/docs/replay.txt +++ b/docs/replay.txt @@ -49,6 +49,28 @@ Modifications of qemu include: * recording/replaying user input (mouse and keyboard) * adding internal checkpoints for cpu and io synchronization +Locking and thread synchronisation +---------------------------------- + +Previously the synchronisation of the main thread and the vCPU thread +was ensured by the holding of the BQL. However the trend has been to +reduce the time the BQL was held across the system including under TCG +system emulation. As it is important that batches of events are kept +in sequence (e.g. expiring timers and checkpoints in the main thread +while instruction checkpoints are written by the vCPU thread) we need +another lock to keep things in lock-step. This role is now handled by +the replay_mutex_lock. It used to be held only for each event being +written but now it is held for a whole execution period. This results +in a deterministic ping-pong between the two main threads. + +As the BQL is now a finer grained lock than the replay_lock it is almost +certainly a bug, and a source of deadlocks, to take the +replay_mutex_lock while the BQL is held. This is enforced by an assert. +While the unlocks are usually in the reverse order, this is not +necessary; you can drop the replay_lock while holding the BQL, without +doing a more complicated unlock_iothread/replay_unlock/lock_iothread +sequence. + Non-deterministic events ------------------------ diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 291bcbc..239d00d 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -61,6 +61,8 @@ void replay_mutex_unlock(void); /* Replay process control functions */ +/*! Enables and take replay locks (even if we don't use it) */ +void replay_init_locks(void); /*! Enables recording or saving event log with specified parameters */ void replay_configure(struct QemuOpts *opts); /*! Initializes timers used for snapshotting and enables events recording */ diff --git a/replay/replay-audio.c b/replay/replay-audio.c index 3d83743..b113836 100644 --- a/replay/replay-audio.c +++ b/replay/replay-audio.c @@ -19,20 +19,17 @@ void replay_audio_out(int *played) { if (replay_mode == REPLAY_MODE_RECORD) { + g_assert(replay_mutex_locked()); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_AUDIO_OUT); replay_put_dword(*played); - replay_mutex_unlock(); } else if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); replay_account_executed_instructions(); - replay_mutex_lock(); if (replay_next_event_is(EVENT_AUDIO_OUT)) { *played = replay_get_dword(); replay_finish_event(); - replay_mutex_unlock(); } else { - replay_mutex_unlock(); error_report("Missing audio out event in the replay log"); abort(); } @@ -44,8 +41,8 @@ void replay_audio_in(int *recorded, void *samples, int *wpos, int size) int pos; uint64_t left, right; if (replay_mode == REPLAY_MODE_RECORD) { + g_assert(replay_mutex_locked()); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_AUDIO_IN); replay_put_dword(*recorded); replay_put_dword(*wpos); @@ -55,10 +52,9 @@ void replay_audio_in(int *recorded, void *samples, int *wpos, int size) replay_put_qword(left); replay_put_qword(right); } - replay_mutex_unlock(); } else if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); replay_account_executed_instructions(); - replay_mutex_lock(); if (replay_next_event_is(EVENT_AUDIO_IN)) { *recorded = replay_get_dword(); *wpos = replay_get_dword(); @@ -69,9 +65,7 @@ void replay_audio_in(int *recorded, void *samples, int *wpos, int size) audio_sample_from_uint64(samples, pos, left, right); } replay_finish_event(); - replay_mutex_unlock(); } else { - replay_mutex_unlock(); error_report("Missing audio in event in the replay log"); abort(); } diff --git a/replay/replay-char.c b/replay/replay-char.c index cbf7c04..736cc8c 100755 --- a/replay/replay-char.c +++ b/replay/replay-char.c @@ -96,25 +96,24 @@ void *replay_event_char_read_load(void) void replay_char_write_event_save(int res, int offset) { + g_assert(replay_mutex_locked()); + replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_CHAR_WRITE); replay_put_dword(res); replay_put_dword(offset); - replay_mutex_unlock(); } void replay_char_write_event_load(int *res, int *offset) { + g_assert(replay_mutex_locked()); + replay_account_executed_instructions(); - replay_mutex_lock(); if (replay_next_event_is(EVENT_CHAR_WRITE)) { *res = replay_get_dword(); *offset = replay_get_dword(); replay_finish_event(); - replay_mutex_unlock(); } else { - replay_mutex_unlock(); error_report("Missing character write event in the replay log"); exit(1); } @@ -122,23 +121,21 @@ void replay_char_write_event_load(int *res, int *offset) int replay_char_read_all_load(uint8_t *buf) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); + if (replay_next_event_is(EVENT_CHAR_READ_ALL)) { size_t size; int res; replay_get_array(buf, &size); replay_finish_event(); - replay_mutex_unlock(); res = (int)size; assert(res >= 0); return res; } else if (replay_next_event_is(EVENT_CHAR_READ_ALL_ERROR)) { int res = replay_get_dword(); replay_finish_event(); - replay_mutex_unlock(); return res; } else { - replay_mutex_unlock(); error_report("Missing character read all event in the replay log"); exit(1); } @@ -146,19 +143,17 @@ int replay_char_read_all_load(uint8_t *buf) void replay_char_read_all_save_error(int res) { + g_assert(replay_mutex_locked()); assert(res < 0); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_CHAR_READ_ALL_ERROR); replay_put_dword(res); - replay_mutex_unlock(); } void replay_char_read_all_save_buf(uint8_t *buf, int offset) { + g_assert(replay_mutex_locked()); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_CHAR_READ_ALL); replay_put_array(buf, offset); - replay_mutex_unlock(); } diff --git a/replay/replay-events.c b/replay/replay-events.c index e858254..54dd9d2 100644 --- a/replay/replay-events.c +++ b/replay/replay-events.c @@ -79,16 +79,14 @@ bool replay_has_events(void) void replay_flush_events(void) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); + while (!QTAILQ_EMPTY(&events_list)) { Event *event = QTAILQ_FIRST(&events_list); - replay_mutex_unlock(); replay_run_event(event); - replay_mutex_lock(); QTAILQ_REMOVE(&events_list, event, events); g_free(event); } - replay_mutex_unlock(); } void replay_disable_events(void) @@ -102,14 +100,14 @@ void replay_disable_events(void) void replay_clear_events(void) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); + while (!QTAILQ_EMPTY(&events_list)) { Event *event = QTAILQ_FIRST(&events_list); QTAILQ_REMOVE(&events_list, event, events); g_free(event); } - replay_mutex_unlock(); } /*! Adds specified async event to the queue */ @@ -136,9 +134,8 @@ void replay_add_event(ReplayAsyncEventKind event_kind, event->opaque2 = opaque2; event->id = id; - replay_mutex_lock(); + g_assert(replay_mutex_locked()); QTAILQ_INSERT_TAIL(&events_list, event, events); - replay_mutex_unlock(); } void replay_bh_schedule_event(QEMUBH *bh) @@ -207,13 +204,11 @@ static void replay_save_event(Event *event, int checkpoint) /* Called with replay mutex locked */ void replay_save_events(int checkpoint) { + g_assert(replay_mutex_locked()); while (!QTAILQ_EMPTY(&events_list)) { Event *event = QTAILQ_FIRST(&events_list); replay_save_event(event, checkpoint); - - replay_mutex_unlock(); replay_run_event(event); - replay_mutex_lock(); QTAILQ_REMOVE(&events_list, event, events); g_free(event); } @@ -292,6 +287,7 @@ static Event *replay_read_event(int checkpoint) /* Called with replay mutex locked */ void replay_read_events(int checkpoint) { + g_assert(replay_mutex_locked()); while (replay_state.data_kind == EVENT_ASYNC) { Event *event = replay_read_event(checkpoint); if (!event) { @@ -299,9 +295,7 @@ void replay_read_events(int checkpoint) } replay_finish_event(); read_event_kind = -1; - replay_mutex_unlock(); replay_run_event(event); - replay_mutex_lock(); g_free(event); } diff --git a/replay/replay-internal.c b/replay/replay-internal.c index 7cdefea..139b9fa 100644 --- a/replay/replay-internal.c +++ b/replay/replay-internal.c @@ -174,10 +174,16 @@ static __thread bool replay_locked; void replay_mutex_init(void) { qemu_mutex_init(&lock); + /* Hold the mutex while we start-up */ + qemu_mutex_lock(&lock); + replay_locked = true; } void replay_mutex_destroy(void) { + if (replay_mutex_locked()) { + qemu_mutex_unlock(&lock); + } qemu_mutex_destroy(&lock); } @@ -186,25 +192,31 @@ bool replay_mutex_locked(void) return replay_locked; } +/* Ordering constraints, replay_lock must be taken before BQL */ void replay_mutex_lock(void) { - g_assert(!replay_mutex_locked()); - qemu_mutex_lock(&lock); - replay_locked = true; + if (replay_mode != REPLAY_MODE_NONE) { + g_assert(!qemu_mutex_iothread_locked()); + g_assert(!replay_mutex_locked()); + qemu_mutex_lock(&lock); + replay_locked = true; + } } void replay_mutex_unlock(void) { - g_assert(replay_mutex_locked()); - replay_locked = false; - qemu_mutex_unlock(&lock); + if (replay_mode != REPLAY_MODE_NONE) { + g_assert(replay_mutex_locked()); + replay_locked = false; + qemu_mutex_unlock(&lock); + } } /*! Saves cached instructions. */ void replay_save_instructions(void) { if (replay_file && replay_mode == REPLAY_MODE_RECORD) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); int diff = (int)(replay_get_current_step() - replay_state.current_step); /* Time can only go forward */ @@ -215,6 +227,5 @@ void replay_save_instructions(void) replay_put_dword(diff); replay_state.current_step += diff; } - replay_mutex_unlock(); } } diff --git a/replay/replay-time.c b/replay/replay-time.c index f70382a..6a7565e 100644 --- a/replay/replay-time.c +++ b/replay/replay-time.c @@ -17,13 +17,13 @@ int64_t replay_save_clock(ReplayClockKind kind, int64_t clock) { - replay_save_instructions(); if (replay_file) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); + + replay_save_instructions(); replay_put_event(EVENT_CLOCK + kind); replay_put_qword(clock); - replay_mutex_unlock(); } return clock; @@ -46,16 +46,16 @@ void replay_read_next_clock(ReplayClockKind kind) /*! Reads next clock event from the input. */ int64_t replay_read_clock(ReplayClockKind kind) { + g_assert(replay_file && replay_mutex_locked()); + replay_account_executed_instructions(); if (replay_file) { int64_t ret; - replay_mutex_lock(); if (replay_next_event_is(EVENT_CLOCK + kind)) { replay_read_next_clock(kind); } ret = replay_state.cached_clock[kind]; - replay_mutex_unlock(); return ret; } diff --git a/replay/replay.c b/replay/replay.c index 9cddb6b..a8b57cd 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -81,7 +81,7 @@ int replay_get_instructions(void) void replay_account_executed_instructions(void) { if (replay_mode == REPLAY_MODE_PLAY) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); if (replay_state.instructions_count > 0) { int count = (int)(replay_get_current_step() - replay_state.current_step); @@ -100,24 +100,22 @@ void replay_account_executed_instructions(void) qemu_notify_event(); } } - replay_mutex_unlock(); } } bool replay_exception(void) { + if (replay_mode == REPLAY_MODE_RECORD) { + g_assert(replay_mutex_locked()); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_EXCEPTION); - replay_mutex_unlock(); return true; } else if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); bool res = replay_has_exception(); if (res) { - replay_mutex_lock(); replay_finish_event(); - replay_mutex_unlock(); } return res; } @@ -129,10 +127,9 @@ bool replay_has_exception(void) { bool res = false; if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); replay_account_executed_instructions(); - replay_mutex_lock(); res = replay_next_event_is(EVENT_EXCEPTION); - replay_mutex_unlock(); } return res; @@ -141,17 +138,15 @@ bool replay_has_exception(void) bool replay_interrupt(void) { if (replay_mode == REPLAY_MODE_RECORD) { + g_assert(replay_mutex_locked()); replay_save_instructions(); - replay_mutex_lock(); replay_put_event(EVENT_INTERRUPT); - replay_mutex_unlock(); return true; } else if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); bool res = replay_has_interrupt(); if (res) { - replay_mutex_lock(); replay_finish_event(); - replay_mutex_unlock(); } return res; } @@ -163,10 +158,9 @@ bool replay_has_interrupt(void) { bool res = false; if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); replay_account_executed_instructions(); - replay_mutex_lock(); res = replay_next_event_is(EVENT_INTERRUPT); - replay_mutex_unlock(); } return res; } @@ -174,9 +168,8 @@ bool replay_has_interrupt(void) void replay_shutdown_request(ShutdownCause cause) { if (replay_mode == REPLAY_MODE_RECORD) { - replay_mutex_lock(); + g_assert(replay_mutex_locked()); replay_put_event(EVENT_SHUTDOWN + cause); - replay_mutex_unlock(); } } @@ -190,9 +183,9 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint) return true; } - replay_mutex_lock(); if (replay_mode == REPLAY_MODE_PLAY) { + g_assert(replay_mutex_locked()); if (replay_next_event_is(EVENT_CHECKPOINT + checkpoint)) { replay_finish_event(); } else if (replay_state.data_kind != EVENT_ASYNC) { @@ -205,15 +198,20 @@ bool replay_checkpoint(ReplayCheckpoint checkpoint) checkpoint were processed */ res = replay_state.data_kind != EVENT_ASYNC; } else if (replay_mode == REPLAY_MODE_RECORD) { + g_assert(replay_mutex_locked()); replay_put_event(EVENT_CHECKPOINT + checkpoint); replay_save_events(checkpoint); res = true; } out: - replay_mutex_unlock(); return res; } +void replay_init_locks(void) +{ + replay_mutex_init(); +} + static void replay_enable(const char *fname, int mode) { const char *fmode = NULL; @@ -233,8 +231,6 @@ static void replay_enable(const char *fname, int mode) atexit(replay_finish); - replay_mutex_init(); - replay_file = fopen(fname, fmode); if (replay_file == NULL) { fprintf(stderr, "Replay: open %s: %s\n", fname, strerror(errno)); @@ -274,6 +270,8 @@ void replay_configure(QemuOpts *opts) Location loc; if (!opts) { + /* we no longer need this lock */ + replay_mutex_destroy(); return; } diff --git a/util/main-loop.c b/util/main-loop.c index 7558eb5..992f9b0 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -29,6 +29,7 @@ #include "qemu/sockets.h" // struct in_addr needed for libslirp.h #include "sysemu/qtest.h" #include "sysemu/cpus.h" +#include "sysemu/replay.h" #include "slirp/libslirp.h" #include "qemu/main-loop.h" #include "block/aio.h" @@ -245,18 +246,19 @@ static int os_host_main_loop_wait(int64_t timeout) timeout = SCALE_MS; } + if (timeout) { spin_counter = 0; - qemu_mutex_unlock_iothread(); } else { spin_counter++; } + qemu_mutex_unlock_iothread(); + replay_mutex_unlock(); ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout); - if (timeout) { - qemu_mutex_lock_iothread(); - } + replay_mutex_lock(); + qemu_mutex_lock_iothread(); glib_pollfds_poll(); @@ -463,8 +465,13 @@ static int os_host_main_loop_wait(int64_t timeout) poll_timeout_ns = qemu_soonest_timeout(poll_timeout_ns, timeout); qemu_mutex_unlock_iothread(); + + replay_mutex_unlock(); + g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns); + replay_mutex_lock(); + qemu_mutex_lock_iothread(); if (g_poll_ret > 0) { for (i = 0; i < w->num; i++) { diff --git a/vl.c b/vl.c index 1170c69..47517f9 100644 --- a/vl.c +++ b/vl.c @@ -3061,6 +3061,8 @@ int main(int argc, char **argv, char **envp) qemu_init_cpu_list(); qemu_init_cpu_loop(); + + replay_init_locks(); qemu_mutex_lock_iothread(); atexit(qemu_run_exit_notifiers); From patchwork Tue Feb 27 09:53:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Pavel Dovgalyuk X-Patchwork-Id: 129753 Delivered-To: patch@linaro.org Received: by 10.46.66.2 with SMTP id p2csp1200834lja; Tue, 27 Feb 2018 01:58:24 -0800 (PST) X-Google-Smtp-Source: AG47ELsGi+7Y+MeajdV1qd61OeF0CcjOzBj2AN5uB8+keiLzauRZyjPx6rZBZO+avk2uGhSWX50E X-Received: by 10.129.28.204 with SMTP id c195mr8513982ywc.262.1519725504062; Tue, 27 Feb 2018 01:58:24 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519725504; cv=none; d=google.com; s=arc-20160816; b=E0FfgveDI3LZmbBAYeUpnIxRBqzUvCWgGHiA7EUDuzfq03pfJaHC6RGRWuPnDtC237 BK+uQCULNQWexu3+rGDzHIXmaH0B7WPW1DY/nvKEq4OC6Hhbx6jKwM4mJ5XC+axHWrW5 VLGhjDZBVMlXJtKcgxJjOiXUBNUz6CjzU4uxkC6pbSc6nfBlf/4r7HG+5lYbFtaSYZHf nUaBwG6PiR8qJA3y13ejvahXqglukMjtdTpw+KdI4nvbnkJ/VXuaJq+rxhFPuSl/wHSu B0JMK5A4FAWR5EkKX70n15V3EXmScK1rwkSsyB0XO3yviQiVYpodSkoV6C3hIy0PRvWs 8hAA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:cc:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject :content-transfer-encoding:mime-version:user-agent:references :in-reply-to:message-id:date:to:from:arc-authentication-results; bh=v9IcqYv/yTMbdIsaamfWIMaz4pDbaHYdRiABxfCNKtU=; b=M4zvVOpDC58H2aefmk32Oq3uWMkz42h0TAMsiKDJof9Aoq3uAaVSFNHxAYJ6kf9QH1 QAGT9Xnl7IDlPd1qBWV4mKeXufww2lvoPg+q/OngpP6tRd6VMLTOxebJozbH15X84WPQ RySS9Ym/yJM+PSyjcuG1sI7Ig5B+kDcJ6R+18RP75g1/omULE3RgJDwHAdtj/V1FEJc/ U6XVG0/cmYuua72W8ZqT7A5Rf8BIHQ0UXakP9yAvNY3bYIfFM5y99vSqDcrhMgpRTIu0 9avcgo4X/4W1bBMijRhvP6T3CXd5ZeT3siWvD/WfXgHdf1Q9H6sIKdYiAb3dAYi3WhGQ 6Czw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id y128-v6si1876455yba.806.2018.02.27.01.58.23 for (version=TLS1 cipher=AES128-SHA bits=128/128); Tue, 27 Feb 2018 01:58:24 -0800 (PST) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) smtp.mailfrom=qemu-devel-bounces+patch=linaro.org@nongnu.org Received: from localhost ([::1]:35841 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqc1f-0006Id-ET for patch@linaro.org; Tue, 27 Feb 2018 04:58:23 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39811) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwe-0001jq-MJ for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:53:14 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eqbwc-0005Fp-UI for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:53:12 -0500 Received: from mail.ispras.ru ([83.149.199.45]:57550) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eqbwc-0005Fj-Fn for qemu-devel@nongnu.org; Tue, 27 Feb 2018 04:53:10 -0500 Received: from [127.0.1.1] (unknown [85.142.117.226]) by mail.ispras.ru (Postfix) with ESMTPSA id 7F3FD54006A; Tue, 27 Feb 2018 12:53:09 +0300 (MSK) From: Pavel Dovgalyuk To: qemu-devel@nongnu.org Date: Tue, 27 Feb 2018 12:53:10 +0300 Message-ID: <20180227095310.1060.14500.stgit@pasha-VirtualBox> In-Reply-To: <20180227095135.1060.36549.stgit@pasha-VirtualBox> References: <20180227095135.1060.36549.stgit@pasha-VirtualBox> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 83.149.199.45 Subject: [Qemu-devel] [PATCH v7 17/22] scripts/replay-dump.py: replay log dumper X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kwolf@redhat.com, peter.maydell@linaro.org, war2jordan@live.com, pavel.dovgaluk@ispras.ru, quintela@redhat.com, ciro.santilli@gmail.com, jasowang@redhat.com, mst@redhat.com, zuban32s@gmail.com, maria.klimushenkova@ispras.ru, dovgaluk@ispras.ru, kraxel@redhat.com, boost.lists@gmail.com, thomas.dullien@googlemail.com, pbonzini@redhat.com, alex.bennee@linaro.org Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: "Qemu-devel" From: Alex Bennée This script is a debugging tool for looking through the contents of a replay log file. It is incomplete but should fail gracefully at events it doesn't understand. It currently understands two different log formats as the audio record/replay support was merged during since MTTCG. It was written to help debug what has caused the BQL changes to break replay support. Signed-off-by: Alex Bennée --- v2 - yet another update to the log format --- scripts/replay-dump.py | 308 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100755 scripts/replay-dump.py diff --git a/scripts/replay-dump.py b/scripts/replay-dump.py new file mode 100755 index 0000000..203bb31 --- /dev/null +++ b/scripts/replay-dump.py @@ -0,0 +1,308 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Dump the contents of a recorded execution stream +# +# Copyright (c) 2017 Alex Bennée +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +import argparse +import struct +from collections import namedtuple + +# This mirrors some of the global replay state which some of the +# stream loading refers to. Some decoders may read the next event so +# we need handle that case. Calling reuse_event will ensure the next +# event is read from the cache rather than advancing the file. + +class ReplayState(object): + def __init__(self): + self.event = -1 + self.event_count = 0 + self.already_read = False + self.current_checkpoint = 0 + self.checkpoint = 0 + + def set_event(self, ev): + self.event = ev + self.event_count += 1 + + def get_event(self): + self.already_read = False + return self.event + + def reuse_event(self, ev): + self.event = ev + self.already_read = True + + def set_checkpoint(self): + self.checkpoint = self.event - self.checkpoint_start + + def get_checkpoint(self): + return self.checkpoint + +replay_state = ReplayState() + +# Simple read functions that mirror replay-internal.c +# The file-stream is big-endian and manually written out a byte at a time. + +def read_byte(fin): + "Read a single byte" + return struct.unpack('>B', fin.read(1))[0] + +def read_event(fin): + "Read a single byte event, but save some state" + if replay_state.already_read: + return replay_state.get_event() + else: + replay_state.set_event(read_byte(fin)) + return replay_state.event + +def read_word(fin): + "Read a 16 bit word" + return struct.unpack('>H', fin.read(2))[0] + +def read_dword(fin): + "Read a 32 bit word" + return struct.unpack('>I', fin.read(4))[0] + +def read_qword(fin): + "Read a 64 bit word" + return struct.unpack('>Q', fin.read(8))[0] + +# Generic decoder structure +Decoder = namedtuple("Decoder", "eid name fn") + +def call_decode(table, index, dumpfile): + "Search decode table for next step" + decoder = next((d for d in table if d.eid == index), None) + if not decoder: + print "Could not decode index: %d" % (index) + print "Entry is: %s" % (decoder) + print "Decode Table is:\n%s" % (table) + return False + else: + return decoder.fn(decoder.eid, decoder.name, dumpfile) + +# Print event +def print_event(eid, name, string=None, event_count=None): + "Print event with count" + if not event_count: + event_count = replay_state.event_count + + if string: + print "%d:%s(%d) %s" % (event_count, name, eid, string) + else: + print "%d:%s(%d)" % (event_count, name, eid) + + +# Decoders for each event type + +def decode_unimp(eid, name, _unused_dumpfile): + "Unimplimented decoder, will trigger exit" + print "%s not handled - will now stop" % (name) + return False + +# Checkpoint decoder +def swallow_async_qword(eid, name, dumpfile): + "Swallow a qword of data without looking at it" + step_id = read_qword(dumpfile) + print " %s(%d) @ %d" % (name, eid, step_id) + return True + +async_decode_table = [ Decoder(0, "REPLAY_ASYNC_EVENT_BH", swallow_async_qword), + Decoder(1, "REPLAY_ASYNC_INPUT", decode_unimp), + Decoder(2, "REPLAY_ASYNC_INPUT_SYNC", decode_unimp), + Decoder(3, "REPLAY_ASYNC_CHAR_READ", decode_unimp), + Decoder(4, "REPLAY_ASYNC_EVENT_BLOCK", decode_unimp), + Decoder(5, "REPLAY_ASYNC_EVENT_NET", decode_unimp), +] +# See replay_read_events/replay_read_event +def decode_async(eid, name, dumpfile): + """Decode an ASYNC event""" + + print_event(eid, name) + + async_event_kind = read_byte(dumpfile) + async_event_checkpoint = read_byte(dumpfile) + + if async_event_checkpoint != replay_state.current_checkpoint: + print " mismatch between checkpoint %d and async data %d" % ( + replay_state.current_checkpoint, async_event_checkpoint) + return True + + return call_decode(async_decode_table, async_event_kind, dumpfile) + + +def decode_instruction(eid, name, dumpfile): + ins_diff = read_dword(dumpfile) + print_event(eid, name, "0x%x" % (ins_diff)) + return True + +def decode_audio_out(eid, name, dumpfile): + audio_data = read_dword(dumpfile) + print_event(eid, name, "%d" % (audio_data)) + return True + +def decode_checkpoint(eid, name, dumpfile): + """Decode a checkpoint. + + Checkpoints contain a series of async events with their own specific data. + """ + replay_state.set_checkpoint() + # save event count as we peek ahead + event_number = replay_state.event_count + next_event = read_event(dumpfile) + + # if the next event is EVENT_ASYNC there are a bunch of + # async events to read, otherwise we are done + if next_event != 3: + print_event(eid, name, "no additional data", event_number) + else: + print_event(eid, name, "more data follows", event_number) + + replay_state.reuse_event(next_event) + return True + +def decode_checkpoint_init(eid, name, dumpfile): + print_event(eid, name) + return True + +def decode_interrupt(eid, name, dumpfile): + print_event(eid, name) + return True + +def decode_clock(eid, name, dumpfile): + clock_data = read_qword(dumpfile) + print_event(eid, name, "0x%x" % (clock_data)) + return True + + +# pre-MTTCG merge +v5_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), + Decoder(1, "EVENT_INTERRUPT", decode_interrupt), + Decoder(2, "EVENT_EXCEPTION", decode_unimp), + Decoder(3, "EVENT_ASYNC", decode_async), + Decoder(4, "EVENT_SHUTDOWN", decode_unimp), + Decoder(5, "EVENT_CHAR_WRITE", decode_unimp), + Decoder(6, "EVENT_CHAR_READ_ALL", decode_unimp), + Decoder(7, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), + Decoder(8, "EVENT_CLOCK_HOST", decode_clock), + Decoder(9, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), + Decoder(10, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), + Decoder(11, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), + Decoder(12, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), + Decoder(13, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), + Decoder(14, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), + Decoder(15, "EVENT_CP_CLOCK_HOST", decode_checkpoint), + Decoder(16, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), + Decoder(17, "EVENT_CP_INIT", decode_checkpoint_init), + Decoder(18, "EVENT_CP_RESET", decode_checkpoint), +] + +# post-MTTCG merge, AUDIO support added +v6_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), + Decoder(1, "EVENT_INTERRUPT", decode_interrupt), + Decoder(2, "EVENT_EXCEPTION", decode_unimp), + Decoder(3, "EVENT_ASYNC", decode_async), + Decoder(4, "EVENT_SHUTDOWN", decode_unimp), + Decoder(5, "EVENT_CHAR_WRITE", decode_unimp), + Decoder(6, "EVENT_CHAR_READ_ALL", decode_unimp), + Decoder(7, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), + Decoder(8, "EVENT_AUDIO_OUT", decode_audio_out), + Decoder(9, "EVENT_AUDIO_IN", decode_unimp), + Decoder(10, "EVENT_CLOCK_HOST", decode_clock), + Decoder(11, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), + Decoder(12, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), + Decoder(13, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), + Decoder(14, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), + Decoder(15, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), + Decoder(16, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), + Decoder(17, "EVENT_CP_CLOCK_HOST", decode_checkpoint), + Decoder(18, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), + Decoder(19, "EVENT_CP_INIT", decode_checkpoint_init), + Decoder(20, "EVENT_CP_RESET", decode_checkpoint), +] + +# Shutdown cause added +v7_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), + Decoder(1, "EVENT_INTERRUPT", decode_interrupt), + Decoder(2, "EVENT_EXCEPTION", decode_unimp), + Decoder(3, "EVENT_ASYNC", decode_async), + Decoder(4, "EVENT_SHUTDOWN", decode_unimp), + Decoder(5, "EVENT_SHUTDOWN_HOST_ERR", decode_unimp), + Decoder(6, "EVENT_SHUTDOWN_HOST_QMP", decode_unimp), + Decoder(7, "EVENT_SHUTDOWN_HOST_SIGNAL", decode_unimp), + Decoder(8, "EVENT_SHUTDOWN_HOST_UI", decode_unimp), + Decoder(9, "EVENT_SHUTDOWN_GUEST_SHUTDOWN", decode_unimp), + Decoder(10, "EVENT_SHUTDOWN_GUEST_RESET", decode_unimp), + Decoder(11, "EVENT_SHUTDOWN_GUEST_PANIC", decode_unimp), + Decoder(12, "EVENT_SHUTDOWN___MAX", decode_unimp), + Decoder(13, "EVENT_CHAR_WRITE", decode_unimp), + Decoder(14, "EVENT_CHAR_READ_ALL", decode_unimp), + Decoder(15, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), + Decoder(16, "EVENT_AUDIO_OUT", decode_audio_out), + Decoder(17, "EVENT_AUDIO_IN", decode_unimp), + Decoder(18, "EVENT_CLOCK_HOST", decode_clock), + Decoder(19, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), + Decoder(20, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), + Decoder(21, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), + Decoder(22, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), + Decoder(23, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), + Decoder(24, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), + Decoder(25, "EVENT_CP_CLOCK_HOST", decode_checkpoint), + Decoder(26, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), + Decoder(27, "EVENT_CP_INIT", decode_checkpoint_init), + Decoder(28, "EVENT_CP_RESET", decode_checkpoint), +] + +def parse_arguments(): + "Grab arguments for script" + parser = argparse.ArgumentParser() + parser.add_argument("-f", "--file", help='record/replay dump to read from', + required=True) + return parser.parse_args() + +def decode_file(filename): + "Decode a record/replay dump" + dumpfile = open(filename, "rb") + + # read and throwaway the header + version = read_dword(dumpfile) + junk = read_qword(dumpfile) + + print "HEADER: version 0x%x" % (version) + + if version == 0xe02007: + event_decode_table = v7_event_table + replay_state.checkpoint_start = 12 + elif version == 0xe02006: + event_decode_table = v6_event_table + replay_state.checkpoint_start = 12 + else: + event_decode_table = v5_event_table + replay_state.checkpoint_start = 10 + + try: + decode_ok = True + while decode_ok: + event = read_event(dumpfile) + decode_ok = call_decode(event_decode_table, event, dumpfile) + finally: + dumpfile.close() + +if __name__ == "__main__": + args = parse_arguments() + decode_file(args.file)