diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-10-03 15:11:43 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-10-17 17:31:00 +0200 |
commit | add40e9777de139fb317ca6b1fb0dc142601cfcd (patch) | |
tree | bec5acdd2592edaa95f52afd6ec2526e7f390c49 | |
parent | 0f809e5fbebb36788aea3523be7f93c04f2c7f8c (diff) | |
download | qemu-add40e9777de139fb317ca6b1fb0dc142601cfcd.tar.gz qemu-add40e9777de139fb317ca6b1fb0dc142601cfcd.tar.bz2 qemu-add40e9777de139fb317ca6b1fb0dc142601cfcd.zip |
timer: add timer_mod_anticipate and timer_mod_anticipate_ns
These let a user anticipate the deadline of a timer, atomically with
other sites that call the function. This helps avoiding complicated
lock hierarchies.
Reviewed-by: Alex Bligh <alex@alex.org.uk>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | include/qemu/timer.h | 26 | ||||
-rw-r--r-- | qemu-timer.c | 29 |
2 files changed, 55 insertions, 0 deletions
diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 1254ef729e..5afcffc3f9 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -545,6 +545,19 @@ void timer_del(QEMUTimer *ts); void timer_mod_ns(QEMUTimer *ts, int64_t expire_time); /** + * timer_mod_anticipate_ns: + * @ts: the timer + * @expire_time: the expiry time in nanoseconds + * + * Modify a timer to expire at @expire_time or the current time, + * whichever comes earlier. + * + * This function is thread-safe but the timer and its timer list must not be + * freed while this function is running. + */ +void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time); + +/** * timer_mod: * @ts: the timer * @expire_time: the expire time in the units associated with the timer @@ -558,6 +571,19 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time); void timer_mod(QEMUTimer *ts, int64_t expire_timer); /** + * timer_mod_anticipate: + * @ts: the timer + * @expire_time: the expiry time in nanoseconds + * + * Modify a timer to expire at @expire_time or the current time, whichever + * comes earlier, taking into account the scale associated with the timer. + * + * This function is thread-safe but the timer and its timer list must not be + * freed while this function is running. + */ +void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time); + +/** * timer_pending: * @ts: the timer * diff --git a/qemu-timer.c b/qemu-timer.c index 0305ad5313..e15ce477cc 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -410,11 +410,40 @@ void timer_mod_ns(QEMUTimer *ts, int64_t expire_time) } } +/* modify the current timer so that it will be fired when current_time + >= expire_time or the current deadline, whichever comes earlier. + The corresponding callback will be called. */ +void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time) +{ + QEMUTimerList *timer_list = ts->timer_list; + bool rearm; + + qemu_mutex_lock(&timer_list->active_timers_lock); + if (ts->expire_time == -1 || ts->expire_time > expire_time) { + if (ts->expire_time != -1) { + timer_del_locked(timer_list, ts); + } + rearm = timer_mod_ns_locked(timer_list, ts, expire_time); + } else { + rearm = false; + } + qemu_mutex_unlock(&timer_list->active_timers_lock); + + if (rearm) { + timerlist_rearm(timer_list); + } +} + void timer_mod(QEMUTimer *ts, int64_t expire_time) { timer_mod_ns(ts, expire_time * ts->scale); } +void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time) +{ + timer_mod_anticipate_ns(ts, expire_time * ts->scale); +} + bool timer_pending(QEMUTimer *ts) { return ts->expire_time >= 0; |