aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qemu-timer.c29
-rw-r--r--qemu-timer.h5
2 files changed, 33 insertions, 1 deletions
diff --git a/qemu-timer.c b/qemu-timer.c
index 67c2974959..f95374c7c1 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -150,6 +150,9 @@ struct QEMUClock {
int enabled;
QEMUTimer *warp_timer;
+
+ NotifierList reset_notifiers;
+ int64_t last;
};
struct QEMUTimer {
@@ -376,9 +379,15 @@ static QEMUTimer *active_timers[QEMU_NUM_CLOCKS];
static QEMUClock *qemu_new_clock(int type)
{
QEMUClock *clock;
+
clock = qemu_mallocz(sizeof(QEMUClock));
clock->type = type;
clock->enabled = 1;
+ notifier_list_init(&clock->reset_notifiers);
+ /* required to detect & report backward jumps */
+ if (type == QEMU_CLOCK_HOST) {
+ clock->last = get_clock_realtime();
+ }
return clock;
}
@@ -593,6 +602,8 @@ static void qemu_run_timers(QEMUClock *clock)
int64_t qemu_get_clock_ns(QEMUClock *clock)
{
+ int64_t now, last;
+
switch(clock->type) {
case QEMU_CLOCK_REALTIME:
return get_clock();
@@ -604,10 +615,26 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
return cpu_get_clock();
}
case QEMU_CLOCK_HOST:
- return get_clock_realtime();
+ now = get_clock_realtime();
+ last = clock->last;
+ clock->last = now;
+ if (now < last) {
+ notifier_list_notify(&clock->reset_notifiers, &now);
+ }
+ return now;
}
}
+void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+{
+ notifier_list_add(&clock->reset_notifiers, notifier);
+}
+
+void qemu_unregister_clock_reset_notifier(QEMUClock *clock, Notifier *notifier)
+{
+ notifier_list_remove(&clock->reset_notifiers, notifier);
+}
+
void init_clocks(void)
{
rt_clock = qemu_new_clock(QEMU_CLOCK_REALTIME);
diff --git a/qemu-timer.h b/qemu-timer.h
index 06cbe20914..0a43469847 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -2,6 +2,7 @@
#define QEMU_TIMER_H
#include "qemu-common.h"
+#include "notify.h"
#include <time.h>
#include <sys/time.h>
@@ -40,6 +41,10 @@ int64_t qemu_get_clock_ns(QEMUClock *clock);
void qemu_clock_enable(QEMUClock *clock, int enabled);
void qemu_clock_warp(QEMUClock *clock);
+void qemu_register_clock_reset_notifier(QEMUClock *clock, Notifier *notifier);
+void qemu_unregister_clock_reset_notifier(QEMUClock *clock,
+ Notifier *notifier);
+
QEMUTimer *qemu_new_timer(QEMUClock *clock, int scale,
QEMUTimerCB *cb, void *opaque);
void qemu_free_timer(QEMUTimer *ts);