mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-30 22:03:54 -06:00
Block layer patches
- Code cleanups around block graph modification - Simplify drain - coroutine_fn correctness fixes, including splitting generated coroutine wrappers into co_wrapper (to be called only from non-coroutine context) and co_wrapper_mixed (both coroutine and non-coroutine context) - Introduce a block graph rwlock -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE3D3rFZqa+V09dFb+fwmycsiPL9YFAmObOHIRHGt3b2xmQHJl ZGhhdC5jb20ACgkQfwmycsiPL9b4DQ//VAgplktr9NvX00a/hu4ZXgMyMuwPz36a 0Lfb11hxZM02hN1Re1M/ldzxrQj5ywxatmPH3bwLW/TjlPcXwOHvToF1EwkW/3Ow evmOUOxEH/o7Re8ZrEQEjEg3LdlFBrpRyRNS5qrGK4+38TKsecLYakZdOvYyPujm zpE4uGzG+ZYygyx4OtEhL7bry/iKO3ehGYO3/5IKrpjH+hj1MhYegcUCE7r4eE0G Mmo48ALsxlwStTUx9gUp9jwr5p08k3Jl+ubZnkTPcNZYoyTgX3rOycD8yPoaHoFr bMV6SKPZckueMT1aCTZ2pQl2gJ2ap+YFgJYQ4oyY8powVayZbVFtO9tGO/ZN+IWY zC88tmRMj1KGlgg1R0dUCOfzaJZkk44wZV72U6D3zKuXWBtHVz3WgnlRmD7k4K5Q MhqgqOatSBcD6XajmzMJi6W1xEcMs7yy9/V5e5AsGLKrjX0Z8r8+A6cK18/Hd+4N 9cDkhHET0TccmU2sTgmkqOYXl/VyiU622g1b7E9sjSdzKnqqZ4H0IkFf2G23gVBR 4xgUsftaBaIIRlrp1mHtR8zo7646pQZrZi3RFPx83dJYXpreUtnNNTzlURdnDDfA chvHjrjZ/sz2VKmMHK+PnFVVpxWSAUhHoRUcMV1+EmRGlm9ikuVO4WDBqaG8HHNk vZBm7LpuGGE= =Z9pn -----END PGP SIGNATURE----- Merge tag 'for-upstream' of https://repo.or.cz/qemu/kevin into staging Block layer patches - Code cleanups around block graph modification - Simplify drain - coroutine_fn correctness fixes, including splitting generated coroutine wrappers into co_wrapper (to be called only from non-coroutine context) and co_wrapper_mixed (both coroutine and non-coroutine context) - Introduce a block graph rwlock # gpg: Signature made Thu 15 Dec 2022 15:08:34 GMT # gpg: using RSA key DC3DEB159A9AF95D3D7456FE7F09B272C88F2FD6 # gpg: issuer "kwolf@redhat.com" # gpg: Good signature from "Kevin Wolf <kwolf@redhat.com>" [full] # Primary key fingerprint: DC3D EB15 9A9A F95D 3D74 56FE 7F09 B272 C88F 2FD6 * tag 'for-upstream' of https://repo.or.cz/qemu/kevin: (50 commits) block: GRAPH_RDLOCK for functions only called by co_wrappers block: use co_wrapper_mixed_bdrv_rdlock in functions taking the rdlock block-coroutine-wrapper.py: introduce annotations that take the graph rdlock Mark assert_bdrv_graph_readable/writable() GRAPH_RD/WRLOCK graph-lock: TSA annotations for lock/unlock functions block: assert that graph read and writes are performed correctly block: remove unnecessary assert_bdrv_graph_writable() block: wrlock in bdrv_replace_child_noperm block: Fix locking in external_snapshot_prepare() test-bdrv-drain: Fix incorrrect drain assumptions clang-tsa: Add macros for shared locks clang-tsa: Add TSA_ASSERT() macro Import clang-tsa.h async: Register/unregister aiocontext in graph lock list graph-lock: Implement guard macros graph-lock: Introduce a lock to protect block graph operations block: Factor out bdrv_drain_all_begin_nopoll() block/dirty-bitmap: convert coroutine-only functions to co_wrapper block: convert bdrv_create to co_wrapper block-coroutine-wrapper.py: support also basic return types ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d038d2645a
45 changed files with 1577 additions and 1130 deletions
|
@ -2,7 +2,7 @@
|
|||
"""Generate coroutine wrappers for block subsystem.
|
||||
|
||||
The program parses one or several concatenated c files from stdin,
|
||||
searches for functions with the 'generated_co_wrapper' specifier
|
||||
searches for functions with the 'co_wrapper' specifier
|
||||
and generates corresponding wrappers on stdout.
|
||||
|
||||
Usage: block-coroutine-wrapper.py generated-file.c FILE.[ch]...
|
||||
|
@ -62,10 +62,28 @@ class ParamDecl:
|
|||
|
||||
|
||||
class FuncDecl:
|
||||
def __init__(self, return_type: str, name: str, args: str) -> None:
|
||||
def __init__(self, return_type: str, name: str, args: str,
|
||||
variant: str) -> None:
|
||||
self.return_type = return_type.strip()
|
||||
self.name = name.strip()
|
||||
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 *':
|
||||
ctx = 'bdrv_get_aio_context(bs)'
|
||||
elif t == 'BdrvChild *':
|
||||
ctx = 'bdrv_get_aio_context(child->bs)'
|
||||
elif t == 'BlockBackend *':
|
||||
ctx = 'blk_get_aio_context(blk)'
|
||||
else:
|
||||
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)
|
||||
|
@ -74,17 +92,20 @@ class FuncDecl:
|
|||
return '\n'.join(format.format_map(arg.__dict__) for arg in self.args)
|
||||
|
||||
|
||||
# Match wrappers declared with a generated_co_wrapper mark
|
||||
func_decl_re = re.compile(r'^int\s*generated_co_wrapper\s*'
|
||||
# Match wrappers declared with a co_wrapper mark
|
||||
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'))
|
||||
args=m.group('args'),
|
||||
variant=m.group('variant'))
|
||||
|
||||
|
||||
def snake_to_camel(func_name: str) -> str:
|
||||
|
@ -97,24 +118,75 @@ def snake_to_camel(func_name: str) -> str:
|
|||
return ''.join(words)
|
||||
|
||||
|
||||
def create_mixed_wrapper(func: FuncDecl) -> str:
|
||||
"""
|
||||
Checks if we are already in coroutine
|
||||
"""
|
||||
name = func.co_name
|
||||
struct_name = func.struct_name
|
||||
graph_assume_lock = 'assume_graph_lock();' if func.graph_rdlock else ''
|
||||
|
||||
return f"""\
|
||||
{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.ctx = {func.ctx},
|
||||
.poll_state.in_progress = true,
|
||||
|
||||
{ func.gen_block(' .{name} = {name},') }
|
||||
}};
|
||||
|
||||
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
|
||||
|
||||
bdrv_poll_co(&s.poll_state);
|
||||
return s.ret;
|
||||
}}
|
||||
}}"""
|
||||
|
||||
|
||||
def create_co_wrapper(func: FuncDecl) -> str:
|
||||
"""
|
||||
Assumes we are not in coroutine, and creates one
|
||||
"""
|
||||
name = func.co_name
|
||||
struct_name = func.struct_name
|
||||
return f"""\
|
||||
{func.return_type} {func.name}({ func.gen_list('{decl}') })
|
||||
{{
|
||||
{struct_name} s = {{
|
||||
.poll_state.ctx = {func.ctx},
|
||||
.poll_state.in_progress = true,
|
||||
|
||||
{ func.gen_block(' .{name} = {name},') }
|
||||
}};
|
||||
assert(!qemu_in_coroutine());
|
||||
|
||||
s.poll_state.co = qemu_coroutine_create({name}_entry, &s);
|
||||
|
||||
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 *']
|
||||
|
||||
subsystem, subname = func.name.split('_', 1)
|
||||
name = func.co_name
|
||||
struct_name = func.struct_name
|
||||
|
||||
name = f'{subsystem}_co_{subname}'
|
||||
graph_lock=''
|
||||
graph_unlock=''
|
||||
if func.graph_rdlock:
|
||||
graph_lock=' bdrv_graph_co_rdlock();'
|
||||
graph_unlock=' bdrv_graph_co_rdunlock();'
|
||||
|
||||
t = func.args[0].type
|
||||
if t == 'BlockDriverState *':
|
||||
bs = 'bs'
|
||||
elif t == 'BdrvChild *':
|
||||
bs = 'child->bs'
|
||||
else:
|
||||
bs = 'blk_bs(blk)'
|
||||
struct_name = snake_to_camel(name)
|
||||
creation_function = create_mixed_wrapper
|
||||
if func.create_only_co:
|
||||
creation_function = create_co_wrapper
|
||||
|
||||
return f"""\
|
||||
/*
|
||||
|
@ -123,6 +195,7 @@ def gen_wrapper(func: FuncDecl) -> str:
|
|||
|
||||
typedef struct {struct_name} {{
|
||||
BdrvPollCo poll_state;
|
||||
{func.return_type} ret;
|
||||
{ func.gen_block(' {decl};') }
|
||||
}} {struct_name};
|
||||
|
||||
|
@ -130,29 +203,15 @@ static void coroutine_fn {name}_entry(void *opaque)
|
|||
{{
|
||||
{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();
|
||||
}}
|
||||
|
||||
int {func.name}({ func.gen_list('{decl}') })
|
||||
{{
|
||||
if (qemu_in_coroutine()) {{
|
||||
return {name}({ func.gen_list('{name}') });
|
||||
}} else {{
|
||||
{struct_name} s = {{
|
||||
.poll_state.bs = {bs},
|
||||
.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);
|
||||
}}
|
||||
}}"""
|
||||
{creation_function(func)}"""
|
||||
|
||||
|
||||
def gen_wrappers(input_code: str) -> str:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue