@@ -555,7 +555,7 @@ void qtest_clock_warp(int64_t dest)
assert(qtest_enabled());
aio_context = qemu_get_aio_context();
while (clock < dest) {
- int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ int64_t deadline = virtual_clock_deadline_ns();
int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
seqlock_write_lock(&timers_state.vm_clock_seqlock,
@@ -615,7 +615,7 @@ void qemu_start_warp_timer(void)
/* We want to use the earliest deadline from ALL vm_clocks */
clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
- deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ deadline = virtual_clock_deadline_ns();
if (deadline < 0) {
static bool notified;
if (!icount_sleep && !notified) {
@@ -1363,7 +1363,7 @@ static int64_t tcg_get_icount_limit(void)
int64_t deadline;
if (replay_mode != REPLAY_MODE_PLAY) {
- deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ deadline = virtual_clock_deadline_ns();
/* Maintain prior (possibly buggy) behaviour where if no deadline
* was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than
@@ -1384,8 +1384,7 @@ static void handle_icount_deadline(void)
{
assert(qemu_in_vcpu_thread());
if (use_icount) {
- int64_t deadline =
- qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ int64_t deadline = virtual_clock_deadline_ns();
if (deadline == 0) {
/* Wake up other AioContexts. */
@@ -175,16 +175,15 @@ bool qemu_clock_expired(QEMUClockType type);
bool qemu_clock_use_for_deadline(QEMUClockType type);
/**
- * qemu_clock_deadline_ns_all:
- * @type: the clock type
+ * virtual_clock_deadline_ns:
*
* Calculate the deadline across all timer lists associated
- * with a clock (as opposed to just the default one)
+ * with virtual clock (excluding external timers)
* in nanoseconds, or -1 if no timer is set to expire.
*
* Returns: time until expiry in nanoseconds or -1
*/
-int64_t qemu_clock_deadline_ns_all(QEMUClockType type);
+int64_t virtual_clock_deadline_ns(void);
/**
* qemu_clock_get_main_loop_timerlist:
@@ -655,7 +655,7 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
int ret = qemu_strtoi64(words[1], NULL, 0, &ns);
g_assert(ret == 0);
} else {
- ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ ns = virtual_clock_deadline_ns();
}
qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns);
qtest_send_prefix(chr);
@@ -88,9 +88,9 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
return ptimer_test_time_ns;
}
-int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
+int64_t virtual_clock_deadline_ns(void)
{
- QEMUTimerList *timer_list = main_loop_tlg.tl[type];
+ QEMUTimerList *timer_list = main_loop_tlg.tl[QEMU_CLOCK_VIRTUAL];
QEMUTimer *t = timer_list->active_timers.next;
int64_t deadline = -1;
@@ -50,13 +50,13 @@ static void ptimer_test_set_qemu_time_ns(int64_t ns)
static void qemu_clock_step(uint64_t ns)
{
- int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ int64_t deadline = virtual_clock_deadline_ns();
int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns;
while (deadline != -1 && deadline <= advanced_time) {
ptimer_test_set_qemu_time_ns(deadline);
ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL);
- deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+ deadline = virtual_clock_deadline_ns();
}
ptimer_test_set_qemu_time_ns(advanced_time);
@@ -236,6 +236,7 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
qemu_mutex_unlock(&timer_list->active_timers_lock);
return -1;
}
+
expire_time = timer_list->active_timers->expire_time;
qemu_mutex_unlock(&timer_list->active_timers_lock);
@@ -248,19 +249,43 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
return delta;
}
-/* Calculate the soonest deadline across all timerlists attached
- * to the clock. This is used for the icount timeout so we
- * ignore whether or not the clock should be used in deadline
- * calculations.
+/*
+ * Calculate the soonest deadline across all timerlists attached
+ * to the virtual clock (excluding the external timers that do not affect
+ * the replayed guest state.
*/
-int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
+int64_t virtual_clock_deadline_ns(void)
{
int64_t deadline = -1;
+ int64_t delta;
+ int64_t expire_time;
+ QEMUTimer *ts;
QEMUTimerList *timer_list;
- QEMUClock *clock = qemu_clock_ptr(type);
+ QEMUClock *clock = qemu_clock_ptr(QEMU_CLOCK_VIRTUAL);
+
+ if (!clock->enabled) {
+ return -1;
+ }
+
QLIST_FOREACH(timer_list, &clock->timerlists, list) {
- deadline = qemu_soonest_timeout(deadline,
- timerlist_deadline_ns(timer_list));
+ qemu_mutex_lock(&timer_list->active_timers_lock);
+ ts = timer_list->active_timers;
+ /* Skip all external timers */
+ while (ts && (ts->attributes & QEMU_TIMER_ATTR_EXTERNAL)) {
+ ts = ts->next;
+ }
+ if (!ts) {
+ qemu_mutex_unlock(&timer_list->active_timers_lock);
+ continue;
+ }
+ expire_time = ts->expire_time;
+ qemu_mutex_unlock(&timer_list->active_timers_lock);
+
+ delta = expire_time - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ if (delta <= 0) {
+ delta = 0;
+ }
+ deadline = qemu_soonest_timeout(deadline, delta);
}
return deadline;
}