block-coroutine-wrapper¶
A lot of functions in QEMU block layer (see block/*
) can only be
called in coroutine context. Such functions are normally marked by the
coroutine_fn specifier. Still, sometimes we need to call them from
non-coroutine context; for this we need to start a coroutine, run the
needed function from it and wait for the coroutine to finish in a
BDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
void* argument. So for each coroutine_fn function which needs a
non-coroutine interface, we should define a structure to pack the
parameters, define a separate function to unpack the parameters and
call the original function and finally define a new interface function
with same list of arguments as original one, which will pack the
parameters into a struct, create a coroutine, run it and wait in
BDRV_POLL_WHILE() loop. It’s boring to create such wrappers by hand,
so we have a script to generate them.
Usage¶
Assume we have defined the coroutine_fn
function
bdrv_co_foo(<some args>)
and need a non-coroutine interface for it,
called bdrv_foo(<same args>)
. In this case the script can help. To
trigger the generation:
- You need
bdrv_foo
declaration somewhere (for example, inblock/coroutines.h
) with thegenerated_co_wrapper
mark, like this:
int generated_co_wrapper bdrv_foo(<some args>);
- You need to feed this declaration to block-coroutine-wrapper script.
For this, add the .h (or .c) file with the declaration to the
input: files(...)
list ofblock_gen_c
target declaration inblock/meson.build
You are done. During the build, coroutine wrappers will be generated in
<BUILD_DIR>/block/block-gen.c
.
Links¶
- The script location is
scripts/block-coroutine-wrapper.py
. - Generic place for private
generated_co_wrapper
declarations isblock/coroutines.h
, for public declarations:include/block/block.h
- The core API of generated coroutine wrappers is placed in
(not generated)
block/block-gen.h