aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpus.c3
-rw-r--r--include/sysemu/replay.h23
-rw-r--r--qemu-timer.c8
-rw-r--r--replay/Makefile.objs1
-rw-r--r--replay/replay-internal.h11
-rw-r--r--replay/replay-time.c64
-rw-r--r--stubs/replay.c13
7 files changed, 119 insertions, 4 deletions
diff --git a/cpus.c b/cpus.c
index f07cac2781..2385caa248 100644
--- a/cpus.c
+++ b/cpus.c
@@ -346,7 +346,8 @@ static void icount_warp_rt(void *opaque)
seqlock_write_lock(&timers_state.vm_clock_seqlock);
if (runstate_is_running()) {
- int64_t clock = cpu_get_clock_locked();
+ int64_t clock = REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT,
+ cpu_get_clock_locked());
int64_t warp_delta;
warp_delta = clock - vm_clock_warp_start;
diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h
index c2a7651d7a..2398509188 100644
--- a/include/sysemu/replay.h
+++ b/include/sysemu/replay.h
@@ -16,6 +16,16 @@
#include <stdint.h>
#include "qapi-types.h"
+/* replay clock kinds */
+enum ReplayClockKind {
+ /* host_clock */
+ REPLAY_CLOCK_HOST,
+ /* virtual_rt_clock */
+ REPLAY_CLOCK_VIRTUAL_RT,
+ REPLAY_CLOCK_COUNT
+};
+typedef enum ReplayClockKind ReplayClockKind;
+
extern ReplayMode replay_mode;
/* Processing the instructions */
@@ -43,6 +53,19 @@ bool replay_interrupt(void);
Returns true, when interrupt request is pending */
bool replay_has_interrupt(void);
+/* Processing clocks and other time sources */
+
+/*! Save the specified clock */
+int64_t replay_save_clock(ReplayClockKind kind, int64_t clock);
+/*! Read the specified clock from the log or return cached data */
+int64_t replay_read_clock(ReplayClockKind kind);
+/*! 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_RECORD \
+ ? replay_save_clock((clock), (value)) \
+ : (value))
+
/* Asynchronous events queue */
/*! Disables storing events in the queue */
diff --git a/qemu-timer.c b/qemu-timer.c
index 2463fe6f6a..3dc847ba3d 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -24,6 +24,7 @@
#include "qemu/main-loop.h"
#include "qemu/timer.h"
+#include "sysemu/replay.h"
#ifdef CONFIG_POSIX
#include <pthread.h>
@@ -570,15 +571,16 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
return cpu_get_clock();
}
case QEMU_CLOCK_HOST:
- now = get_clock_realtime();
+ now = REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime());
last = clock->last;
clock->last = now;
- if (now < last || now > (last + get_max_clock_jump())) {
+ if ((now < last || now > (last + get_max_clock_jump()))
+ && replay_mode == REPLAY_MODE_NONE) {
notifier_list_notify(&clock->reset_notifiers, &now);
}
return now;
case QEMU_CLOCK_VIRTUAL_RT:
- return cpu_get_clock();
+ return REPLAY_CLOCK(REPLAY_CLOCK_VIRTUAL_RT, cpu_get_clock());
}
}
diff --git a/replay/Makefile.objs b/replay/Makefile.objs
index 6b439c2c23..56328ac53b 100644
--- a/replay/Makefile.objs
+++ b/replay/Makefile.objs
@@ -1,3 +1,4 @@
common-obj-y += replay.o
common-obj-y += replay-internal.o
common-obj-y += replay-events.o
+common-obj-y += replay-time.o
diff --git a/replay/replay-internal.h b/replay/replay-internal.h
index 23807ca413..f042c46e70 100644
--- a/replay/replay-internal.h
+++ b/replay/replay-internal.h
@@ -23,6 +23,10 @@ enum ReplayEvents {
EVENT_EXCEPTION,
/* for async events */
EVENT_ASYNC,
+ /* for clock read/writes */
+ /* some of greater codes are reserved for clocks */
+ EVENT_CLOCK,
+ EVENT_CLOCK_LAST = EVENT_CLOCK + REPLAY_CLOCK_COUNT - 1,
EVENT_COUNT
};
@@ -35,6 +39,8 @@ enum ReplayAsyncEventKind {
typedef enum ReplayAsyncEventKind ReplayAsyncEventKind;
typedef struct ReplayState {
+ /*! Cached clock values. */
+ int64_t cached_clock[REPLAY_CLOCK_COUNT];
/*! Current step - number of processed instructions and timer events. */
uint64_t current_step;
/*! Number of instructions to be executed before other events happen. */
@@ -85,6 +91,11 @@ void replay_save_instructions(void);
\return true, if event was found */
bool replay_next_event_is(int event);
+/*! Reads next clock value from the file.
+ If clock kind read from the file is different from the parameter,
+ the value is not used. */
+void replay_read_next_clock(unsigned int kind);
+
/* Asynchronous events queue */
/*! Initializes events' processing internals */
diff --git a/replay/replay-time.c b/replay/replay-time.c
new file mode 100644
index 0000000000..6d06951f5e
--- /dev/null
+++ b/replay/replay-time.c
@@ -0,0 +1,64 @@
+/*
+ * replay-time.c
+ *
+ * Copyright (c) 2010-2015 Institute for System Programming
+ * of the Russian Academy of Sciences.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "sysemu/replay.h"
+#include "replay-internal.h"
+#include "qemu/error-report.h"
+
+int64_t replay_save_clock(ReplayClockKind kind, int64_t clock)
+{
+ replay_save_instructions();
+
+ if (replay_file) {
+ replay_mutex_lock();
+ replay_put_event(EVENT_CLOCK + kind);
+ replay_put_qword(clock);
+ replay_mutex_unlock();
+ }
+
+ return clock;
+}
+
+void replay_read_next_clock(ReplayClockKind kind)
+{
+ unsigned int read_kind = replay_data_kind - EVENT_CLOCK;
+
+ assert(read_kind == kind);
+
+ int64_t clock = replay_get_qword();
+
+ replay_check_error();
+ replay_finish_event();
+
+ replay_state.cached_clock[read_kind] = clock;
+}
+
+/*! Reads next clock event from the input. */
+int64_t replay_read_clock(ReplayClockKind kind)
+{
+ 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;
+ }
+
+ error_report("REPLAY INTERNAL ERROR %d", __LINE__);
+ exit(1);
+}
diff --git a/stubs/replay.c b/stubs/replay.c
index 12c1a7557d..f0d95b05f1 100644
--- a/stubs/replay.c
+++ b/stubs/replay.c
@@ -1,3 +1,16 @@
#include "sysemu/replay.h"
+#include <stdlib.h>
ReplayMode replay_mode;
+
+int64_t replay_save_clock(unsigned int kind, int64_t clock)
+{
+ abort();
+ return 0;
+}
+
+int64_t replay_read_clock(unsigned int kind)
+{
+ abort();
+ return 0;
+}