diff options
author | Peter Maydell | 2021-05-24 16:48:08 +0200 |
---|---|---|
committer | Peter Maydell | 2021-05-24 16:48:08 +0200 |
commit | 0dab1d36f55c3ed649bb8e4c74b9269ef3a63049 (patch) | |
tree | 212e624387db446a1bf062305e0851ccac18e4c5 /util/qemu-coroutine-sleep.c | |
parent | Merge remote-tracking branch 'remotes/xtensa/tags/20210521-xtensa' into staging (diff) | |
parent | coroutine-sleep: introduce qemu_co_sleep (diff) | |
download | qemu-0dab1d36f55c3ed649bb8e4c74b9269ef3a63049.tar.gz qemu-0dab1d36f55c3ed649bb8e4c74b9269ef3a63049.tar.xz qemu-0dab1d36f55c3ed649bb8e4c74b9269ef3a63049.zip |
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-request' into staging
Pull request
(Resent due to an email preparation mistake.)
# gpg: Signature made Mon 24 May 2021 14:01:42 BST
# gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full]
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8
* remotes/stefanha-gitlab/tags/block-pull-request:
coroutine-sleep: introduce qemu_co_sleep
coroutine-sleep: replace QemuCoSleepState pointer with struct in the API
coroutine-sleep: move timer out of QemuCoSleepState
coroutine-sleep: allow qemu_co_sleep_wake that wakes nothing
coroutine-sleep: disallow NULL QemuCoSleepState** argument
coroutine-sleep: use a stack-allocated timer
bitops.h: Improve find_xxx_bit() documentation
multi-process: Initialize variables declared with g_auto*
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'util/qemu-coroutine-sleep.c')
-rw-r--r-- | util/qemu-coroutine-sleep.c | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/util/qemu-coroutine-sleep.c b/util/qemu-coroutine-sleep.c index 8c4dac4fd7..571ab521ff 100644 --- a/util/qemu-coroutine-sleep.c +++ b/util/qemu-coroutine-sleep.c @@ -19,43 +19,34 @@ static const char *qemu_co_sleep_ns__scheduled = "qemu_co_sleep_ns"; -struct QemuCoSleepState { +void qemu_co_sleep_wake(QemuCoSleep *w) +{ Coroutine *co; - QEMUTimer *ts; - QemuCoSleepState **user_state_pointer; -}; -void qemu_co_sleep_wake(QemuCoSleepState *sleep_state) -{ - /* Write of schedule protected by barrier write in aio_co_schedule */ - const char *scheduled = qatomic_cmpxchg(&sleep_state->co->scheduled, - qemu_co_sleep_ns__scheduled, NULL); + co = w->to_wake; + w->to_wake = NULL; + if (co) { + /* Write of schedule protected by barrier write in aio_co_schedule */ + const char *scheduled = qatomic_cmpxchg(&co->scheduled, + qemu_co_sleep_ns__scheduled, NULL); - assert(scheduled == qemu_co_sleep_ns__scheduled); - if (sleep_state->user_state_pointer) { - *sleep_state->user_state_pointer = NULL; + assert(scheduled == qemu_co_sleep_ns__scheduled); + aio_co_wake(co); } - timer_del(sleep_state->ts); - aio_co_wake(sleep_state->co); } static void co_sleep_cb(void *opaque) { - qemu_co_sleep_wake(opaque); + QemuCoSleep *w = opaque; + qemu_co_sleep_wake(w); } -void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns, - QemuCoSleepState **sleep_state) +void coroutine_fn qemu_co_sleep(QemuCoSleep *w) { - AioContext *ctx = qemu_get_current_aio_context(); - QemuCoSleepState state = { - .co = qemu_coroutine_self(), - .ts = aio_timer_new(ctx, type, SCALE_NS, co_sleep_cb, &state), - .user_state_pointer = sleep_state, - }; + Coroutine *co = qemu_coroutine_self(); - const char *scheduled = qatomic_cmpxchg(&state.co->scheduled, NULL, - qemu_co_sleep_ns__scheduled); + const char *scheduled = qatomic_cmpxchg(&co->scheduled, NULL, + qemu_co_sleep_ns__scheduled); if (scheduled) { fprintf(stderr, "%s: Co-routine was already scheduled in '%s'\n", @@ -63,17 +54,27 @@ void coroutine_fn qemu_co_sleep_ns_wakeable(QEMUClockType type, int64_t ns, abort(); } - if (sleep_state) { - *sleep_state = &state; - } - timer_mod(state.ts, qemu_clock_get_ns(type) + ns); + w->to_wake = co; qemu_coroutine_yield(); - if (sleep_state) { - /* - * Note that *sleep_state is cleared during qemu_co_sleep_wake - * before resuming this coroutine. - */ - assert(*sleep_state == NULL); - } - timer_free(state.ts); + + /* w->to_wake is cleared before resuming this coroutine. */ + assert(w->to_wake == NULL); +} + +void coroutine_fn qemu_co_sleep_ns_wakeable(QemuCoSleep *w, + QEMUClockType type, int64_t ns) +{ + AioContext *ctx = qemu_get_current_aio_context(); + QEMUTimer ts; + + aio_timer_init(ctx, &ts, type, SCALE_NS, co_sleep_cb, w); + timer_mod(&ts, qemu_clock_get_ns(type) + ns); + + /* + * The timer will fire in the current AiOContext, so the callback + * must happen after qemu_co_sleep yields and there is no race + * between timer_mod and qemu_co_sleep. + */ + qemu_co_sleep(w); + timer_del(&ts); } |