On 05/08/20 12:00, Stefan Hajnoczi wrote: > + > + /* > + * aio_notify can avoid the expensive event_notifier_set if > + * everything (file descriptors, bottom halves, timers) will > + * be re-evaluated before the next blocking poll(). This is > + * already true when aio_poll is called with blocking == false; > + * if blocking == true, it is only true after poll() returns, > + * so disable the optimization now. > + */ > + if (use_notify_me) { > + atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); > + /* > + * Write ctx->notify_me before reading ctx->notified. Pairs with > + * smp_mb in aio_notify(). > + */ > + smp_mb(); > + > + /* Don't block if aio_notify() was called */ > + if (atomic_read(&ctx->notified)) { > + timeout = 0; > + }
Aha, this is the trick: "timeout = 0" also applies if a timer was moved early. In this case you uselessly keep notify_me set for a bit, but it's okay. Nice! The code can be simplified a bit more, since the use_notify_me variable is just "timeout": use_notify_me = (timeout != 0); if (use_notify_me) { /* * aio_notify can avoid the expensive event_notifier_set if * everything (file descriptors, bottom halves, timers) will * be re-evaluated before the next blocking poll(). This is * already true when aio_poll is called with blocking == false; * if blocking == true, it is only true after poll() returns, * so disable the optimization now. */ atomic_set(&ctx->notify_me, atomic_read(&ctx->notify_me) + 2); /* * Write ctx->notify_me before reading ctx->notified. Pairs with * smp_mb in aio_notify(). */ smp_mb(); /* Don't block if aio_notify() was called */ if (atomic_read(&ctx->notified)) { timeout = 0; } } if (timeout || ctx->fdmon_ops->need_wait(ctx)) { ret = ctx->fdmon_ops->wait(ctx, &ready_list, timeout); } if (use_notify_me) { /* Finish the poll before clearing the flag. */ atomic_store_release(&ctx->notify_me, atomic_read(&ctx->notify_me) - 2); } Paolo