This patch does below: - Move function timerlist_has_timers() to be first QEMUTimerList function because there is a chance that we will make it private - Move QEMUTimerList related functions together - Remove below comments for function timerlist_deadline_ns(), because: -- There is already information in the header file include/qemu/timer.h -- "As above" part of the information is wrong /* * As above, but return -1 for no deadline, and do not cap to 2^32 * as we know the result is always positive. */
Signed-off-by: Xuebing Wang <xbi...@gmail.com> --- include/qemu/timer.h | 28 +++--- qemu-timer.c | 231 +++++++++++++++++++++++++------------------------- 2 files changed, 129 insertions(+), 130 deletions(-) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 7f9a074..55cd3a7 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -254,6 +254,20 @@ bool qemu_clock_run_all_timers(void); */ /** + * timerlist_has_timers: + * @timer_list: the timer list to operate on + * + * Determine whether a timer list has active timers + * + * Note that this function should not be used when other threads also access + * the timer list. The return value may be outdated by the time it is acted + * upon. + * + * Returns: true if the timer list has timers. + */ +bool timerlist_has_timers(QEMUTimerList *timer_list); + +/** * timerlist_new: * @type: the clock type to associate with the timerlist * @cb: the callback to call on notification @@ -276,20 +290,6 @@ QEMUTimerList *timerlist_new(QEMUClockType type, void timerlist_free(QEMUTimerList *timer_list); /** - * timerlist_has_timers: - * @timer_list: the timer list to operate on - * - * Determine whether a timer list has active timers - * - * Note that this function should not be used when other threads also access - * the timer list. The return value may be outdated by the time it is acted - * upon. - * - * Returns: true if the timer list has timers. - */ -bool timerlist_has_timers(QEMUTimerList *timer_list); - -/** * timerlist_expired: * @timer_list: the timer list to operate on * diff --git a/qemu-timer.c b/qemu-timer.c index e15ce47..4929f8b 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -95,6 +95,15 @@ static bool timer_expired_ns(QEMUTimer *timer_head, int64_t current_time) return timer_head && (timer_head->expire_time <= current_time); } +/* + * QEMUTimerList + */ + +bool timerlist_has_timers(QEMUTimerList *timer_list) +{ + return !!timer_list->active_timers; +} + QEMUTimerList *timerlist_new(QEMUClockType type, QEMUTimerListNotifyCB *cb, void *opaque) @@ -122,6 +131,112 @@ void timerlist_free(QEMUTimerList *timer_list) g_free(timer_list); } +bool timerlist_expired(QEMUTimerList *timer_list) +{ + int64_t expire_time; + + qemu_mutex_lock(&timer_list->active_timers_lock); + if (!timer_list->active_timers) { + qemu_mutex_unlock(&timer_list->active_timers_lock); + return false; + } + expire_time = timer_list->active_timers->expire_time; + qemu_mutex_unlock(&timer_list->active_timers_lock); + + return expire_time < qemu_clock_get_ns(timer_list->clock->type); +} + +int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) +{ + int64_t delta; + int64_t expire_time; + + if (!timer_list->clock->enabled) { + return -1; + } + + /* The active timers list may be modified before the caller uses our return + * value but ->notify_cb() is called when the deadline changes. Therefore + * the caller should notice the change and there is no race condition. + */ + qemu_mutex_lock(&timer_list->active_timers_lock); + if (!timer_list->active_timers) { + 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); + + delta = expire_time - qemu_clock_get_ns(timer_list->clock->type); + + if (delta <= 0) { + return 0; + } + + return delta; +} + +QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list) +{ + return timer_list->clock->type; +} + +bool timerlist_run_timers(QEMUTimerList *timer_list) +{ + QEMUTimer *ts; + int64_t current_time; + bool progress = false; + QEMUTimerCB *cb; + void *opaque; + + qemu_event_reset(&timer_list->timers_done_ev); + if (!timer_list->clock->enabled) { + goto out; + } + + current_time = qemu_clock_get_ns(timer_list->clock->type); + for(;;) { + qemu_mutex_lock(&timer_list->active_timers_lock); + ts = timer_list->active_timers; + if (!timer_expired_ns(ts, current_time)) { + qemu_mutex_unlock(&timer_list->active_timers_lock); + break; + } + + /* remove timer from the list before calling the callback */ + timer_list->active_timers = ts->next; + ts->next = NULL; + ts->expire_time = -1; + cb = ts->cb; + opaque = ts->opaque; + qemu_mutex_unlock(&timer_list->active_timers_lock); + + /* run the callback (the timer list can be modified) */ + cb(opaque); + progress = true; + } + +out: + qemu_event_set(&timer_list->timers_done_ev); + return progress; +} + +void timerlist_notify(QEMUTimerList *timer_list) +{ + if (timer_list->notify_cb) { + timer_list->notify_cb(timer_list->notify_opaque); + } else { + qemu_notify_event(); + } +} + +static void timerlist_rearm(QEMUTimerList *timer_list) +{ + /* Interrupt execution to force deadline recalculation. */ + qemu_clock_warp(timer_list->clock->type); + timerlist_notify(timer_list); +} + static void qemu_clock_init(QEMUClockType type) { QEMUClock *clock = qemu_clock_ptr(type); @@ -170,73 +285,18 @@ void qemu_clock_enable(QEMUClockType type, bool enabled) } } -bool timerlist_has_timers(QEMUTimerList *timer_list) -{ - return !!timer_list->active_timers; -} - bool qemu_clock_has_timers(QEMUClockType type) { return timerlist_has_timers( main_loop_tlg.tl[type]); } -bool timerlist_expired(QEMUTimerList *timer_list) -{ - int64_t expire_time; - - qemu_mutex_lock(&timer_list->active_timers_lock); - if (!timer_list->active_timers) { - qemu_mutex_unlock(&timer_list->active_timers_lock); - return false; - } - expire_time = timer_list->active_timers->expire_time; - qemu_mutex_unlock(&timer_list->active_timers_lock); - - return expire_time < qemu_clock_get_ns(timer_list->clock->type); -} - bool qemu_clock_expired(QEMUClockType type) { return timerlist_expired( main_loop_tlg.tl[type]); } -/* - * As above, but return -1 for no deadline, and do not cap to 2^32 - * as we know the result is always positive. - */ - -int64_t timerlist_deadline_ns(QEMUTimerList *timer_list) -{ - int64_t delta; - int64_t expire_time; - - if (!timer_list->clock->enabled) { - return -1; - } - - /* The active timers list may be modified before the caller uses our return - * value but ->notify_cb() is called when the deadline changes. Therefore - * the caller should notice the change and there is no race condition. - */ - qemu_mutex_lock(&timer_list->active_timers_lock); - if (!timer_list->active_timers) { - 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); - - delta = expire_time - qemu_clock_get_ns(timer_list->clock->type); - - if (delta <= 0) { - return 0; - } - - 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 @@ -254,25 +314,11 @@ int64_t qemu_clock_deadline_ns_all(QEMUClockType type) return deadline; } -QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list) -{ - return timer_list->clock->type; -} - QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type) { return main_loop_tlg.tl[type]; } -void timerlist_notify(QEMUTimerList *timer_list) -{ - if (timer_list->notify_cb) { - timer_list->notify_cb(timer_list->notify_opaque); - } else { - qemu_notify_event(); - } -} - /* Transition function to convert a nanosecond timeout to ms * This is used where a system does not support ppoll */ @@ -376,13 +422,6 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list, return pt == &timer_list->active_timers; } -static void timerlist_rearm(QEMUTimerList *timer_list) -{ - /* Interrupt execution to force deadline recalculation. */ - qemu_clock_warp(timer_list->clock->type); - timerlist_notify(timer_list); -} - /* stop a timer, but do not dealloc it */ void timer_del(QEMUTimer *ts) { @@ -454,46 +493,6 @@ bool timer_expired(QEMUTimer *timer_head, int64_t current_time) return timer_expired_ns(timer_head, current_time * timer_head->scale); } -bool timerlist_run_timers(QEMUTimerList *timer_list) -{ - QEMUTimer *ts; - int64_t current_time; - bool progress = false; - QEMUTimerCB *cb; - void *opaque; - - qemu_event_reset(&timer_list->timers_done_ev); - if (!timer_list->clock->enabled) { - goto out; - } - - current_time = qemu_clock_get_ns(timer_list->clock->type); - for(;;) { - qemu_mutex_lock(&timer_list->active_timers_lock); - ts = timer_list->active_timers; - if (!timer_expired_ns(ts, current_time)) { - qemu_mutex_unlock(&timer_list->active_timers_lock); - break; - } - - /* remove timer from the list before calling the callback */ - timer_list->active_timers = ts->next; - ts->next = NULL; - ts->expire_time = -1; - cb = ts->cb; - opaque = ts->opaque; - qemu_mutex_unlock(&timer_list->active_timers_lock); - - /* run the callback (the timer list can be modified) */ - cb(opaque); - progress = true; - } - -out: - qemu_event_set(&timer_list->timers_done_ev); - return progress; -} - bool qemu_clock_run_timers(QEMUClockType type) { return timerlist_run_timers(main_loop_tlg.tl[type]); -- 1.7.9.5