diff options
-rw-r--r-- | cpus.c | 17 | ||||
-rw-r--r-- | include/qemu/timer.h | 8 | ||||
-rw-r--r-- | qtest.c | 3 | ||||
-rw-r--r-- | tests/ptimer-test-stubs.c | 4 | ||||
-rw-r--r-- | tests/ptimer-test.c | 6 | ||||
-rw-r--r-- | util/qemu-timer.c | 30 |
6 files changed, 53 insertions, 15 deletions
@@ -556,7 +556,8 @@ 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); int64_t warp = qemu_soonest_timeout(dest - clock, deadline); seqlock_write_lock(&timers_state.vm_clock_seqlock, @@ -616,7 +617,8 @@ 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + ~QEMU_TIMER_ATTR_EXTERNAL); if (deadline < 0) { static bool notified; if (!icount_sleep && !notified) { @@ -1352,7 +1354,12 @@ 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); + /* + * Include all the timers, because they may need an attention. + * Too long CPU execution may create unnecessary delay in UI. + */ + deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); /* Maintain prior (possibly buggy) behaviour where if no deadline * was set (as there is no QEMU_CLOCK_VIRTUAL timer) or it is more than @@ -1373,8 +1380,8 @@ 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); if (deadline == 0) { /* Wake up other AioContexts. */ diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 5bcab93..85bc6eb 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -62,13 +62,15 @@ typedef enum { * The following attributes are available: * * QEMU_TIMER_ATTR_EXTERNAL: drives external subsystem + * QEMU_TIMER_ATTR_ALL: mask for all existing attributes * * Timers with this attribute do not recorded in rr mode, therefore it could be * used for the subsystems that operate outside the guest core. Applicable only * with virtual clock type. */ -#define QEMU_TIMER_ATTR_EXTERNAL BIT(0) +#define QEMU_TIMER_ATTR_EXTERNAL ((int)BIT(0)) +#define QEMU_TIMER_ATTR_ALL 0xffffffff typedef struct QEMUTimerList QEMUTimerList; @@ -177,6 +179,8 @@ bool qemu_clock_use_for_deadline(QEMUClockType type); /** * qemu_clock_deadline_ns_all: * @type: the clock type + * @attr_mask: mask for the timer attributes that are included + * in deadline calculation * * Calculate the deadline across all timer lists associated * with a clock (as opposed to just the default one) @@ -184,7 +188,7 @@ bool qemu_clock_use_for_deadline(QEMUClockType type); * * Returns: time until expiry in nanoseconds or -1 */ -int64_t qemu_clock_deadline_ns_all(QEMUClockType type); +int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask); /** * qemu_clock_get_main_loop_timerlist: @@ -654,7 +654,8 @@ 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); } qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns); qtest_send_prefix(chr); diff --git a/tests/ptimer-test-stubs.c b/tests/ptimer-test-stubs.c index 54b3fd2..ed393d9 100644 --- a/tests/ptimer-test-stubs.c +++ b/tests/ptimer-test-stubs.c @@ -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 qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask) { - 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; diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c index b30aad0..5b20e91 100644 --- a/tests/ptimer-test.c +++ b/tests/ptimer-test.c @@ -50,13 +50,15 @@ 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); 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 = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL, + QEMU_TIMER_ATTR_ALL); } ptimer_test_set_qemu_time_ns(advanced_time); diff --git a/util/qemu-timer.c b/util/qemu-timer.c index 37ecfe3..d428fec 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -247,14 +247,38 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) * ignore whether or not the clock should be used in deadline * calculations. */ -int64_t qemu_clock_deadline_ns_all(QEMUClockType type) +int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask) { int64_t deadline = -1; + int64_t delta; + int64_t expire_time; + QEMUTimer *ts; QEMUTimerList *timer_list; QEMUClock *clock = qemu_clock_ptr(type); + + 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 & ~attr_mask)) { + 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(type); + if (delta <= 0) { + delta = 0; + } + deadline = qemu_soonest_timeout(deadline, delta); } return deadline; } |