• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Révisioncfe63e46be0a1f8a7fd2fd5547222f8344a43279 (tree)
l'heure2022-01-28 00:45:13
AuteurPeter Maydell <peter.maydell@lina...>
CommiterPeter Maydell

Message de Log

QAPI patches patches for 2022-01-27
-----BEGIN PGP SIGNATURE-----

iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAmHyqgcSHGFybWJydUBy
ZWRoYXQuY29tAAoJEDhwtADrkYZT3A0P/3FpDflF8zwLlKEuTaLdprUCowEjouTq
8lIKE1La0NK+cvuH0lDMSVLitqdk57WzopLvoSU7sSUXtvb9oJuJNnBPiCXVU8Ou
uapzUnYxSM0KF3ehRtH+eOefyQ9MWpdzfzImmR6DDFjf1Ff03g4dNW9qrNUbMl9D
Oy0ZUMsTms3OtXqkKeg9giAbDOARYgHcHcQEkm41xp28ORMUJvORiP6HV7CTWF4Q
M2fLNT2cOtKZcby+YBU1HUYARFZuAII5718OD4YDWcv+ADMpwp0yCl7BRtLHDDNu
cSm+6KNF+r8SfvwyLVHIvA1W5jP32lzJ/VpgK+2N5mWw8wKAgGzvIZHL8i5rE+b+
NHXv3bFburrBAM/nzHntbFxzLCl5ysgWvQb32Uc/sDd6KKOwHqf1NqoBsn1POn3D
AeQCBaXGlgBpKmeHeU99GnmgV5UKputHahAQqTzslSy8OKkEK9P0GTyEwl9KUmgJ
g8rY2fhsSP8j+dwSRIhHE6B3WDVJ+bxUMUg0Io3BZjAP7SQosoUUYZYhOubTn4B4
6usz2+QVoJePokC7GFl+LdyO5NOIfxvuRkCH9nw3q5eU5WYskvrh/vBvQ8H9UAvP
NBeFHdKwTm82ZGTKz18w2/9imyy5NaAZGte0S3isDOLdGdUqmDxUC0hsHuibrSq2
hjsQSYrsGS5C
=gEIj
-----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2022-01-27-v2' into staging

QAPI patches patches for 2022-01-27

# gpg: Signature made Thu 27 Jan 2022 14:19:51 GMT
# gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653
# gpg: issuer "armbru@redhat.com"
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full]
# gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full]
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653

* remotes/armbru/tags/pull-qapi-2022-01-27-v2:

qapi: generate trace events by default
meson: document why we don't generate trace events for tests/ and qga/
docs/qapi-code-gen: update to cover trace events code generation
meson: generate trace events for qmp commands
qapi/commands: Optionally generate trace for QMP commands
qapi/commands: refactor error handling code
qapi/gen: Add FOO.trace-events output module
schemas: add missing vim modeline

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

Change Summary

Modification

--- a/docs/devel/qapi-code-gen.rst
+++ b/docs/devel/qapi-code-gen.rst
@@ -1630,6 +1630,9 @@ The following files are generated:
16301630 ``$(prefix)qapi-commands.h``
16311631 Function prototypes for the QMP commands specified in the schema
16321632
1633+ ``$(prefix)qapi-commands.trace-events``
1634+ Trace event declarations, see :ref:`tracing`.
1635+
16331636 ``$(prefix)qapi-init-commands.h``
16341637 Command initialization prototype
16351638
@@ -1650,6 +1653,13 @@ Example::
16501653 void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp);
16511654
16521655 #endif /* EXAMPLE_QAPI_COMMANDS_H */
1656+
1657+ $ cat qapi-generated/example-qapi-commands.trace-events
1658+ # AUTOMATICALLY GENERATED, DO NOT MODIFY
1659+
1660+ qmp_enter_my_command(const char *json) "%s"
1661+ qmp_exit_my_command(const char *result, bool succeeded) "%s %d"
1662+
16531663 $ cat qapi-generated/example-qapi-commands.c
16541664 [Uninteresting stuff omitted...]
16551665
@@ -1689,14 +1699,27 @@ Example::
16891699 goto out;
16901700 }
16911701
1702+ if (trace_event_get_state_backends(TRACE_QMP_ENTER_MY_COMMAND)) {
1703+ g_autoptr(GString) req_json = qobject_to_json(QOBJECT(args));
1704+
1705+ trace_qmp_enter_my_command(req_json->str);
1706+ }
1707+
16921708 retval = qmp_my_command(arg.arg1, &err);
1693- error_propagate(errp, err);
16941709 if (err) {
1710+ trace_qmp_exit_my_command(error_get_pretty(err), false);
1711+ error_propagate(errp, err);
16951712 goto out;
16961713 }
16971714
16981715 qmp_marshal_output_UserDefOne(retval, ret, errp);
16991716
1717+ if (trace_event_get_state_backends(TRACE_QMP_EXIT_MY_COMMAND)) {
1718+ g_autoptr(GString) ret_json = qobject_to_json(*ret);
1719+
1720+ trace_qmp_exit_my_command(ret_json->str, true);
1721+ }
1722+
17001723 out:
17011724 visit_free(v);
17021725 v = qapi_dealloc_visitor_new();
--- a/docs/devel/tracing.rst
+++ b/docs/devel/tracing.rst
@@ -1,3 +1,5 @@
1+.. _tracing:
2+
13 =======
24 Tracing
35 =======
--- a/meson.build
+++ b/meson.build
@@ -41,6 +41,7 @@ qemu_icondir = get_option('datadir') / 'icons'
4141
4242 config_host_data = configuration_data()
4343 genh = []
44+qapi_trace_events = []
4445
4546 target_dirs = config_host['TARGET_DIRS'].split()
4647 have_linux_user = false
@@ -2557,6 +2558,8 @@ if 'CONFIG_VHOST_USER' in config_host
25572558 vhost_user = libvhost_user.get_variable('vhost_user_dep')
25582559 endif
25592560
2561+# NOTE: the trace/ subdirectory needs the qapi_trace_events variable
2562+# that is filled in by qapi/.
25602563 subdir('qapi')
25612564 subdir('qobject')
25622565 subdir('stubs')
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -1,4 +1,5 @@
11 # -*- mode: python -*-
2+# vim: filetype=python
23 #
34 # Copyright (C) 2015-2019 Zoltán Kővágó <DirtY.iCE.hu@gmail.com>
45 #
--- a/qapi/compat.json
+++ b/qapi/compat.json
@@ -1,4 +1,5 @@
11 # -*- Mode: Python -*-
2+# vim: filetype=python
23
34 ##
45 # = Compatibility policy
--- a/qapi/meson.build
+++ b/qapi/meson.build
@@ -114,6 +114,7 @@ foreach module : qapi_all_modules
114114 'qapi-events-@0@.h'.format(module),
115115 'qapi-commands-@0@.c'.format(module),
116116 'qapi-commands-@0@.h'.format(module),
117+ 'qapi-commands-@0@.trace-events'.format(module),
117118 ]
118119 endif
119120 if module.endswith('-target')
@@ -137,6 +138,9 @@ foreach output : qapi_util_outputs
137138 if output.endswith('.h')
138139 genh += qapi_files[i]
139140 endif
141+ if output.endswith('.trace-events')
142+ qapi_trace_events += qapi_files[i]
143+ endif
140144 util_ss.add(qapi_files[i])
141145 i = i + 1
142146 endforeach
@@ -145,6 +149,9 @@ foreach output : qapi_specific_outputs + qapi_nonmodule_outputs
145149 if output.endswith('.h')
146150 genh += qapi_files[i]
147151 endif
152+ if output.endswith('.trace-events')
153+ qapi_trace_events += qapi_files[i]
154+ endif
148155 specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: qapi_files[i])
149156 i = i + 1
150157 endforeach
--- a/qapi/replay.json
+++ b/qapi/replay.json
@@ -1,4 +1,5 @@
11 # -*- Mode: Python -*-
2+# vim: filetype=python
23 #
34
45 ##
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -1,4 +1,5 @@
11 # -*- mode: python -*-
2+# vim: filetype=python
23 #
34 # Copyright (C) 2011-2016 Lluís Vilanova <vilanova@ac.upc.edu>
45 #
--- a/qga/meson.build
+++ b/qga/meson.build
@@ -15,10 +15,18 @@ qga_qapi_outputs = [
1515 'qga-qapi-visit.h',
1616 ]
1717
18+# Problem: to generate trace events, we'd have to add the .trace-events
19+# file to qapi_trace_events like we do in qapi/meson.build. Since
20+# qapi_trace_events is used by trace/meson.build, we'd have to move
21+# subdir('qga') above subdir('trace') in the top-level meson.build.
22+# Can't, because it would break the dependency of qga on qemuutil (which
23+# depends on trace_ss). Not worth solving now; simply suppress trace
24+# event generation instead.
1825 qga_qapi_files = custom_target('QGA QAPI files',
1926 output: qga_qapi_outputs,
2027 input: 'qapi-schema.json',
21- command: [ qapi_gen, '-o', 'qga', '-p', 'qga-', '@INPUT0@' ],
28+ command: [ qapi_gen, '-o', 'qga', '-p', 'qga-', '@INPUT0@',
29+ '--suppress-tracing' ],
2230 depend_files: qapi_gen_depends)
2331
2432 qga_ss = ss.source_set()
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -53,7 +53,8 @@ def gen_command_decl(name: str,
5353 def gen_call(name: str,
5454 arg_type: Optional[QAPISchemaObjectType],
5555 boxed: bool,
56- ret_type: Optional[QAPISchemaType]) -> str:
56+ ret_type: Optional[QAPISchemaType],
57+ gen_tracing: bool) -> str:
5758 ret = ''
5859
5960 argstr = ''
@@ -71,21 +72,67 @@ def gen_call(name: str,
7172 if ret_type:
7273 lhs = 'retval = '
7374
74- ret = mcgen('''
75+ name = c_name(name)
76+ upper = name.upper()
7577
76- %(lhs)sqmp_%(c_name)s(%(args)s&err);
77- error_propagate(errp, err);
78-''',
79- c_name=c_name(name), args=argstr, lhs=lhs)
80- if ret_type:
78+ if gen_tracing:
8179 ret += mcgen('''
80+
81+ if (trace_event_get_state_backends(TRACE_QMP_ENTER_%(upper)s)) {
82+ g_autoptr(GString) req_json = qobject_to_json(QOBJECT(args));
83+
84+ trace_qmp_enter_%(name)s(req_json->str);
85+ }
86+ ''',
87+ upper=upper, name=name)
88+
89+ ret += mcgen('''
90+
91+ %(lhs)sqmp_%(name)s(%(args)s&err);
92+''',
93+ name=name, args=argstr, lhs=lhs)
94+
95+ ret += mcgen('''
8296 if (err) {
97+''')
98+
99+ if gen_tracing:
100+ ret += mcgen('''
101+ trace_qmp_exit_%(name)s(error_get_pretty(err), false);
102+''',
103+ name=name)
104+
105+ ret += mcgen('''
106+ error_propagate(errp, err);
83107 goto out;
84108 }
109+''')
110+
111+ if ret_type:
112+ ret += mcgen('''
85113
86114 qmp_marshal_output_%(c_name)s(retval, ret, errp);
87115 ''',
88116 c_name=ret_type.c_name())
117+
118+ if gen_tracing:
119+ if ret_type:
120+ ret += mcgen('''
121+
122+ if (trace_event_get_state_backends(TRACE_QMP_EXIT_%(upper)s)) {
123+ g_autoptr(GString) ret_json = qobject_to_json(*ret);
124+
125+ trace_qmp_exit_%(name)s(ret_json->str, true);
126+ }
127+ ''',
128+ upper=upper, name=name)
129+ else:
130+ ret += mcgen('''
131+
132+ trace_qmp_exit_%(name)s("{}", true);
133+ ''',
134+ name=name)
135+
89136 return ret
90137
91138
@@ -122,10 +169,19 @@ def gen_marshal_decl(name: str) -> str:
122169 proto=build_marshal_proto(name))
123170
124171
172+def gen_trace(name: str) -> str:
173+ return mcgen('''
174+qmp_enter_%(name)s(const char *json) "%%s"
175+qmp_exit_%(name)s(const char *result, bool succeeded) "%%s %%d"
176+''',
177+ name=c_name(name))
178+
179+
125180 def gen_marshal(name: str,
126181 arg_type: Optional[QAPISchemaObjectType],
127182 boxed: bool,
128- ret_type: Optional[QAPISchemaType]) -> str:
183+ ret_type: Optional[QAPISchemaType],
184+ gen_tracing: bool) -> str:
129185 have_args = boxed or (arg_type and not arg_type.is_empty())
130186 if have_args:
131187 assert arg_type is not None
@@ -180,7 +236,7 @@ def gen_marshal(name: str,
180236 }
181237 ''')
182238
183- ret += gen_call(name, arg_type, boxed, ret_type)
239+ ret += gen_call(name, arg_type, boxed, ret_type, gen_tracing)
184240
185241 ret += mcgen('''
186242
@@ -238,11 +294,13 @@ def gen_register_command(name: str,
238294
239295
240296 class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
241- def __init__(self, prefix: str):
297+ def __init__(self, prefix: str, gen_tracing: bool):
242298 super().__init__(
243299 prefix, 'qapi-commands',
244- ' * Schema-defined QAPI/QMP commands', None, __doc__)
300+ ' * Schema-defined QAPI/QMP commands', None, __doc__,
301+ gen_tracing=gen_tracing)
245302 self._visited_ret_types: Dict[QAPIGenC, Set[QAPISchemaType]] = {}
303+ self._gen_tracing = gen_tracing
246304
247305 def _begin_user_module(self, name: str) -> None:
248306 self._visited_ret_types[self._genc] = set()
@@ -261,6 +319,16 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
261319
262320 ''',
263321 commands=commands, visit=visit))
322+
323+ if self._gen_tracing and commands != 'qapi-commands':
324+ self._genc.add(mcgen('''
325+#include "qapi/qmp/qjson.h"
326+#include "trace/trace-%(nm)s_trace_events.h"
327+''',
328+ nm=c_name(commands, protect=False)))
329+ # We use c_name(commands, protect=False) to turn '-' into '_', to
330+ # match .underscorify() in trace/meson.build
331+
264332 self._genh.add(mcgen('''
265333 #include "%(types)s.h"
266334
@@ -322,7 +390,10 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
322390 with ifcontext(ifcond, self._genh, self._genc):
323391 self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type))
324392 self._genh.add(gen_marshal_decl(name))
325- self._genc.add(gen_marshal(name, arg_type, boxed, ret_type))
393+ self._genc.add(gen_marshal(name, arg_type, boxed, ret_type,
394+ self._gen_tracing))
395+ if self._gen_tracing:
396+ self._gen_trace_events.add(gen_trace(name))
326397 with self._temp_module('./init'):
327398 with ifcontext(ifcond, self._genh, self._genc):
328399 self._genc.add(gen_register_command(
@@ -332,7 +403,8 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds)
332403
333404 def gen_commands(schema: QAPISchema,
334405 output_dir: str,
335- prefix: str) -> None:
336- vis = QAPISchemaGenCommandVisitor(prefix)
406+ prefix: str,
407+ gen_tracing: bool) -> None:
408+ vis = QAPISchemaGenCommandVisitor(prefix, gen_tracing)
337409 schema.visit(vis)
338410 vis.write(output_dir)
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -192,6 +192,11 @@ class QAPIGenH(QAPIGenC):
192192 return guardend(self.fname)
193193
194194
195+class QAPIGenTrace(QAPIGen):
196+ def _top(self) -> str:
197+ return super()._top() + '# AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n'
198+
199+
195200 @contextmanager
196201 def ifcontext(ifcond: QAPISchemaIfCond, *args: QAPIGenCCode) -> Iterator[None]:
197202 """
@@ -244,15 +249,18 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
244249 what: str,
245250 user_blurb: str,
246251 builtin_blurb: Optional[str],
247- pydoc: str):
252+ pydoc: str,
253+ gen_tracing: bool = False):
248254 self._prefix = prefix
249255 self._what = what
250256 self._user_blurb = user_blurb
251257 self._builtin_blurb = builtin_blurb
252258 self._pydoc = pydoc
253259 self._current_module: Optional[str] = None
254- self._module: Dict[str, Tuple[QAPIGenC, QAPIGenH]] = {}
260+ self._module: Dict[str, Tuple[QAPIGenC, QAPIGenH,
261+ Optional[QAPIGenTrace]]] = {}
255262 self._main_module: Optional[str] = None
263+ self._gen_tracing = gen_tracing
256264
257265 @property
258266 def _genc(self) -> QAPIGenC:
@@ -264,6 +272,14 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
264272 assert self._current_module is not None
265273 return self._module[self._current_module][1]
266274
275+ @property
276+ def _gen_trace_events(self) -> QAPIGenTrace:
277+ assert self._gen_tracing
278+ assert self._current_module is not None
279+ gent = self._module[self._current_module][2]
280+ assert gent is not None
281+ return gent
282+
267283 @staticmethod
268284 def _module_dirname(name: str) -> str:
269285 if QAPISchemaModule.is_user_module(name):
@@ -293,7 +309,12 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
293309 basename = self._module_filename(self._what, name)
294310 genc = QAPIGenC(basename + '.c', blurb, self._pydoc)
295311 genh = QAPIGenH(basename + '.h', blurb, self._pydoc)
296- self._module[name] = (genc, genh)
312+
313+ gent: Optional[QAPIGenTrace] = None
314+ if self._gen_tracing:
315+ gent = QAPIGenTrace(basename + '.trace-events')
316+
317+ self._module[name] = (genc, genh, gent)
297318 self._current_module = name
298319
299320 @contextmanager
@@ -304,11 +325,13 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
304325 self._current_module = old_module
305326
306327 def write(self, output_dir: str, opt_builtins: bool = False) -> None:
307- for name, (genc, genh) in self._module.items():
328+ for name, (genc, genh, gent) in self._module.items():
308329 if QAPISchemaModule.is_builtin_module(name) and not opt_builtins:
309330 continue
310331 genc.write(output_dir)
311332 genh.write(output_dir)
333+ if gent is not None:
334+ gent.write(output_dir)
312335
313336 def _begin_builtin_module(self) -> None:
314337 pass
--- a/scripts/qapi/main.py
+++ b/scripts/qapi/main.py
@@ -32,7 +32,8 @@ def generate(schema_file: str,
3232 output_dir: str,
3333 prefix: str,
3434 unmask: bool = False,
35- builtins: bool = False) -> None:
35+ builtins: bool = False,
36+ gen_tracing: bool = False) -> None:
3637 """
3738 Generate C code for the given schema into the target directory.
3839
@@ -49,7 +50,7 @@ def generate(schema_file: str,
4950 schema = QAPISchema(schema_file)
5051 gen_types(schema, output_dir, prefix, builtins)
5152 gen_visit(schema, output_dir, prefix, builtins)
52- gen_commands(schema, output_dir, prefix)
53+ gen_commands(schema, output_dir, prefix, gen_tracing)
5354 gen_events(schema, output_dir, prefix)
5455 gen_introspect(schema, output_dir, prefix, unmask)
5556
@@ -74,6 +75,12 @@ def main() -> int:
7475 parser.add_argument('-u', '--unmask-non-abi-names', action='store_true',
7576 dest='unmask',
7677 help="expose non-ABI names in introspection")
78+
79+ # Option --suppress-tracing exists so we can avoid solving build system
80+ # problems. TODO Drop it when we no longer need it.
81+ parser.add_argument('--suppress-tracing', action='store_true',
82+ help="suppress adding trace events to qmp marshals")
83+
7784 parser.add_argument('schema', action='store')
7885 args = parser.parse_args()
7986
@@ -88,7 +95,8 @@ def main() -> int:
8895 output_dir=args.output_dir,
8996 prefix=args.prefix,
9097 unmask=args.unmask,
91- builtins=args.builtins)
98+ builtins=args.builtins,
99+ gen_tracing=not args.suppress_tracing)
92100 except QAPIError as err:
93101 print(f"{sys.argv[0]}: {str(err)}", file=sys.stderr)
94102 return 1
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -31,13 +31,21 @@ test_qapi_outputs = [
3131 'test-qapi-visit.h',
3232 ]
3333
34+# Problem: to generate trace events, we'd have to add the .trace-events
35+# file to qapi_trace_events like we do in qapi/meson.build. Since
36+# qapi_trace_events is used by trace/meson.build, we'd have to move
37+# subdir('tests') above subdir('trace') in the top-level meson.build.
38+# Can't, because it would break the dependency of qga on qemuutil (which
39+# depends on trace_ss). Not worth solving now; simply suppress trace
40+# event generation instead.
3441 test_qapi_files = custom_target('Test QAPI files',
3542 output: test_qapi_outputs,
3643 input: files('qapi-schema/qapi-schema-test.json',
3744 'qapi-schema/include/sub-module.json',
3845 'qapi-schema/sub-sub-module.json'),
3946 command: [ qapi_gen, '-o', meson.current_build_dir(),
40- '-b', '-p', 'test-', '@INPUT0@' ],
47+ '-b', '-p', 'test-', '@INPUT0@',
48+ '--suppress-tracing' ],
4149 depend_files: qapi_gen_depends)
4250
4351 # meson doesn't like generated output in other directories
--- a/trace/meson.build
+++ b/trace/meson.build
@@ -2,10 +2,15 @@
22 specific_ss.add(files('control-target.c'))
33
44 trace_events_files = []
5-foreach dir : [ '.' ] + trace_events_subdirs
6- trace_events_file = meson.project_source_root() / dir / 'trace-events'
5+foreach item : [ '.' ] + trace_events_subdirs + qapi_trace_events
6+ if item in qapi_trace_events
7+ trace_events_file = item
8+ group_name = item.full_path().split('/')[-1].underscorify()
9+ else
10+ trace_events_file = meson.project_source_root() / item / 'trace-events'
11+ group_name = item == '.' ? 'root' : item.underscorify()
12+ endif
713 trace_events_files += [ trace_events_file ]
8- group_name = dir == '.' ? 'root' : dir.underscorify()
914 group = '--group=' + group_name
1015 fmt = '@0@-' + group_name + '.@1@'
1116