From 0421b563ab4d947a388078331c057daa9b979f41 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 13 Oct 2022 14:58:56 -0400 Subject: coroutine: add flag to re-queue at front of CoQueue When a coroutine wakes up it may determine that it must re-queue. Normally coroutines are pushed onto the back of the CoQueue, but for fairness it may be necessary to push it onto the front of the CoQueue. Add a flag to specify that the coroutine should be pushed onto the front of the CoQueue. A later patch will use this to ensure fairness in the bounce buffer CoQueue used by the blkio BlockDriver. Signed-off-by: Stefan Hajnoczi Message-id: 20221013185908.1297568-2-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi --- include/qemu/coroutine.h | 15 +++++++++++++-- util/qemu-coroutine-lock.c | 9 +++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index aae33cce17..608fe45dcf 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -198,14 +198,25 @@ typedef struct CoQueue { */ void qemu_co_queue_init(CoQueue *queue); +typedef enum { + /* + * Enqueue at front instead of back. Use this to re-queue a request when + * its wait condition is not satisfied after being woken up. + */ + CO_QUEUE_WAIT_FRONT = 0x1, +} CoQueueWaitFlags; + /** * Adds the current coroutine to the CoQueue and transfers control to the * caller of the coroutine. The mutex is unlocked during the wait and * locked again afterwards. */ #define qemu_co_queue_wait(queue, lock) \ - qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock)) -void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock); + qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), 0) +#define qemu_co_queue_wait_flags(queue, lock, flags) \ + qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), (flags)) +void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock, + CoQueueWaitFlags flags); /** * Removes the next coroutine from the CoQueue, and queue it to run after diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index 15c82d9348..45c6b57374 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -39,10 +39,15 @@ void qemu_co_queue_init(CoQueue *queue) QSIMPLEQ_INIT(&queue->entries); } -void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock) +void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock, + CoQueueWaitFlags flags) { Coroutine *self = qemu_coroutine_self(); - QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next); + if (flags & CO_QUEUE_WAIT_FRONT) { + QSIMPLEQ_INSERT_HEAD(&queue->entries, self, co_queue_next); + } else { + QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next); + } if (lock) { qemu_lockable_unlock(lock); -- cgit v1.2.3