Message ID | 1375998147-24292-12-git-send-email-alex@alex.org.uk |
---|---|
State | New |
Headers | show |
Il 08/08/2013 23:42, Alex Bligh ha scritto: > Add a notify pointer to QEMUTimerList so it knows what to notify > on a timer change. If we do the "two AioContexts" trick, this can simply be a back-pointer to the AioContext. Paolo > Signed-off-by: Alex Bligh <alex@alex.org.uk> > --- > async.c | 7 ++++++- > include/qemu/timer.h | 35 ++++++++++++++++++++++++++++++++--- > qemu-timer.c | 24 ++++++++++++++++++++++-- > 3 files changed, 60 insertions(+), 6 deletions(-) > > diff --git a/async.c b/async.c > index 99fb5a8..2051921 100644 > --- a/async.c > +++ b/async.c > @@ -234,6 +234,11 @@ void aio_notify(AioContext *ctx) > event_notifier_set(&ctx->notifier); > } > > +static void aio_timerlist_notify(void *opaque) > +{ > + aio_notify(opaque); > +} > + > AioContext *aio_context_new(void) > { > AioContext *ctx; > @@ -245,7 +250,7 @@ AioContext *aio_context_new(void) > aio_set_event_notifier(ctx, &ctx->notifier, > (EventNotifierHandler *) > event_notifier_test_and_clear, NULL); > - timerlistgroup_init(ctx->tlg); > + timerlistgroup_init(ctx->tlg, aio_timerlist_notify, ctx); > > return ctx; > } > diff --git a/include/qemu/timer.h b/include/qemu/timer.h > index 3b46f60..07e6d9e 100644 > --- a/include/qemu/timer.h > +++ b/include/qemu/timer.h > @@ -54,6 +54,7 @@ typedef struct QEMUClock QEMUClock; > typedef struct QEMUTimerList QEMUTimerList; > typedef QEMUTimerList *QEMUTimerListGroup[QEMU_CLOCK_MAX]; > typedef void QEMUTimerCB(void *opaque); > +typedef void QEMUTimerListNotifyCB(void *opaque); > > extern QEMUTimerListGroup main_loop_tlg; > extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX]; > @@ -213,13 +214,41 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list); > bool timerlist_run_timers(QEMUTimerList *timer_list); > > /** > + * timerlist_set_notify_cb: > + * @timer_list: the timer list to use > + * @cb: the callback to call on notification > + * @opaque: the opaque pointer to pass to the callback > + * > + * Set the notify callback for a timer list. The notifier > + * callback is called when the clock is reenabled or a timer > + * on the list is modified. > + */ > +void timerlist_set_notify_cb(QEMUTimerList *timer_list, > + QEMUTimerListNotifyCB *cb, void *opaque); > + > +/** > + * 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: > * @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 > - * allocated in memory and zeroed. > - */ > -void timerlistgroup_init(QEMUTimerListGroup tlg); > + * 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, > + QEMUTimerListNotifyCB *cb, void *opaque); > > /** > * timerlistgroup_deinit: > diff --git a/qemu-timer.c b/qemu-timer.c > index e151d24..14cb433 100644 > --- a/qemu-timer.c > +++ b/qemu-timer.c > @@ -73,6 +73,8 @@ struct QEMUTimerList { > QEMUClock *clock; > QEMUTimer *active_timers; > QLIST_ENTRY(QEMUTimerList) list; > + QEMUTimerListNotifyCB *notify_cb; > + void *notify_opaque; > }; > > struct QEMUTimer { > @@ -394,6 +396,22 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock) > return clock->main_loop_timerlist; > } > > +void timerlist_set_notify_cb(QEMUTimerList *timer_list, > + QEMUTimerListNotifyCB *cb, void *opaque) > +{ > + timer_list->notify_cb = cb; > + timer_list->notify_opaque = opaque; > +} > + > +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 > */ > @@ -518,7 +536,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) > /* Interrupt execution to force deadline recalculation. */ > qemu_clock_warp(ts->timer_list->clock); > if (use_icount) { > - qemu_notify_event(); > + timerlist_notify(ts->timer_list); > } > } > } > @@ -576,11 +594,13 @@ bool qemu_run_timers(QEMUClock *clock) > return timerlist_run_timers(clock->main_loop_timerlist); > } > > -void timerlistgroup_init(QEMUTimerListGroup tlg) > +void timerlistgroup_init(QEMUTimerListGroup tlg, > + QEMUTimerListNotifyCB *cb, void *opaque) > { > QEMUClockType type; > for (type = 0; type < QEMU_CLOCK_MAX; type++) { > tlg[type] = timerlist_new(type); > + timerlist_set_notify_cb(tlg[type], cb, opaque); > } > } > >
On 9 Aug 2013, at 11:03, Paolo Bonzini wrote: > Il 08/08/2013 23:42, Alex Bligh ha scritto: >> Add a notify pointer to QEMUTimerList so it knows what to notify >> on a timer change. > > If we do the "two AioContexts" trick, this can simply be a back-pointer > to the AioContext. Well this would assume that NOTHING other than an AioContext would ever want its own timers. Suppose we want a thread which has no need of an AioContext?
Paolo, On 9 Aug 2013, at 11:03, Paolo Bonzini wrote: > Il 08/08/2013 23:42, Alex Bligh ha scritto: >> Add a notify pointer to QEMUTimerList so it knows what to notify >> on a timer change. > > If we do the "two AioContexts" trick, this can simply be a back-pointer > to the AioContext. Actually this isn't right. All the timer lists associated with normal AioContexts need to call aio_notify() (or use the callback) but the timer list associated with the dummy AioContext needs to call qemu_notify. This makes the trick a bit uglier. I'll do a v2 of my demo patch for this.
diff --git a/async.c b/async.c index 99fb5a8..2051921 100644 --- a/async.c +++ b/async.c @@ -234,6 +234,11 @@ void aio_notify(AioContext *ctx) event_notifier_set(&ctx->notifier); } +static void aio_timerlist_notify(void *opaque) +{ + aio_notify(opaque); +} + AioContext *aio_context_new(void) { AioContext *ctx; @@ -245,7 +250,7 @@ AioContext *aio_context_new(void) aio_set_event_notifier(ctx, &ctx->notifier, (EventNotifierHandler *) event_notifier_test_and_clear, NULL); - timerlistgroup_init(ctx->tlg); + timerlistgroup_init(ctx->tlg, aio_timerlist_notify, ctx); return ctx; } diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 3b46f60..07e6d9e 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -54,6 +54,7 @@ typedef struct QEMUClock QEMUClock; typedef struct QEMUTimerList QEMUTimerList; typedef QEMUTimerList *QEMUTimerListGroup[QEMU_CLOCK_MAX]; typedef void QEMUTimerCB(void *opaque); +typedef void QEMUTimerListNotifyCB(void *opaque); extern QEMUTimerListGroup main_loop_tlg; extern QEMUClock *qemu_clocks[QEMU_CLOCK_MAX]; @@ -213,13 +214,41 @@ QEMUClock *timerlist_get_clock(QEMUTimerList *timer_list); bool timerlist_run_timers(QEMUTimerList *timer_list); /** + * timerlist_set_notify_cb: + * @timer_list: the timer list to use + * @cb: the callback to call on notification + * @opaque: the opaque pointer to pass to the callback + * + * Set the notify callback for a timer list. The notifier + * callback is called when the clock is reenabled or a timer + * on the list is modified. + */ +void timerlist_set_notify_cb(QEMUTimerList *timer_list, + QEMUTimerListNotifyCB *cb, void *opaque); + +/** + * 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: * @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 - * allocated in memory and zeroed. - */ -void timerlistgroup_init(QEMUTimerListGroup tlg); + * 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, + QEMUTimerListNotifyCB *cb, void *opaque); /** * timerlistgroup_deinit: diff --git a/qemu-timer.c b/qemu-timer.c index e151d24..14cb433 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -73,6 +73,8 @@ struct QEMUTimerList { QEMUClock *clock; QEMUTimer *active_timers; QLIST_ENTRY(QEMUTimerList) list; + QEMUTimerListNotifyCB *notify_cb; + void *notify_opaque; }; struct QEMUTimer { @@ -394,6 +396,22 @@ QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClock *clock) return clock->main_loop_timerlist; } +void timerlist_set_notify_cb(QEMUTimerList *timer_list, + QEMUTimerListNotifyCB *cb, void *opaque) +{ + timer_list->notify_cb = cb; + timer_list->notify_opaque = opaque; +} + +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 */ @@ -518,7 +536,7 @@ void qemu_mod_timer_ns(QEMUTimer *ts, int64_t expire_time) /* Interrupt execution to force deadline recalculation. */ qemu_clock_warp(ts->timer_list->clock); if (use_icount) { - qemu_notify_event(); + timerlist_notify(ts->timer_list); } } } @@ -576,11 +594,13 @@ bool qemu_run_timers(QEMUClock *clock) return timerlist_run_timers(clock->main_loop_timerlist); } -void timerlistgroup_init(QEMUTimerListGroup tlg) +void timerlistgroup_init(QEMUTimerListGroup tlg, + QEMUTimerListNotifyCB *cb, void *opaque) { QEMUClockType type; for (type = 0; type < QEMU_CLOCK_MAX; type++) { tlg[type] = timerlist_new(type); + timerlist_set_notify_cb(tlg[type], cb, opaque); } }
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> --- async.c | 7 ++++++- include/qemu/timer.h | 35 ++++++++++++++++++++++++++++++++--- qemu-timer.c | 24 ++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 6 deletions(-)