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 <stefanha@redhat.com> Message-id: 20221013185908.1297568-2-stefanha@redhat.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
79fc2fb685
commit
0421b563ab
@ -198,14 +198,25 @@ typedef struct CoQueue {
|
|||||||
*/
|
*/
|
||||||
void qemu_co_queue_init(CoQueue *queue);
|
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
|
* Adds the current coroutine to the CoQueue and transfers control to the
|
||||||
* caller of the coroutine. The mutex is unlocked during the wait and
|
* caller of the coroutine. The mutex is unlocked during the wait and
|
||||||
* locked again afterwards.
|
* locked again afterwards.
|
||||||
*/
|
*/
|
||||||
#define qemu_co_queue_wait(queue, lock) \
|
#define qemu_co_queue_wait(queue, lock) \
|
||||||
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock))
|
qemu_co_queue_wait_impl(queue, QEMU_MAKE_LOCKABLE(lock), 0)
|
||||||
void coroutine_fn qemu_co_queue_wait_impl(CoQueue *queue, QemuLockable *lock);
|
#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
|
* Removes the next coroutine from the CoQueue, and queue it to run after
|
||||||
|
@ -39,10 +39,15 @@ void qemu_co_queue_init(CoQueue *queue)
|
|||||||
QSIMPLEQ_INIT(&queue->entries);
|
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();
|
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) {
|
if (lock) {
|
||||||
qemu_lockable_unlock(lock);
|
qemu_lockable_unlock(lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user