aio / timers: Add a notify callback to QEMUTimerList

Add a notify pointer to QEMUTimerList so it knows what to notify
on a timer change.

Signed-off-by: Alex Bligh <alex@alex.org.uk>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Alex Bligh 2013-08-21 16:02:50 +01:00 committed by Stefan Hajnoczi
parent dae21b98b9
commit d5541d8680
3 changed files with 52 additions and 11 deletions

View File

@ -234,6 +234,11 @@ void aio_notify(AioContext *ctx)
event_notifier_set(&ctx->notifier); event_notifier_set(&ctx->notifier);
} }
static void aio_timerlist_notify(void *opaque)
{
aio_notify(opaque);
}
AioContext *aio_context_new(void) AioContext *aio_context_new(void)
{ {
AioContext *ctx; AioContext *ctx;
@ -245,7 +250,7 @@ AioContext *aio_context_new(void)
aio_set_event_notifier(ctx, &ctx->notifier, aio_set_event_notifier(ctx, &ctx->notifier,
(EventNotifierHandler *) (EventNotifierHandler *)
event_notifier_test_and_clear); event_notifier_test_and_clear);
timerlistgroup_init(&ctx->tlg); timerlistgroup_init(&ctx->tlg, aio_timerlist_notify, ctx);
return ctx; return ctx;
} }

View File

@ -59,6 +59,7 @@ struct QEMUTimerListGroup {
}; };
typedef void QEMUTimerCB(void *opaque); typedef void QEMUTimerCB(void *opaque);
typedef void QEMUTimerListNotifyCB(void *opaque);
struct QEMUTimer { struct QEMUTimer {
int64_t expire_time; /* in nanoseconds */ int64_t expire_time; /* in nanoseconds */
@ -137,13 +138,16 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock);
/** /**
* timerlist_new: * timerlist_new:
* @type: the clock type to associate with the timerlist * @type: the clock type to associate with the timerlist
* @cb: the callback to call on notification
* @opaque: the opaque pointer to pass to the callback
* *
* Create a new timerlist associated with the clock of * Create a new timerlist associated with the clock of
* type @type. * type @type.
* *
* Returns: a pointer to the QEMUTimerList created * Returns: a pointer to the QEMUTimerList created
*/ */
QEMUTimerList *timerlist_new(QEMUClockType type); QEMUTimerList *timerlist_new(QEMUClockType type,
QEMUTimerListNotifyCB *cb, void *opaque);
/** /**
* timerlist_free: * timerlist_free:
@ -223,14 +227,29 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list);
*/ */
bool timerlist_run_timers(QEMUTimerList *timer_list); bool timerlist_run_timers(QEMUTimerList *timer_list);
/**
* timerlist_notify:
* @timer_list: the timer list to use
*
* call the notifier callback associated with the timer list.
*/
void timerlist_notify(QEMUTimerList *timer_list);
/** /**
* timerlistgroup_init: * timerlistgroup_init:
* @tlg: the timer list group * @tlg: the timer list group
* @cb: the callback to call when a notify is required
* @opaque: the opaque pointer to be passed to the callback.
* *
* Initialise a timer list group. This must already be * Initialise a timer list group. This must already be
* allocated in memory and zeroed. * allocated in memory and zeroed. The notifier callback is
* called whenever a clock in the timer list group is
* reenabled or whenever a timer associated with any timer
* list is modified. If @cb is specified as null, qemu_notify()
* is used instead.
*/ */
void timerlistgroup_init(QEMUTimerListGroup *tlg); void timerlistgroup_init(QEMUTimerListGroup *tlg,
QEMUTimerListNotifyCB *cb, void *opaque);
/** /**
* timerlistgroup_deinit: * timerlistgroup_deinit:

View File

@ -73,6 +73,8 @@ struct QEMUTimerList {
QEMUClock *clock; QEMUClock *clock;
QEMUTimer *active_timers; QEMUTimer *active_timers;
QLIST_ENTRY(QEMUTimerList) list; QLIST_ENTRY(QEMUTimerList) list;
QEMUTimerListNotifyCB *notify_cb;
void *notify_opaque;
}; };
struct qemu_alarm_timer { struct qemu_alarm_timer {
@ -243,7 +245,9 @@ next:
} }
} }
static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock) static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock,
QEMUTimerListNotifyCB *cb,
void *opaque)
{ {
QEMUTimerList *timer_list; QEMUTimerList *timer_list;
@ -257,13 +261,16 @@ static QEMUTimerList *timerlist_new_from_clock(QEMUClock *clock)
timer_list = g_malloc0(sizeof(QEMUTimerList)); timer_list = g_malloc0(sizeof(QEMUTimerList));
timer_list->clock = clock; timer_list->clock = clock;
timer_list->notify_cb = cb;
timer_list->notify_opaque = opaque;
QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list); QLIST_INSERT_HEAD(&clock->timerlists, timer_list, list);
return timer_list; return timer_list;
} }
QEMUTimerList *timerlist_new(QEMUClockType type) QEMUTimerList *timerlist_new(QEMUClockType type,
QEMUTimerListNotifyCB *cb, void *opaque)
{ {
return timerlist_new_from_clock(qemu_clock_ptr(type)); return timerlist_new_from_clock(qemu_clock_ptr(type), cb, opaque);
} }
void timerlist_free(QEMUTimerList *timer_list) void timerlist_free(QEMUTimerList *timer_list)
@ -288,7 +295,7 @@ static QEMUClock *qemu_clock_new(QEMUClockType type)
clock->last = INT64_MIN; clock->last = INT64_MIN;
QLIST_INIT(&clock->timerlists); QLIST_INIT(&clock->timerlists);
notifier_list_init(&clock->reset_notifiers); notifier_list_init(&clock->reset_notifiers);
clock->main_loop_timerlist = timerlist_new_from_clock(clock); clock->main_loop_timerlist = timerlist_new_from_clock(clock, NULL, NULL);
return clock; return clock;
} }
@ -386,6 +393,15 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock)
return clock->main_loop_timerlist; return clock->main_loop_timerlist;
} }
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 /* Transition function to convert a nanosecond timeout to ms
* This is used where a system does not support ppoll * This is used where a system does not support ppoll
*/ */
@ -507,7 +523,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time)
/* Interrupt execution to force deadline recalculation. */ /* Interrupt execution to force deadline recalculation. */
qemu_clock_warp(ts->timer_list->clock); qemu_clock_warp(ts->timer_list->clock);
if (use_icount) { if (use_icount) {
qemu_notify_event(); timerlist_notify(ts->timer_list);
} }
} }
} }
@ -565,11 +581,12 @@ bool qemu_run_timers(QEMUClock *clock)
return timerlist_run_timers(clock->main_loop_timerlist); return timerlist_run_timers(clock->main_loop_timerlist);
} }
void timerlistgroup_init(QEMUTimerListGroup *tlg) void timerlistgroup_init(QEMUTimerListGroup *tlg,
QEMUTimerListNotifyCB *cb, void *opaque)
{ {
QEMUClockType type; QEMUClockType type;
for (type = 0; type < QEMU_CLOCK_MAX; type++) { for (type = 0; type < QEMU_CLOCK_MAX; type++) {
tlg->tl[type] = timerlist_new(type); tlg->tl[type] = timerlist_new(type, cb, opaque);
} }
} }