summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Dovgalyuk <pavel.dovgalyuk@ispras.ru>2021-02-16 15:51:44 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2021-02-16 17:15:39 +0100
commit366a85e4bb748794b1ae0ca0ccc2d95f316679a0 (patch)
treeccbf65483b2908cc8ea997c735ca3cebe1510319
parent82e2756897810b6e17e0c352101878b97b1e2688 (diff)
replay: fix icount request when replaying clock access
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> Message-Id: <161347990483.1313189.8371838968343494161.stgit@pasha-ThinkPad-X280> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--include/sysemu/replay.h14
-rw-r--r--replay/replay-internal.c29
-rw-r--r--replay/replay-time.c4
-rw-r--r--replay/replay.c23
-rw-r--r--stubs/replay-tools.c2
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;