@@ -4,6 +4,7 @@
#include "qemu/typedefs.h"
#include "qemu-common.h"
#include "qemu/notify.h"
+#include "replay/replay.h"
/* timers */
@@ -64,6 +65,10 @@ struct QEMUTimer {
};
extern QEMUTimerListGroup main_loop_tlg;
+/* Offset for realtime clock for replay changed mode. */
+extern int64_t realtime_clock_replay_offset;
+/* Offset for real ticks clock for replay changed mode. */
+extern int64_t real_ticks_replay_offset;
/*
* QEMUClockType
@@ -237,7 +242,7 @@ void qemu_clock_unregister_reset_notifier(QEMUClockType type,
*
* Returns: true if any timer ran.
*/
-bool qemu_clock_run_timers(QEMUClockType type);
+bool qemu_clock_run_timers(QEMUClockType type, bool run_all);
/**
* qemu_clock_run_all_timers:
@@ -333,7 +338,7 @@ QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list);
*
* Returns: true if any timer expired
*/
-bool timerlist_run_timers(QEMUTimerList *timer_list);
+bool timerlist_run_timers(QEMUTimerList *timer_list, bool run_all);
/**
* timerlist_notify:
@@ -689,6 +694,7 @@ int64_t cpu_get_ticks(void);
void cpu_enable_ticks(void);
/* Caller must hold BQL */
void cpu_disable_ticks(void);
+void cpu_do_enable_ticks(void);
static inline int64_t get_ticks_per_sec(void)
{
@@ -699,8 +705,7 @@ static inline int64_t get_ticks_per_sec(void)
* Low level clock functions
*/
-/* real time host monotonic timer */
-static inline int64_t get_clock_realtime(void)
+static inline int64_t get_clock_realtime_impl(void)
{
struct timeval tv;
@@ -708,6 +713,24 @@ static inline int64_t get_clock_realtime(void)
return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
}
+/* real time host monotonic timer */
+static inline int64_t get_clock_realtime(void)
+{
+ int64_t result = get_clock_realtime_impl();
+
+ if (replay_mode == REPLAY_SAVE) {
+ replay_save_clock(REPLAY_CLOCK_REALTIME, result);
+ } else if (replay_mode == REPLAY_PLAY) {
+ if (replay_get_play_submode() == REPLAY_PLAY_CHANGED) {
+ result += realtime_clock_replay_offset;
+ } else {
+ result = replay_read_clock(REPLAY_CLOCK_REALTIME);
+ }
+ }
+
+ return result;
+}
+
/* Warning: don't insert tracepoints into these functions, they are
also used by simpletrace backend and tracepoints would cause
an infinite recursion! */
@@ -749,6 +772,8 @@ int64_t cpu_get_clock(void);
/*******************************************/
/* host CPU ticks (if available) */
+#define cpu_get_real_ticks cpu_get_real_ticks_impl
+
#if defined(_ARCH_PPC)
static inline int64_t cpu_get_real_ticks(void)
@@ -902,6 +927,27 @@ static inline int64_t cpu_get_real_ticks (void)
}
#endif
+#undef cpu_get_real_ticks
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+ int64_t val = cpu_get_real_ticks_impl();
+
+ if (replay_mode == REPLAY_SAVE) {
+ replay_save_clock(REPLAY_CLOCK_REAL_TICKS, val);
+ } else if (replay_mode == REPLAY_PLAY) {
+ if (replay_get_play_submode() == REPLAY_PLAY_CHANGED) {
+ // not used in replay_icount mode
+ // remove it later?
+ val += real_ticks_replay_offset;
+ } else {
+ val = replay_read_clock(REPLAY_CLOCK_REAL_TICKS);
+ }
+ }
+
+ return val;
+}
+
#ifdef CONFIG_PROFILER
static inline int64_t profile_getclock(void)
{
@@ -41,6 +41,9 @@
#include <sys/prctl.h>
#endif
+#include "replay/replay.h"
+#include "qemu/log.h"
+
/***********************************************************/
/* timers */
@@ -103,7 +106,8 @@ QEMUTimerList *timerlist_new(QEMUClockType type,
QEMUClock *clock = qemu_clock_ptr(type);
timer_list = g_malloc0(sizeof(QEMUTimerList));
- qemu_event_init(&timer_list->timers_done_ev, false);
+ // create signaled event, because they should be signaled outside the timerlist_run_timers
function
+ qemu_event_init(&timer_list->timers_done_ev, true);
timer_list->clock = clock;
timer_list->notify_cb = cb;
These patches contain modifications for recording and replaying host and virtual clock to the execution log. RDTSC output is also recorded. Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com> --- timer_list->notify_opaque = opaque; @@ -457,7 +461,7 @@ bool timer_expired(QEMUTimer *timer_head, int64_t current_time) return timer_expired_ns(timer_head, current_time * timer_head->scale); } -bool timerlist_run_timers(QEMUTimerList *timer_list) +bool timerlist_run_timers(QEMUTimerList *timer_list, bool run_all) { QEMUTimer *ts; int64_t current_time; @@ -465,6 +469,20 @@ bool timerlist_run_timers(QEMUTimerList *timer_list) QEMUTimerCB *cb; void *opaque; + switch (timer_list->clock->type) { + case QEMU_CLOCK_REALTIME: + break; + default: + case QEMU_CLOCK_VIRTUAL: + if ((replay_mode != REPLAY_NONE && !runstate_is_running()) || !replay_checkpoint(run_all ? 2 : 3)) + return false; + break; + case QEMU_CLOCK_HOST: + if ((replay_mode != REPLAY_NONE && !runstate_is_running()) || !replay_checkpoint(run_all ? 5 : 6)) + return false; + break; + } + qemu_event_reset(&timer_list->timers_done_ev); if (!timer_list->clock->enabled) { goto out; @@ -497,9 +515,9 @@ out: return progress; } -bool qemu_clock_run_timers(QEMUClockType type) +bool qemu_clock_run_timers(QEMUClockType type, bool run_all) { - return timerlist_run_timers(main_loop_tlg.tl[type]); + return timerlist_run_timers(main_loop_tlg.tl[type], run_all); } void timerlistgroup_init(QEMUTimerListGroup *tlg, @@ -524,7 +542,7 @@ bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg) QEMUClockType type; bool progress = false; for (type = 0; type < QEMU_CLOCK_MAX; type++) { - progress |= timerlist_run_timers(tlg->tl[type]); + progress |= timerlist_run_timers(tlg->tl[type], false); } return progress; } @@ -533,11 +551,17 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg) { int64_t deadline = -1; QEMUClockType type; + bool play = replay_mode == REPLAY_PLAY && replay_get_play_submode() != REPLAY_PLAY_CHANGED; for (type = 0; type < QEMU_CLOCK_MAX; type++) { if (qemu_clock_use_for_deadline(tlg->tl[type]->clock->type)) { - deadline = qemu_soonest_timeout(deadline, - timerlist_deadline_ns( + if (!play || tlg->tl[type]->clock->type == QEMU_CLOCK_REALTIME) { + deadline = qemu_soonest_timeout(deadline, + timerlist_deadline_ns( tlg->tl[type])); + } else { + // read clock from the replay file + qemu_clock_get_ns(tlg->tl[type]->clock->type); + } } } return deadline; @@ -553,11 +577,14 @@ int64_t qemu_clock_get_ns(QEMUClockType type) return get_clock(); default: case QEMU_CLOCK_VIRTUAL: - if (use_icount) { - return cpu_get_icount(); + if (replay_icount) { + now = replay_get_icount(); + } else if (use_icount) { + now = cpu_get_icount(); } else { - return cpu_get_clock(); + now = cpu_get_clock(); } + return now; case QEMU_CLOCK_HOST: now = get_clock_realtime(); last = clock->last; @@ -605,7 +632,7 @@ bool qemu_clock_run_all_timers(void) QEMUClockType type; for (type = 0; type < QEMU_CLOCK_MAX; type++) { - progress |= qemu_clock_run_timers(type); + progress |= qemu_clock_run_timers(type, true); } return progress;