aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpus.c31
-rw-r--r--include/sysemu/replay.h3
-rw-r--r--replay/replay.c12
3 files changed, 36 insertions, 10 deletions
diff --git a/cpus.c b/cpus.c
index d8b3b46cc8..68f08f5b2d 100644
--- a/cpus.c
+++ b/cpus.c
@@ -583,18 +583,29 @@ void qemu_start_warp_timer(void)
return;
}
- /* warp clock deterministically in record/replay mode */
- if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) {
- return;
- }
+ if (replay_mode != REPLAY_MODE_PLAY) {
+ if (!all_cpu_threads_idle()) {
+ return;
+ }
- if (!all_cpu_threads_idle()) {
- return;
- }
+ if (qtest_enabled()) {
+ /* When testing, qtest commands advance icount. */
+ return;
+ }
- if (qtest_enabled()) {
- /* When testing, qtest commands advance icount. */
- return;
+ replay_checkpoint(CHECKPOINT_CLOCK_WARP_START);
+ } else {
+ /* warp clock deterministically in record/replay mode */
+ if (!replay_checkpoint(CHECKPOINT_CLOCK_WARP_START)) {
+ /* vCPU is sleeping and warp can't be started.
+ It is probably a race condition: notification sent
+ to vCPU was processed in advance and vCPU went to sleep.
+ Therefore we have to wake it up for doing someting. */
+ if (replay_has_checkpoint()) {
+ qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+ }
+ return;
+ }
}
/* We want to use the earliest deadline from ALL vm_clocks */
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index 3ced6bc231..7f7a594eca 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -120,6 +120,9 @@ void replay_shutdown_request(ShutdownCause cause);
Returns 0 in PLAY mode if checkpoint was not found.
Returns 1 in all other cases. */
bool replay_checkpoint(ReplayCheckpoint checkpoint);
+/*! Used to determine that checkpoint is pending.
+ Does not proceed to the next event in the log. */
+bool replay_has_checkpoint(void);
/* Asynchronous events queue */
diff --git a/replay/replay.c b/replay/replay.c
index 8228261401..379b51ab46 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -224,6 +224,18 @@ out:
return res;
}
+bool replay_has_checkpoint(void)
+{
+ bool res = false;
+ if (replay_mode == REPLAY_MODE_PLAY) {
+ g_assert(replay_mutex_locked());
+ replay_account_executed_instructions();
+ res = EVENT_CHECKPOINT <= replay_state.data_kind
+ && replay_state.data_kind <= EVENT_CHECKPOINT_LAST;
+ }
+ return res;
+}
+
static void replay_enable(const char *fname, int mode)
{
const char *fmode = NULL;