diff options
Diffstat (limited to 'monitor')
-rw-r--r-- | monitor/qmp.c | 27 |
1 files changed, 18 insertions, 9 deletions
diff --git a/monitor/qmp.c b/monitor/qmp.c index e6b1043c9f..c8e0156974 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -39,13 +39,16 @@ * coroutine never gets scheduled a second time when it's already * scheduled (scheduling the same coroutine twice is forbidden). * - * It is true if the coroutine is active and processing requests. - * Additional requests may then be pushed onto mon->qmp_requests, - * and @qmp_dispatcher_co_shutdown may be set without further ado. - * @qmp_dispatcher_co_busy must not be woken up in this case. + * It is true if the coroutine will process at least one more request + * before going to sleep. Either it has been kicked already, or it + * is active and processing requests. Additional requests may therefore + * be pushed onto mon->qmp_requests, and @qmp_dispatcher_co_shutdown may + * be set without further ado. @qmp_dispatcher_co must not be woken up + * in this case. * - * If false, you also have to set @qmp_dispatcher_co_busy to true and - * wake up @qmp_dispatcher_co after pushing the new requests. + * If false, you have to wake up @qmp_dispatcher_co after pushing new + * requests. You also have to set @qmp_dispatcher_co_busy to true + * before waking up the coroutine. * * The coroutine will automatically change this variable back to false * before it yields. Nobody else may set the variable to false. @@ -230,15 +233,18 @@ static QMPRequest *monitor_qmp_dispatcher_pop_any(void) { while (true) { /* - * busy must be set to true again by whoever - * rescheduled us to avoid double scheduling + * To avoid double scheduling, busy is true on entry to + * monitor_qmp_dispatcher_co(), and must be set again before + * aio_co_wake()-ing it. */ - assert(qatomic_mb_read(&qmp_dispatcher_co_busy) == true); + assert(qatomic_read(&qmp_dispatcher_co_busy) == true); /* * Mark the dispatcher as not busy already here so that we * don't miss any new requests coming in the middle of our * processing. + * + * Clear qmp_dispatcher_co_busy before reading request. */ qatomic_mb_set(&qmp_dispatcher_co_busy, false); @@ -364,6 +370,9 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data) void qmp_dispatcher_co_wake(void) { + /* Write request before reading qmp_dispatcher_co_busy. */ + smp_mb__before_rmw(); + if (!qatomic_xchg(&qmp_dispatcher_co_busy, true)) { aio_co_wake(qmp_dispatcher_co); } |