QEMU coroutine implementation

The documentation for the header qemu/coroutine.h.

coroutine_fn()

Parameters

Description

cooperative userspace threading. These functions provide a simple but useful flavor of coroutines that is suitable for writing sequential code, rather than callbacks, for operations that need to give up control while waiting for events to complete.

These functions are re-entrant and may be used outside the global mutex.

typedef void coroutine_fn CoroutineEntry(void * opaque)

Parameters

void * opaque
undescribed

Description

When the coroutine is entered for the first time, opaque is passed in as an argument.

When this function returns, the coroutine is destroyed automatically and execution continues in the caller who last entered the coroutine.

Coroutine * qemu_coroutine_create(CoroutineEntry * entry, void * opaque)

Parameters

CoroutineEntry * entry
undescribed
void * opaque
undescribed

Description

Use qemu_coroutine_enter() to actually transfer control to the coroutine. The opaque argument is passed as the argument to the entry point.

void qemu_coroutine_enter(Coroutine * coroutine)

Parameters

Coroutine * coroutine
undescribed
void qemu_coroutine_enter_if_inactive(Coroutine * co)

Parameters

Coroutine * co
undescribed

Description

stack of the running coroutine). Otherwise, do nothing.

void qemu_aio_coroutine_enter(AioContext * ctx, Coroutine * co)

Parameters

AioContext * ctx
undescribed
Coroutine * co
undescribed
void coroutine_fn qemu_coroutine_yield(void)

Parameters

void
no arguments

Description

This function does not return until the coroutine is re-entered using qemu_coroutine_enter().

bool qemu_in_coroutine(void)

Parameters

void
no arguments

Description

This can be used to write functions that work both when in coroutine context and when not in coroutine context. Note that such functions cannot use the coroutine_fn annotation since they work outside coroutine context.

bool qemu_coroutine_entered(Coroutine * co)

Parameters

Coroutine * co
undescribed

Description

A coroutine is “entered” if it has not yielded from the current qemu_coroutine_enter() call used to run it. This does not mean that the coroutine is currently executing code since it may have transferred control to another coroutine using qemu_coroutine_enter().

When several coroutines enter each other there may be no way to know which ones have already been entered. In such situations this function can be used to avoid recursively entering coroutines.

void qemu_co_mutex_init(CoMutex * mutex)

Parameters

CoMutex * mutex
undescribed

Description

on the CoMutex.

void coroutine_fn qemu_co_mutex_lock(CoMutex * mutex)

Parameters

CoMutex * mutex
undescribed

Description

transferred to the caller of the current coroutine.

void coroutine_fn qemu_co_mutex_unlock(CoMutex * mutex)

Parameters

CoMutex * mutex
undescribed

Description

lock to be run.

void qemu_co_queue_init(CoQueue * queue)

Parameters

CoQueue * queue
undescribed

Description

on the CoQueue.

qemu_co_queue_wait(queue, lock)

Parameters

queue
undescribed
lock
undescribed

Description

caller of the coroutine. The mutex is unlocked during the wait and locked again afterwards.

bool coroutine_fn qemu_co_queue_next(CoQueue * queue)

Parameters

CoQueue * queue
undescribed

Description

Returns true if a coroutine was removed, false if the queue is empty.

void coroutine_fn qemu_co_queue_restart_all(CoQueue * queue)

Parameters

CoQueue * queue
undescribed
qemu_co_enter_next(queue, lock)

Parameters

queue
undescribed
lock
undescribed

Description

qemu_co_queue_next, this function releases the lock during aio_co_wake because it is meant to be used outside coroutine context; in that case, the coroutine is entered immediately, before qemu_co_enter_next returns.

If used in coroutine context, qemu_co_enter_next is equivalent to qemu_co_queue_next.

bool qemu_co_queue_empty(CoQueue * queue)

Parameters

CoQueue * queue
undescribed
void qemu_co_rwlock_init(CoRwlock * lock)

Parameters

CoRwlock * lock
undescribed

Description

is used on the CoRwlock

void qemu_co_rwlock_rdlock(CoRwlock * lock)

Parameters

CoRwlock * lock
undescribed

Description

of a parallel writer, control is transferred to the caller of the current coroutine.

void qemu_co_rwlock_upgrade(CoRwlock * lock)

Parameters

CoRwlock * lock
undescribed

Description

qemu_co_rwlock_unlock followed by a separate qemu_co_rwlock_wrlock. However, if the lock cannot be upgraded immediately, control is transferred to the caller of the current coroutine. Also, qemu_co_rwlock_upgrade only overrides CoRwlock fairness if there are no concurrent readers, so another writer might run while qemu_co_rwlock_upgrade blocks.

void qemu_co_rwlock_downgrade(CoRwlock * lock)

side critical section to a reader. Downgrading with qemu_co_rwlock_downgrade never blocks, unlike qemu_co_rwlock_unlock followed by qemu_co_rwlock_rdlock. This makes it more efficient, but may also sometimes be necessary for correctness.

Parameters

CoRwlock * lock
undescribed
void qemu_co_rwlock_wrlock(CoRwlock * lock)

Parameters

CoRwlock * lock
undescribed

Description

of a parallel reader, control is transferred to the caller of the current coroutine.

void qemu_co_rwlock_unlock(CoRwlock * lock)

Parameters

CoRwlock * lock
undescribed

Description

waiting for this lock to be run.

void coroutine_fn qemu_co_sleep_ns(QEMUClockType type, int64_t ns)

Parameters

QEMUClockType type
undescribed
int64_t ns
undescribed
void coroutine_fn yield_until_fd_readable(int fd)

Parameters

int fd
undescribed

Description

Note that this function clobbers the handlers for the file descriptor.