xref: /qemu/docs/devel/block-coroutine-wrapper.rst (revision aaaa20b69b93c961ed8064c553a3577f8c072982)
1*aaaa20b6SVladimir Sementsov-Ogievskiy=======================
2*aaaa20b6SVladimir Sementsov-Ogievskiyblock-coroutine-wrapper
3*aaaa20b6SVladimir Sementsov-Ogievskiy=======================
4*aaaa20b6SVladimir Sementsov-Ogievskiy
5*aaaa20b6SVladimir Sementsov-OgievskiyA lot of functions in QEMU block layer (see ``block/*``) can only be
6*aaaa20b6SVladimir Sementsov-Ogievskiycalled in coroutine context. Such functions are normally marked by the
7*aaaa20b6SVladimir Sementsov-Ogievskiycoroutine_fn specifier. Still, sometimes we need to call them from
8*aaaa20b6SVladimir Sementsov-Ogievskiynon-coroutine context; for this we need to start a coroutine, run the
9*aaaa20b6SVladimir Sementsov-Ogievskiyneeded function from it and wait for the coroutine to finish in a
10*aaaa20b6SVladimir Sementsov-OgievskiyBDRV_POLL_WHILE() loop. To run a coroutine we need a function with one
11*aaaa20b6SVladimir Sementsov-Ogievskiyvoid* argument. So for each coroutine_fn function which needs a
12*aaaa20b6SVladimir Sementsov-Ogievskiynon-coroutine interface, we should define a structure to pack the
13*aaaa20b6SVladimir Sementsov-Ogievskiyparameters, define a separate function to unpack the parameters and
14*aaaa20b6SVladimir Sementsov-Ogievskiycall the original function and finally define a new interface function
15*aaaa20b6SVladimir Sementsov-Ogievskiywith same list of arguments as original one, which will pack the
16*aaaa20b6SVladimir Sementsov-Ogievskiyparameters into a struct, create a coroutine, run it and wait in
17*aaaa20b6SVladimir Sementsov-OgievskiyBDRV_POLL_WHILE() loop. It's boring to create such wrappers by hand,
18*aaaa20b6SVladimir Sementsov-Ogievskiyso we have a script to generate them.
19*aaaa20b6SVladimir Sementsov-Ogievskiy
20*aaaa20b6SVladimir Sementsov-OgievskiyUsage
21*aaaa20b6SVladimir Sementsov-Ogievskiy=====
22*aaaa20b6SVladimir Sementsov-Ogievskiy
23*aaaa20b6SVladimir Sementsov-OgievskiyAssume we have defined the ``coroutine_fn`` function
24*aaaa20b6SVladimir Sementsov-Ogievskiy``bdrv_co_foo(<some args>)`` and need a non-coroutine interface for it,
25*aaaa20b6SVladimir Sementsov-Ogievskiycalled ``bdrv_foo(<same args>)``. In this case the script can help. To
26*aaaa20b6SVladimir Sementsov-Ogievskiytrigger the generation:
27*aaaa20b6SVladimir Sementsov-Ogievskiy
28*aaaa20b6SVladimir Sementsov-Ogievskiy1. You need ``bdrv_foo`` declaration somewhere (for example, in
29*aaaa20b6SVladimir Sementsov-Ogievskiy   ``block/coroutines.h``) with the ``generated_co_wrapper`` mark,
30*aaaa20b6SVladimir Sementsov-Ogievskiy   like this:
31*aaaa20b6SVladimir Sementsov-Ogievskiy
32*aaaa20b6SVladimir Sementsov-Ogievskiy.. code-block:: c
33*aaaa20b6SVladimir Sementsov-Ogievskiy
34*aaaa20b6SVladimir Sementsov-Ogievskiy    int generated_co_wrapper bdrv_foo(<some args>);
35*aaaa20b6SVladimir Sementsov-Ogievskiy
36*aaaa20b6SVladimir Sementsov-Ogievskiy2. You need to feed this declaration to block-coroutine-wrapper script.
37*aaaa20b6SVladimir Sementsov-Ogievskiy   For this, add the .h (or .c) file with the declaration to the
38*aaaa20b6SVladimir Sementsov-Ogievskiy   ``input: files(...)`` list of ``block_gen_c`` target declaration in
39*aaaa20b6SVladimir Sementsov-Ogievskiy   ``block/meson.build``
40*aaaa20b6SVladimir Sementsov-Ogievskiy
41*aaaa20b6SVladimir Sementsov-OgievskiyYou are done. During the build, coroutine wrappers will be generated in
42*aaaa20b6SVladimir Sementsov-Ogievskiy``<BUILD_DIR>/block/block-gen.c``.
43*aaaa20b6SVladimir Sementsov-Ogievskiy
44*aaaa20b6SVladimir Sementsov-OgievskiyLinks
45*aaaa20b6SVladimir Sementsov-Ogievskiy=====
46*aaaa20b6SVladimir Sementsov-Ogievskiy
47*aaaa20b6SVladimir Sementsov-Ogievskiy1. The script location is ``scripts/block-coroutine-wrapper.py``.
48*aaaa20b6SVladimir Sementsov-Ogievskiy
49*aaaa20b6SVladimir Sementsov-Ogievskiy2. Generic place for private ``generated_co_wrapper`` declarations is
50*aaaa20b6SVladimir Sementsov-Ogievskiy   ``block/coroutines.h``, for public declarations:
51*aaaa20b6SVladimir Sementsov-Ogievskiy   ``include/block/block.h``
52*aaaa20b6SVladimir Sementsov-Ogievskiy
53*aaaa20b6SVladimir Sementsov-Ogievskiy3. The core API of generated coroutine wrappers is placed in
54*aaaa20b6SVladimir Sementsov-Ogievskiy   (not generated) ``block/block-gen.h``
55