#include "qemu/osdep.h"
#include "block/coroutines.h"
#include "block/block-gen.h"
-#include "block/block_int.h"\
+#include "block/block_int.h"
+#include "block/dirty-bitmap.h"
"""
self.struct_name = snake_to_camel(self.name)
self.args = [ParamDecl(arg.strip()) for arg in args.split(',')]
self.create_only_co = 'mixed' not in variant
+ self.graph_rdlock = 'bdrv_rdlock' in variant
subsystem, subname = self.name.split('_', 1)
self.co_name = f'{subsystem}_co_{subname}'
t = self.args[0].type
if t == 'BlockDriverState *':
- bs = 'bs'
+ ctx = 'bdrv_get_aio_context(bs)'
elif t == 'BdrvChild *':
- bs = 'child->bs'
+ ctx = 'bdrv_get_aio_context(child->bs)'
+ elif t == 'BlockBackend *':
+ ctx = 'blk_get_aio_context(blk)'
else:
- bs = 'blk_bs(blk)'
- self.bs = bs
+ ctx = 'qemu_get_aio_context()'
+ self.ctx = ctx
def gen_list(self, format: str) -> str:
return ', '.join(format.format_map(arg.__dict__) for arg in self.args)
# Match wrappers declared with a co_wrapper mark
-func_decl_re = re.compile(r'^int\s*co_wrapper'
+func_decl_re = re.compile(r'^(?P<return_type>[a-zA-Z][a-zA-Z0-9_]* [\*]?)'
+ r'\s*co_wrapper'
r'(?P<variant>(_[a-z][a-z0-9_]*)?)\s*'
r'(?P<wrapper_name>[a-z][a-z0-9_]*)'
r'\((?P<args>[^)]*)\);$', re.MULTILINE)
def func_decl_iter(text: str) -> Iterator:
for m in func_decl_re.finditer(text):
- yield FuncDecl(return_type='int',
+ yield FuncDecl(return_type=m.group('return_type'),
name=m.group('wrapper_name'),
args=m.group('args'),
variant=m.group('variant'))
"""
name = func.co_name
struct_name = func.struct_name
+ graph_assume_lock = 'assume_graph_lock();' if func.graph_rdlock else ''
+
return f"""\
-int {func.name}({ func.gen_list('{decl}') })
+{func.return_type} {func.name}({ func.gen_list('{decl}') })
{{
if (qemu_in_coroutine()) {{
+ {graph_assume_lock}
return {name}({ func.gen_list('{name}') });
}} else {{
{struct_name} s = {{
- .poll_state.bs = {func.bs},
+ .poll_state.ctx = {func.ctx},
.poll_state.in_progress = true,
{ func.gen_block(' .{name} = {name},') }
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
- return bdrv_poll_co(&s.poll_state);
+ bdrv_poll_co(&s.poll_state);
+ return s.ret;
}}
}}"""
name = func.co_name
struct_name = func.struct_name
return f"""\
-int {func.name}({ func.gen_list('{decl}') })
+{func.return_type} {func.name}({ func.gen_list('{decl}') })
{{
{struct_name} s = {{
- .poll_state.bs = {func.bs},
+ .poll_state.ctx = {func.ctx},
.poll_state.in_progress = true,
{ func.gen_block(' .{name} = {name},') }
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
- return bdrv_poll_co(&s.poll_state);
+ bdrv_poll_co(&s.poll_state);
+ return s.ret;
}}"""
def gen_wrapper(func: FuncDecl) -> str:
assert not '_co_' in func.name
- assert func.return_type == 'int'
- assert func.args[0].type in ['BlockDriverState *', 'BdrvChild *',
- 'BlockBackend *']
name = func.co_name
struct_name = func.struct_name
+ graph_lock=''
+ graph_unlock=''
+ if func.graph_rdlock:
+ graph_lock=' bdrv_graph_co_rdlock();'
+ graph_unlock=' bdrv_graph_co_rdunlock();'
+
creation_function = create_mixed_wrapper
if func.create_only_co:
creation_function = create_co_wrapper
typedef struct {struct_name} {{
BdrvPollCo poll_state;
+ {func.return_type} ret;
{ func.gen_block(' {decl};') }
}} {struct_name};
{{
{struct_name} *s = opaque;
- s->poll_state.ret = {name}({ func.gen_list('s->{name}') });
+{graph_lock}
+ s->ret = {name}({ func.gen_list('s->{name}') });
+{graph_unlock}
s->poll_state.in_progress = false;
aio_wait_kick();