mirror of https://github.com/xemu-project/xemu.git
qemu-timer: check active_timers outside lock/event
This avoids taking the active_timers_lock or resetting/setting the timers_done_ev if there are no active timers. This removes a small (2-3%) source of overhead for dataplane. The list is then checked again inside the lock, or a NULL pointer could be dereferenced. Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
e7a9f35321
commit
8caa05d889
20
qemu-timer.c
20
qemu-timer.c
|
@ -174,7 +174,7 @@ void qemu_clock_enable(QEMUClockType type, bool enabled)
|
||||||
|
|
||||||
bool timerlist_has_timers(QEMUTimerList *timer_list)
|
bool timerlist_has_timers(QEMUTimerList *timer_list)
|
||||||
{
|
{
|
||||||
return !!timer_list->active_timers;
|
return !!atomic_read(&timer_list->active_timers);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool qemu_clock_has_timers(QEMUClockType type)
|
bool qemu_clock_has_timers(QEMUClockType type)
|
||||||
|
@ -187,6 +187,10 @@ bool timerlist_expired(QEMUTimerList *timer_list)
|
||||||
{
|
{
|
||||||
int64_t expire_time;
|
int64_t expire_time;
|
||||||
|
|
||||||
|
if (!atomic_read(&timer_list->active_timers)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_mutex_lock(&timer_list->active_timers_lock);
|
qemu_mutex_lock(&timer_list->active_timers_lock);
|
||||||
if (!timer_list->active_timers) {
|
if (!timer_list->active_timers) {
|
||||||
qemu_mutex_unlock(&timer_list->active_timers_lock);
|
qemu_mutex_unlock(&timer_list->active_timers_lock);
|
||||||
|
@ -214,6 +218,10 @@ int64_t timerlist_deadline_ns(QEMUTimerList *timer_list)
|
||||||
int64_t delta;
|
int64_t delta;
|
||||||
int64_t expire_time;
|
int64_t expire_time;
|
||||||
|
|
||||||
|
if (!atomic_read(&timer_list->active_timers)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!timer_list->clock->enabled) {
|
if (!timer_list->clock->enabled) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -363,7 +371,7 @@ static void timer_del_locked(QEMUTimerList *timer_list, QEMUTimer *ts)
|
||||||
if (!t)
|
if (!t)
|
||||||
break;
|
break;
|
||||||
if (t == ts) {
|
if (t == ts) {
|
||||||
*pt = t->next;
|
atomic_set(pt, t->next);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pt = &t->next;
|
pt = &t->next;
|
||||||
|
@ -386,7 +394,7 @@ static bool timer_mod_ns_locked(QEMUTimerList *timer_list,
|
||||||
}
|
}
|
||||||
ts->expire_time = MAX(expire_time, 0);
|
ts->expire_time = MAX(expire_time, 0);
|
||||||
ts->next = *pt;
|
ts->next = *pt;
|
||||||
*pt = ts;
|
atomic_set(pt, ts);
|
||||||
|
|
||||||
return pt == &timer_list->active_timers;
|
return pt == &timer_list->active_timers;
|
||||||
}
|
}
|
||||||
|
@ -481,8 +489,12 @@ bool timerlist_run_timers(QEMUTimerList *timer_list)
|
||||||
QEMUTimerCB *cb;
|
QEMUTimerCB *cb;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
|
||||||
|
if (!atomic_read(&timer_list->active_timers)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
qemu_event_reset(&timer_list->timers_done_ev);
|
qemu_event_reset(&timer_list->timers_done_ev);
|
||||||
if (!timer_list->clock->enabled || !timer_list->active_timers) {
|
if (!timer_list->clock->enabled) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue