On 09/19/2012 12:51 PM, Paolo Bonzini wrote:
> Il 19/09/2012 11:21, Avi Kivity ha scritto:
>>> > I don't know if the front-end (device) lock should come before or after
>>> > the back-end (e.g. netdev) lock in the hierarchy, but that's another
>>> > story.
>> I would say device -> backend. It's natural if the backend is the timer
>> subsystem, so extend it from there to the block and network layers. Of
>> course callbacks want it to be the other way round.
>
> Yes, that's what I wasn't sure about. In many cases I believe callbacks
> can just release the backend lock. It works for timers, for example:
>
> for(;;) {
> ts = clock->active_timers;
> if (!qemu_timer_expired_ns(ts, current_time)) {
> break;
> }
> /* remove timer from the list before calling the callback */
> clock->active_timers = ts->next;
> ts->next = NULL;
>
> /* run the callback (the timer list can be modified) */
> - ts->cb(ts->opaque);
> + cb = ts->cb;
> + opaque = ts->opaque;
> + unlock();
> + cb(opaque);
> + lock();
> }
>
> (The hunch is that ts could be deleted exactly at the moment the
> callback is unlocked. This can be solved with ref/unref on the opaque
> value, as you mention below).
Are you saying that this works as is or not? It does seem broken wrt
deletion; after qemu_del_timer() completes the caller expects the
callback not to be called.
This isn't trivial to guarantee, we need something like
dispatch_timer():
pending += 1
timer.ref()
drop lock
timer.cb()
take lock
timer.unref()
pending -= 1
notify
del_timer():
take lock
timer.unlink()
while pending:
wait for notification
drop lock
but, if del_timer is called with the device lock held, we deadlock. ugh.
--
error compiling committee.c: too many arguments to function