From: Paolo Bonzini <pbonzini@redhat.com>
To: Pavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>, qemu-devel@nongnu.org
Cc: alex.bennee@linaro.org
Subject: Re: [PATCH] replay: fix icount request when replaying clock access
Date: Tue, 16 Feb 2021 17:14:06 +0100 [thread overview]
Message-ID: <5f2d2ef8-39b9-bfec-066c-81c262b77afd@redhat.com> (raw)
In-Reply-To: <161347990483.1313189.8371838968343494161.stgit@pasha-ThinkPad-X280>
On 16/02/21 13:51, Pavel Dovgalyuk wrote:
> Record/replay provides REPLAY_CLOCK_LOCKED macro to access
> the clock when vm_clock_seqlock is locked. This macro is
> needed because replay internals operate icount. In locked case
> replay use icount_get_raw_locked for icount request, which prevents
> excess locking which leads to deadlock. But previously only
> record code used *_locked function and replay did not.
> Therefore sometimes clock access lead to deadlocks.
> This patch fixes clock access for replay too and uses *_locked
> icount access function.
>
> Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgalyuk@ispras.ru>
> ---
> include/sysemu/replay.h | 14 ++++++++------
> replay/replay-internal.c | 29 +++++++++++++++++++++++++----
> replay/replay-time.c | 4 ++--
> replay/replay.c | 23 +----------------------
> stubs/replay-tools.c | 2 +-
> 5 files changed, 37 insertions(+), 35 deletions(-)
>
> diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
> index 56c0c17c30..0f3b0f7eac 100644
> --- a/include/sysemu/replay.h
> +++ b/include/sysemu/replay.h
> @@ -128,18 +128,20 @@ bool replay_has_interrupt(void);
> int64_t replay_save_clock(ReplayClockKind kind, int64_t clock,
> int64_t raw_icount);
> /*! Read the specified clock from the log or return cached data */
> -int64_t replay_read_clock(ReplayClockKind kind);
> +int64_t replay_read_clock(ReplayClockKind kind, int64_t raw_icount);
> /*! Saves or reads the clock depending on the current replay mode. */
> #define REPLAY_CLOCK(clock, value) \
> - (replay_mode == REPLAY_MODE_PLAY ? replay_read_clock((clock)) \
> + (replay_mode == REPLAY_MODE_PLAY \
> + ? replay_read_clock((clock), icount_get_raw()) \
> : replay_mode == REPLAY_MODE_RECORD \
> - ? replay_save_clock((clock), (value), icount_get_raw()) \
> - : (value))
> + ? replay_save_clock((clock), (value), icount_get_raw()) \
> + : (value))
> #define REPLAY_CLOCK_LOCKED(clock, value) \
> - (replay_mode == REPLAY_MODE_PLAY ? replay_read_clock((clock)) \
> + (replay_mode == REPLAY_MODE_PLAY \
> + ? replay_read_clock((clock), icount_get_raw_locked()) \
> : replay_mode == REPLAY_MODE_RECORD \
> ? replay_save_clock((clock), (value), icount_get_raw_locked()) \
> - : (value))
> + : (value))
>
> /* Processing data from random generators */
>
> diff --git a/replay/replay-internal.c b/replay/replay-internal.c
> index 2e8a3e947a..77d0c82327 100644
> --- a/replay/replay-internal.c
> +++ b/replay/replay-internal.c
> @@ -247,10 +247,31 @@ void replay_advance_current_icount(uint64_t current_icount)
> /* Time can only go forward */
> assert(diff >= 0);
>
> - if (diff > 0) {
> - replay_put_event(EVENT_INSTRUCTION);
> - replay_put_dword(diff);
> - replay_state.current_icount += diff;
> + if (replay_mode == REPLAY_MODE_RECORD) {
> + if (diff > 0) {
> + replay_put_event(EVENT_INSTRUCTION);
> + replay_put_dword(diff);
> + replay_state.current_icount += diff;
> + }
> + } else if (replay_mode == REPLAY_MODE_PLAY) {
> + if (diff > 0) {
> + replay_state.instruction_count -= diff;
> + replay_state.current_icount += diff;
> + if (replay_state.instruction_count == 0) {
> + assert(replay_state.data_kind == EVENT_INSTRUCTION);
> + replay_finish_event();
> + /* Wake up iothread. This is required because
> + timers will not expire until clock counters
> + will be read from the log. */
> + qemu_notify_event();
> + }
> + }
> + /* Execution reached the break step */
> + if (replay_break_icount == replay_state.current_icount) {
> + /* Cannot make callback directly from the vCPU thread */
> + timer_mod_ns(replay_break_timer,
> + qemu_clock_get_ns(QEMU_CLOCK_REALTIME));
> + }
> }
> }
>
> diff --git a/replay/replay-time.c b/replay/replay-time.c
> index 43357c9f24..00ebcb7a49 100644
> --- a/replay/replay-time.c
> +++ b/replay/replay-time.c
> @@ -46,12 +46,12 @@ void replay_read_next_clock(ReplayClockKind kind)
> }
>
> /*! Reads next clock event from the input. */
> -int64_t replay_read_clock(ReplayClockKind kind)
> +int64_t replay_read_clock(ReplayClockKind kind, int64_t raw_icount)
> {
> int64_t ret;
> g_assert(replay_file && replay_mutex_locked());
>
> - replay_account_executed_instructions();
> + replay_advance_current_icount(raw_icount);
>
> if (replay_next_event_is(EVENT_CLOCK + kind)) {
> replay_read_next_clock(kind);
> diff --git a/replay/replay.c b/replay/replay.c
> index d4c228ab28..c806fec69a 100644
> --- a/replay/replay.c
> +++ b/replay/replay.c
> @@ -94,28 +94,7 @@ void replay_account_executed_instructions(void)
> if (replay_mode == REPLAY_MODE_PLAY) {
> g_assert(replay_mutex_locked());
> if (replay_state.instruction_count > 0) {
> - int count = (int)(replay_get_current_icount()
> - - replay_state.current_icount);
> -
> - /* Time can only go forward */
> - assert(count >= 0);
> -
> - replay_state.instruction_count -= count;
> - replay_state.current_icount += count;
> - if (replay_state.instruction_count == 0) {
> - assert(replay_state.data_kind == EVENT_INSTRUCTION);
> - replay_finish_event();
> - /* Wake up iothread. This is required because
> - timers will not expire until clock counters
> - will be read from the log. */
> - qemu_notify_event();
> - }
> - /* Execution reached the break step */
> - if (replay_break_icount == replay_state.current_icount) {
> - /* Cannot make callback directly from the vCPU thread */
> - timer_mod_ns(replay_break_timer,
> - qemu_clock_get_ns(QEMU_CLOCK_REALTIME));
> - }
> + replay_advance_current_icount(replay_get_current_icount());
> }
> }
> }
> diff --git a/stubs/replay-tools.c b/stubs/replay-tools.c
> index c06b360e22..43296b3d4e 100644
> --- a/stubs/replay-tools.c
> +++ b/stubs/replay-tools.c
> @@ -13,7 +13,7 @@ int64_t replay_save_clock(unsigned int kind, int64_t clock, int64_t raw_icount)
> return 0;
> }
>
> -int64_t replay_read_clock(unsigned int kind)
> +int64_t replay_read_clock(unsigned int kind, int64_t raw_icount)
> {
> abort();
> return 0;
>
I can't honestly say I understand this very well, but it's all in
replay_mode != REPLAY_MODE_NONE so queued, thanks.
Paolo
prev parent reply other threads:[~2021-02-16 16:16 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-16 12:51 [PATCH] replay: fix icount request when replaying clock access Pavel Dovgalyuk
2021-02-16 16:14 ` Paolo Bonzini [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5f2d2ef8-39b9-bfec-066c-81c262b77afd@redhat.com \
--to=pbonzini@redhat.com \
--cc=alex.bennee@linaro.org \
--cc=pavel.dovgalyuk@ispras.ru \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).