aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpus.c17
-rw-r--r--include/qemu/timer.h8
-rw-r--r--qtest.c3
-rw-r--r--tests/ptimer-test-stubs.c4
-rw-r--r--tests/ptimer-test.c6
-rw-r--r--util/qemu-timer.c30
6 files changed, 53 insertions, 15 deletions
diff --git a/cpus.c b/cpus.c
index f4ad855..85cd451 100644
--- a/cpus.c
+++ b/cpus.c
@@ -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:
diff --git a/qtest.c b/qtest.c
index 59df1b6..d8b4857 100644
--- a/qtest.c
+++ b/qtest.c
@@ -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;
}