mirror of
				https://github.com/qemu/qemu.git
				synced 2025-10-31 20:44:16 +00:00 
			
		
		
		
	 aaaa20b69b
			
		
	
	
		aaaa20b69b
		
	
	
	
	
		
			
			We have a very frequent pattern of creating a coroutine from a function
with several arguments:
  - create a structure to pack parameters
  - create _entry function to call original function taking parameters
    from struct
  - do different magic to handle completion: set ret to NOT_DONE or
    EINPROGRESS or use separate bool field
  - fill the struct and create coroutine from _entry function with this
    struct as a parameter
  - do coroutine enter and BDRV_POLL_WHILE loop
Let's reduce code duplication by generating coroutine wrappers.
This patch adds scripts/block-coroutine-wrapper.py together with some
friends, which will generate functions with declared prototypes marked
by the 'generated_co_wrapper' specifier.
The usage of new code generation is as follows:
    1. define the coroutine function somewhere
        int coroutine_fn bdrv_co_NAME(...) {...}
    2. declare in some header file
        int generated_co_wrapper bdrv_NAME(...);
       with same list of parameters (generated_co_wrapper is
       defined in "include/block/block.h").
    3. Make sure the block_gen_c declaration in block/meson.build
       mentions the file with your marker function.
Still, no function is now marked, this work is for the following
commit.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Message-Id: <20200924185414.28642-5-vsementsov@virtuozzo.com>
[Added encoding='utf-8' to open() calls as requested by Vladimir. Fixed
typo and grammar issues pointed out by Eric Blake. Removed clang-format
dependency that caused build test issues.
--Stefan]
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
		
	
			
		
			
				
	
	
		
			55 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			55 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| =======================
 | |
| 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:
 | |
| 
 | |
| 1. You need ``bdrv_foo`` declaration somewhere (for example, in
 | |
|    ``block/coroutines.h``) with the ``generated_co_wrapper`` mark,
 | |
|    like this:
 | |
| 
 | |
| .. code-block:: c
 | |
| 
 | |
|     int generated_co_wrapper bdrv_foo(<some args>);
 | |
| 
 | |
| 2. 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 of ``block_gen_c`` target declaration in
 | |
|    ``block/meson.build``
 | |
| 
 | |
| You are done. During the build, coroutine wrappers will be generated in
 | |
| ``<BUILD_DIR>/block/block-gen.c``.
 | |
| 
 | |
| Links
 | |
| =====
 | |
| 
 | |
| 1. The script location is ``scripts/block-coroutine-wrapper.py``.
 | |
| 
 | |
| 2. Generic place for private ``generated_co_wrapper`` declarations is
 | |
|    ``block/coroutines.h``, for public declarations:
 | |
|    ``include/block/block.h``
 | |
| 
 | |
| 3. The core API of generated coroutine wrappers is placed in
 | |
|    (not generated) ``block/block-gen.h``
 |