mirror of https://github.com/xqemu/xqemu.git
trace: [tracetool] Minimize the amount of per-backend code
Backends now only contain the essential backend-specific code, and most of the work is moved to frontend code. Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
ef0bd3bba6
commit
1dad2ce973
|
@ -109,14 +109,10 @@ def process(events, log, analyzer):
|
||||||
if isinstance(log, str):
|
if isinstance(log, str):
|
||||||
log = open(log, 'rb')
|
log = open(log, 'rb')
|
||||||
|
|
||||||
enabled_events = []
|
|
||||||
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
|
dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)")
|
||||||
edict = {dropped_event_id: dropped_event}
|
edict = {dropped_event_id: dropped_event}
|
||||||
|
|
||||||
for e in events:
|
for num, event in enumerate(events):
|
||||||
if 'disable' not in e.properties:
|
|
||||||
enabled_events.append(e)
|
|
||||||
for num, event in enumerate(enabled_events):
|
|
||||||
edict[num] = event
|
edict[num] = event
|
||||||
|
|
||||||
def build_fn(analyzer, event):
|
def build_fn(analyzer, event):
|
||||||
|
|
|
@ -266,10 +266,7 @@ def generate(fevents, format, backend,
|
||||||
if not tracetool.backend.exists(backend):
|
if not tracetool.backend.exists(backend):
|
||||||
raise TracetoolError("unknown backend: %s" % backend)
|
raise TracetoolError("unknown backend: %s" % backend)
|
||||||
backend = backend.replace("-", "_")
|
backend = backend.replace("-", "_")
|
||||||
|
backend = tracetool.backend.Wrapper(backend, format)
|
||||||
if not tracetool.backend.compatible(backend, format):
|
|
||||||
raise TracetoolError("backend '%s' not compatible with format '%s'" %
|
|
||||||
(backend, format))
|
|
||||||
|
|
||||||
import tracetool.backend.dtrace
|
import tracetool.backend.dtrace
|
||||||
tracetool.backend.dtrace.BINARY = binary
|
tracetool.backend.dtrace.BINARY = binary
|
||||||
|
@ -277,16 +274,4 @@ def generate(fevents, format, backend,
|
||||||
|
|
||||||
events = _read_events(fevents)
|
events = _read_events(fevents)
|
||||||
|
|
||||||
if backend == "nop":
|
tracetool.format.generate(events, format, backend)
|
||||||
( e.properies.add("disable") for e in events )
|
|
||||||
|
|
||||||
tracetool.format.generate_begin(format, events)
|
|
||||||
tracetool.backend.generate("nop", format,
|
|
||||||
[ e
|
|
||||||
for e in events
|
|
||||||
if "disable" in e.properties ])
|
|
||||||
tracetool.backend.generate(backend, format,
|
|
||||||
[ e
|
|
||||||
for e in events
|
|
||||||
if "disable" not in e.properties ])
|
|
||||||
tracetool.format.generate_end(format, events)
|
|
||||||
|
|
|
@ -30,17 +30,24 @@ PUBLIC If exists and is set to 'True', the backend is considered "public".
|
||||||
Backend functions
|
Backend functions
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
======== =======================================================================
|
All the following functions are optional, and no output will be generated if
|
||||||
Function Description
|
they do not exist.
|
||||||
======== =======================================================================
|
|
||||||
<format> Called to generate the format- and backend-specific code for each of
|
=============================== ==============================================
|
||||||
the specified events. If the function does not exist, the backend is
|
Function Description
|
||||||
considered not compatible with the given format.
|
=============================== ==============================================
|
||||||
======== =======================================================================
|
generate_<format>_begin(events) Generate backend- and format-specific file
|
||||||
|
header contents.
|
||||||
|
generate_<format>_end(events) Generate backend- and format-specific file
|
||||||
|
footer contents.
|
||||||
|
generate_<format>(event) Generate backend- and format-specific contents
|
||||||
|
for the given event.
|
||||||
|
=============================== ==============================================
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||||
__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
|
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||||
__license__ = "GPL version 2 or (at your option) any later version"
|
__license__ = "GPL version 2 or (at your option) any later version"
|
||||||
|
|
||||||
__maintainer__ = "Stefan Hajnoczi"
|
__maintainer__ = "Stefan Hajnoczi"
|
||||||
|
@ -91,39 +98,24 @@ def exists(name):
|
||||||
return tracetool.try_import("tracetool.backend." + name)[1]
|
return tracetool.try_import("tracetool.backend." + name)[1]
|
||||||
|
|
||||||
|
|
||||||
def compatible(backend, format):
|
class Wrapper:
|
||||||
"""Whether a backend is compatible with the given format."""
|
def __init__(self, backend, format):
|
||||||
if not exists(backend):
|
self._backend = backend.replace("-", "_")
|
||||||
raise ValueError("unknown backend: %s" % backend)
|
self._format = format.replace("-", "_")
|
||||||
|
assert exists(self._backend)
|
||||||
|
assert tracetool.format.exists(self._format)
|
||||||
|
|
||||||
backend = backend.replace("-", "_")
|
def _run_function(self, name, *args, **kwargs):
|
||||||
format = format.replace("-", "_")
|
func = tracetool.try_import("tracetool.backend." + self._backend,
|
||||||
|
name % self._format, None)[1]
|
||||||
|
if func is not None:
|
||||||
|
func(*args, **kwargs)
|
||||||
|
|
||||||
if backend == "nop":
|
def generate_begin(self, events):
|
||||||
return True
|
self._run_function("generate_%s_begin", events)
|
||||||
else:
|
|
||||||
func = tracetool.try_import("tracetool.backend." + backend,
|
|
||||||
format, None)[1]
|
|
||||||
return func is not None
|
|
||||||
|
|
||||||
|
def generate(self, event):
|
||||||
|
self._run_function("generate_%s", event)
|
||||||
|
|
||||||
def _empty(events):
|
def generate_end(self, events):
|
||||||
pass
|
self._run_function("generate_%s_end", events)
|
||||||
|
|
||||||
def generate(backend, format, events):
|
|
||||||
"""Generate the per-event output for the given (backend, format) pair."""
|
|
||||||
if not compatible(backend, format):
|
|
||||||
raise ValueError("backend '%s' not compatible with format '%s'" %
|
|
||||||
(backend, format))
|
|
||||||
|
|
||||||
backend = backend.replace("-", "_")
|
|
||||||
format = format.replace("-", "_")
|
|
||||||
|
|
||||||
if backend == "nop":
|
|
||||||
func = tracetool.try_import("tracetool.format." + format,
|
|
||||||
"nop", _empty)[1]
|
|
||||||
else:
|
|
||||||
func = tracetool.try_import("tracetool.backend." + backend,
|
|
||||||
format, None)[1]
|
|
||||||
|
|
||||||
func(events)
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ PUBLIC = True
|
||||||
|
|
||||||
PROBEPREFIX = None
|
PROBEPREFIX = None
|
||||||
|
|
||||||
def _probeprefix():
|
def probeprefix():
|
||||||
if PROBEPREFIX is None:
|
if PROBEPREFIX is None:
|
||||||
raise ValueError("you must set PROBEPREFIX")
|
raise ValueError("you must set PROBEPREFIX")
|
||||||
return PROBEPREFIX
|
return PROBEPREFIX
|
||||||
|
@ -29,81 +29,18 @@ def _probeprefix():
|
||||||
|
|
||||||
BINARY = None
|
BINARY = None
|
||||||
|
|
||||||
def _binary():
|
def binary():
|
||||||
if BINARY is None:
|
if BINARY is None:
|
||||||
raise ValueError("you must set BINARY")
|
raise ValueError("you must set BINARY")
|
||||||
return BINARY
|
return BINARY
|
||||||
|
|
||||||
|
|
||||||
def c(events):
|
def generate_h_begin(events):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def h(events):
|
|
||||||
out('#include "trace/generated-tracers-dtrace.h"',
|
out('#include "trace/generated-tracers-dtrace.h"',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
for e in events:
|
|
||||||
out('static inline void %(api)s(%(args)s) {',
|
|
||||||
' QEMU_%(uppername)s(%(argnames)s);',
|
|
||||||
'}',
|
|
||||||
api = e.api(),
|
|
||||||
args = e.args,
|
|
||||||
uppername = e.name.upper(),
|
|
||||||
argnames = ", ".join(e.args.names()),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
def generate_h(event):
|
||||||
def d(events):
|
out(' QEMU_%(uppername)s(%(argnames)s);',
|
||||||
out('provider qemu {')
|
uppername=event.name.upper(),
|
||||||
|
argnames=", ".join(event.args.names()))
|
||||||
for e in events:
|
|
||||||
args = str(e.args)
|
|
||||||
|
|
||||||
# DTrace provider syntax expects foo() for empty
|
|
||||||
# params, not foo(void)
|
|
||||||
if args == 'void':
|
|
||||||
args = ''
|
|
||||||
|
|
||||||
# Define prototype for probe arguments
|
|
||||||
out('',
|
|
||||||
'probe %(name)s(%(args)s);',
|
|
||||||
name = e.name,
|
|
||||||
args = args,
|
|
||||||
)
|
|
||||||
|
|
||||||
out('',
|
|
||||||
'};')
|
|
||||||
|
|
||||||
|
|
||||||
# Technically 'self' is not used by systemtap yet, but
|
|
||||||
# they recommended we keep it in the reserved list anyway
|
|
||||||
RESERVED_WORDS = (
|
|
||||||
'break', 'catch', 'continue', 'delete', 'else', 'for',
|
|
||||||
'foreach', 'function', 'global', 'if', 'in', 'limit',
|
|
||||||
'long', 'next', 'probe', 'return', 'self', 'string',
|
|
||||||
'try', 'while'
|
|
||||||
)
|
|
||||||
|
|
||||||
def stap(events):
|
|
||||||
for e in events:
|
|
||||||
# Define prototype for probe arguments
|
|
||||||
out('probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")',
|
|
||||||
'{',
|
|
||||||
probeprefix = _probeprefix(),
|
|
||||||
name = e.name,
|
|
||||||
binary = _binary(),
|
|
||||||
)
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
if len(e.args) > 0:
|
|
||||||
for name in e.args.names():
|
|
||||||
# Append underscore to reserved keywords
|
|
||||||
if name in RESERVED_WORDS:
|
|
||||||
name += '_'
|
|
||||||
out(' %s = $arg%d;' % (name, i))
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
out('}')
|
|
||||||
|
|
||||||
out()
|
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
Generic event description.
|
|
||||||
|
|
||||||
This is a dummy backend to establish appropriate frontend/backend compatibility
|
|
||||||
checks.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
|
|
||||||
__license__ = "GPL version 2 or (at your option) any later version"
|
|
||||||
|
|
||||||
__maintainer__ = "Stefan Hajnoczi"
|
|
||||||
__email__ = "stefanha@linux.vnet.ibm.com"
|
|
||||||
|
|
||||||
|
|
||||||
def events_h(events):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def events_c(events):
|
|
||||||
pass
|
|
|
@ -19,36 +19,30 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def c(events):
|
def generate_h_begin(events):
|
||||||
pass
|
|
||||||
|
|
||||||
def h(events):
|
|
||||||
out('#include "trace/ftrace.h"',
|
out('#include "trace/ftrace.h"',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
'',
|
'')
|
||||||
)
|
|
||||||
|
|
||||||
for e in events:
|
|
||||||
argnames = ", ".join(e.args.names())
|
|
||||||
if len(e.args) > 0:
|
|
||||||
argnames = ", " + argnames
|
|
||||||
|
|
||||||
out('static inline void trace_%(name)s(%(args)s)',
|
def generate_h(event):
|
||||||
'{',
|
argnames = ", ".join(event.args.names())
|
||||||
' char ftrace_buf[MAX_TRACE_STRLEN];',
|
if len(event.args) > 0:
|
||||||
' int unused __attribute__ ((unused));',
|
argnames = ", " + argnames
|
||||||
' int trlen;',
|
|
||||||
' bool _state = trace_event_get_state(%(event_id)s);',
|
out(' {',
|
||||||
' if (_state) {',
|
' char ftrace_buf[MAX_TRACE_STRLEN];',
|
||||||
' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
|
' int unused __attribute__ ((unused));',
|
||||||
' "%(name)s " %(fmt)s "\\n" %(argnames)s);',
|
' int trlen;',
|
||||||
' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
|
' if (trace_event_get_state(%(event_id)s)) {',
|
||||||
' unused = write(trace_marker_fd, ftrace_buf, trlen);',
|
' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,',
|
||||||
' }',
|
' "%(name)s " %(fmt)s "\\n" %(argnames)s);',
|
||||||
'}',
|
' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);',
|
||||||
name = e.name,
|
' unused = write(trace_marker_fd, ftrace_buf, trlen);',
|
||||||
args = e.args,
|
' }',
|
||||||
event_id = "TRACE_" + e.name.upper(),
|
' }',
|
||||||
fmt = e.fmt.rstrip("\n"),
|
name=event.name,
|
||||||
argnames = argnames,
|
args=event.args,
|
||||||
)
|
event_id="TRACE_" + event.name.upper(),
|
||||||
|
fmt=event.fmt.rstrip("\n"),
|
||||||
|
argnames=argnames)
|
||||||
|
|
|
@ -26,76 +26,74 @@ def is_string(arg):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def c(events):
|
|
||||||
|
def generate_h_begin(events):
|
||||||
|
for event in events:
|
||||||
|
out('void _simple_%(api)s(%(args)s);',
|
||||||
|
api=event.api(),
|
||||||
|
args=event.args)
|
||||||
|
out('')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_h(event):
|
||||||
|
out(' _simple_%(api)s(%(args)s);',
|
||||||
|
api=event.api(),
|
||||||
|
args=", ".join(event.args.names()))
|
||||||
|
|
||||||
|
|
||||||
|
def generate_c_begin(events):
|
||||||
out('#include "trace.h"',
|
out('#include "trace.h"',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
'#include "trace/simple.h"',
|
'#include "trace/simple.h"',
|
||||||
|
'')
|
||||||
|
|
||||||
|
|
||||||
|
def generate_c(event):
|
||||||
|
out('void _simple_%(api)s(%(args)s)',
|
||||||
|
'{',
|
||||||
|
' TraceBufferRecord rec;',
|
||||||
|
api=event.api(),
|
||||||
|
args=event.args)
|
||||||
|
sizes = []
|
||||||
|
for type_, name in event.args:
|
||||||
|
if is_string(type_):
|
||||||
|
out(' size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;',
|
||||||
|
name=name)
|
||||||
|
strsizeinfo = "4 + arg%s_len" % name
|
||||||
|
sizes.append(strsizeinfo)
|
||||||
|
else:
|
||||||
|
sizes.append("8")
|
||||||
|
sizestr = " + ".join(sizes)
|
||||||
|
if len(event.args) == 0:
|
||||||
|
sizestr = '0'
|
||||||
|
|
||||||
|
|
||||||
|
out('',
|
||||||
|
' if (!trace_event_get_state(%(event_id)s)) {',
|
||||||
|
' return;',
|
||||||
|
' }',
|
||||||
'',
|
'',
|
||||||
)
|
' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
|
||||||
|
' return; /* Trace Buffer Full, Event Dropped ! */',
|
||||||
|
' }',
|
||||||
|
event_id='TRACE_' + event.name.upper(),
|
||||||
|
size_str=sizestr)
|
||||||
|
|
||||||
for num, event in enumerate(events):
|
if len(event.args) > 0:
|
||||||
out('void %(api)s(%(args)s)',
|
|
||||||
'{',
|
|
||||||
' TraceBufferRecord rec;',
|
|
||||||
api = event.api(),
|
|
||||||
args = event.args,
|
|
||||||
)
|
|
||||||
sizes = []
|
|
||||||
for type_, name in event.args:
|
for type_, name in event.args:
|
||||||
|
# string
|
||||||
if is_string(type_):
|
if is_string(type_):
|
||||||
out(' size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;',
|
out(' trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
|
||||||
name = name,
|
name=name)
|
||||||
)
|
# pointer var (not string)
|
||||||
strsizeinfo = "4 + arg%s_len" % name
|
elif type_.endswith('*'):
|
||||||
sizes.append(strsizeinfo)
|
out(' trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
|
||||||
|
name=name)
|
||||||
|
# primitive data type
|
||||||
else:
|
else:
|
||||||
sizes.append("8")
|
out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
|
||||||
sizestr = " + ".join(sizes)
|
name=name)
|
||||||
if len(event.args) == 0:
|
|
||||||
sizestr = '0'
|
|
||||||
|
|
||||||
|
out(' trace_record_finish(&rec);',
|
||||||
out('',
|
'}',
|
||||||
' TraceEvent *eventp = trace_event_id(%(event_enum)s);',
|
'')
|
||||||
' bool _state = trace_event_get_state_dynamic(eventp);',
|
|
||||||
' if (!_state) {',
|
|
||||||
' return;',
|
|
||||||
' }',
|
|
||||||
'',
|
|
||||||
' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
|
|
||||||
' return; /* Trace Buffer Full, Event Dropped ! */',
|
|
||||||
' }',
|
|
||||||
event_enum = 'TRACE_' + event.name.upper(),
|
|
||||||
event_id = num,
|
|
||||||
size_str = sizestr,
|
|
||||||
)
|
|
||||||
|
|
||||||
if len(event.args) > 0:
|
|
||||||
for type_, name in event.args:
|
|
||||||
# string
|
|
||||||
if is_string(type_):
|
|
||||||
out(' trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
|
|
||||||
name = name,
|
|
||||||
)
|
|
||||||
# pointer var (not string)
|
|
||||||
elif type_.endswith('*'):
|
|
||||||
out(' trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
|
|
||||||
name = name,
|
|
||||||
)
|
|
||||||
# primitive data type
|
|
||||||
else:
|
|
||||||
out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
|
|
||||||
name = name,
|
|
||||||
)
|
|
||||||
|
|
||||||
out(' trace_record_finish(&rec);',
|
|
||||||
'}',
|
|
||||||
'')
|
|
||||||
|
|
||||||
|
|
||||||
def h(events):
|
|
||||||
for event in events:
|
|
||||||
out('void %(api)s(%(args)s);',
|
|
||||||
api = event.api(),
|
|
||||||
args = event.args,
|
|
||||||
)
|
|
||||||
|
|
|
@ -19,31 +19,21 @@ from tracetool import out
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
|
|
||||||
def c(events):
|
def generate_h_begin(events):
|
||||||
pass
|
|
||||||
|
|
||||||
def h(events):
|
|
||||||
out('#include <stdio.h>',
|
out('#include <stdio.h>',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
'',
|
'')
|
||||||
)
|
|
||||||
|
|
||||||
for e in events:
|
|
||||||
argnames = ", ".join(e.args.names())
|
|
||||||
if len(e.args) > 0:
|
|
||||||
argnames = ", " + argnames
|
|
||||||
|
|
||||||
out('static inline void %(api)s(%(args)s)',
|
def generate_h(event):
|
||||||
'{',
|
argnames = ", ".join(event.args.names())
|
||||||
' bool _state = trace_event_get_state(%(event_id)s);',
|
if len(event.args) > 0:
|
||||||
' if (_state) {',
|
argnames = ", " + argnames
|
||||||
' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
|
|
||||||
' }',
|
out(' if (trace_event_get_state(%(event_id)s)) {',
|
||||||
'}',
|
' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
|
||||||
api = e.api(),
|
' }',
|
||||||
name = e.name,
|
event_id="TRACE_" + event.name.upper(),
|
||||||
args = e.args,
|
name=event.name,
|
||||||
event_id = "TRACE_" + e.name.upper(),
|
fmt=event.fmt.rstrip("\n"),
|
||||||
fmt = e.fmt.rstrip("\n"),
|
argnames=argnames)
|
||||||
argnames = argnames,
|
|
||||||
)
|
|
||||||
|
|
|
@ -18,66 +18,18 @@ from tracetool import out
|
||||||
|
|
||||||
PUBLIC = True
|
PUBLIC = True
|
||||||
|
|
||||||
def c(events):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
def generate_h_begin(events):
|
||||||
def h(events):
|
|
||||||
out('#include <lttng/tracepoint.h>',
|
out('#include <lttng/tracepoint.h>',
|
||||||
'#include "trace/generated-ust-provider.h"',
|
'#include "trace/generated-ust-provider.h"',
|
||||||
'')
|
'')
|
||||||
for e in events:
|
|
||||||
argnames = ", ".join(e.args.names())
|
|
||||||
if len(e.args) > 0:
|
|
||||||
argnames = ", " + argnames
|
|
||||||
|
|
||||||
out('static inline void %(api)s(%(args)s)',
|
|
||||||
'{',
|
|
||||||
' tracepoint(qemu, %(name)s%(tp_args)s);',
|
|
||||||
'}',
|
|
||||||
'',
|
|
||||||
api = e.api()
|
|
||||||
name = e.name,
|
|
||||||
args = e.args,
|
|
||||||
tp_args = argnames,
|
|
||||||
)
|
|
||||||
|
|
||||||
def ust_events_c(events):
|
def generate_h(event):
|
||||||
pass
|
argnames = ", ".join(event.args.names())
|
||||||
|
if len(event.args) > 0:
|
||||||
|
argnames = ", " + argnames
|
||||||
|
|
||||||
def ust_events_h(events):
|
out(' tracepoint(qemu, %(name)s%(tp_args)s);',
|
||||||
for e in events:
|
name=event.name,
|
||||||
if len(e.args) > 0:
|
tp_args=argnames)
|
||||||
out('TRACEPOINT_EVENT(',
|
|
||||||
' qemu,',
|
|
||||||
' %(name)s,',
|
|
||||||
' TP_ARGS(%(args)s),',
|
|
||||||
' TP_FIELDS(',
|
|
||||||
name = e.name,
|
|
||||||
args = ", ".join(", ".join(i) for i in e.args),
|
|
||||||
)
|
|
||||||
|
|
||||||
for t,n in e.args:
|
|
||||||
if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
|
|
||||||
out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
|
|
||||||
elif ('double' in t) or ('float' in t):
|
|
||||||
out(' ctf_float(' + t + ', ' + n + ', ' + n + ')')
|
|
||||||
elif ('char *' in t) or ('char*' in t):
|
|
||||||
out(' ctf_string(' + n + ', ' + n + ')')
|
|
||||||
elif ('void *' in t) or ('void*' in t):
|
|
||||||
out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')
|
|
||||||
|
|
||||||
out(' )',
|
|
||||||
')',
|
|
||||||
'')
|
|
||||||
|
|
||||||
else:
|
|
||||||
out('TRACEPOINT_EVENT(',
|
|
||||||
' qemu,',
|
|
||||||
' %(name)s,',
|
|
||||||
' TP_ARGS(void),',
|
|
||||||
' TP_FIELDS()',
|
|
||||||
')',
|
|
||||||
'',
|
|
||||||
name = e.name,
|
|
||||||
)
|
|
||||||
|
|
|
@ -20,17 +20,12 @@ All formats must generate their contents through the 'tracetool.out' routine.
|
||||||
Format functions
|
Format functions
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
All the following functions are optional, and no output will be generated if
|
======== ==================================================================
|
||||||
they do not exist.
|
|
||||||
|
|
||||||
======== =======================================================================
|
|
||||||
Function Description
|
Function Description
|
||||||
======== =======================================================================
|
======== ==================================================================
|
||||||
begin Called to generate the format-specific file header.
|
generate Called to generate a format-specific file.
|
||||||
end Called to generate the format-specific file footer.
|
======== ==================================================================
|
||||||
nop Called to generate the per-event contents when the event is disabled or
|
|
||||||
the selected backend is 'nop'.
|
|
||||||
======== =======================================================================
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||||
|
@ -79,25 +74,12 @@ def exists(name):
|
||||||
return tracetool.try_import("tracetool.format." + name)[1]
|
return tracetool.try_import("tracetool.format." + name)[1]
|
||||||
|
|
||||||
|
|
||||||
def _empty(events):
|
def generate(events, format, backend):
|
||||||
pass
|
if not exists(format):
|
||||||
|
raise ValueError("unknown format: %s" % format)
|
||||||
def generate_begin(name, events):
|
format = format.replace("-", "_")
|
||||||
"""Generate the header of the format-specific file."""
|
func = tracetool.try_import("tracetool.format." + format,
|
||||||
if not exists(name):
|
"generate")[1]
|
||||||
raise ValueError("unknown format: %s" % name)
|
if func is None:
|
||||||
|
raise AttributeError("format has no 'generate': %s" % format)
|
||||||
name = name.replace("-", "_")
|
func(events, backend)
|
||||||
func = tracetool.try_import("tracetool.format." + name,
|
|
||||||
"begin", _empty)[1]
|
|
||||||
func(events)
|
|
||||||
|
|
||||||
def generate_end(name, events):
|
|
||||||
"""Generate the footer of the format-specific file."""
|
|
||||||
if not exists(name):
|
|
||||||
raise ValueError("unknown format: %s" % name)
|
|
||||||
|
|
||||||
name = name.replace("-", "_")
|
|
||||||
func = tracetool.try_import("tracetool.format." + name,
|
|
||||||
"end", _empty)[1]
|
|
||||||
func(events)
|
|
||||||
|
|
|
@ -16,5 +16,13 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */')
|
events = [e for e in events
|
||||||
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
|
'')
|
||||||
|
backend.generate_begin(events)
|
||||||
|
for event in events:
|
||||||
|
backend.generate(event)
|
||||||
|
backend.generate_end(events)
|
||||||
|
|
|
@ -16,5 +16,27 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */')
|
events = [e for e in events
|
||||||
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
out('/* This file is autogenerated by tracetool, do not edit. */'
|
||||||
|
'',
|
||||||
|
'provider qemu {')
|
||||||
|
|
||||||
|
for e in events:
|
||||||
|
args = str(e.args)
|
||||||
|
|
||||||
|
# DTrace provider syntax expects foo() for empty
|
||||||
|
# params, not foo(void)
|
||||||
|
if args == 'void':
|
||||||
|
args = ''
|
||||||
|
|
||||||
|
# Define prototype for probe arguments
|
||||||
|
out('',
|
||||||
|
'probe %(name)s(%(args)s);',
|
||||||
|
name=e.name,
|
||||||
|
args=args)
|
||||||
|
|
||||||
|
out('',
|
||||||
|
'};')
|
||||||
|
|
|
@ -16,14 +16,13 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#include "trace.h"',
|
'#include "trace.h"',
|
||||||
'#include "trace/generated-events.h"',
|
'#include "trace/generated-events.h"',
|
||||||
'#include "trace/control.h"',
|
'#include "trace/control.h"',
|
||||||
'',
|
'')
|
||||||
)
|
|
||||||
|
|
||||||
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
|
out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
|
||||||
|
|
||||||
|
@ -31,9 +30,7 @@ def begin(events):
|
||||||
out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
|
out(' { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
|
||||||
id = "TRACE_" + e.name.upper(),
|
id = "TRACE_" + e.name.upper(),
|
||||||
name = e.name,
|
name = e.name,
|
||||||
sstate = "TRACE_%s_ENABLED" % e.name.upper(),
|
sstate = "TRACE_%s_ENABLED" % e.name.upper())
|
||||||
)
|
|
||||||
|
|
||||||
out('};',
|
out('};',
|
||||||
'',
|
'')
|
||||||
)
|
|
||||||
|
|
|
@ -16,15 +16,14 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#ifndef TRACE__GENERATED_EVENTS_H',
|
'#ifndef TRACE__GENERATED_EVENTS_H',
|
||||||
'#define TRACE__GENERATED_EVENTS_H',
|
'#define TRACE__GENERATED_EVENTS_H',
|
||||||
'',
|
'',
|
||||||
'#include <stdbool.h>',
|
'#include <stdbool.h>',
|
||||||
''
|
'')
|
||||||
)
|
|
||||||
|
|
||||||
# event identifiers
|
# event identifiers
|
||||||
out('typedef enum {')
|
out('typedef enum {')
|
||||||
|
@ -33,8 +32,7 @@ def begin(events):
|
||||||
out(' TRACE_%s,' % e.name.upper())
|
out(' TRACE_%s,' % e.name.upper())
|
||||||
|
|
||||||
out(' TRACE_EVENT_COUNT',
|
out(' TRACE_EVENT_COUNT',
|
||||||
'} TraceEventID;',
|
'} TraceEventID;')
|
||||||
)
|
|
||||||
|
|
||||||
# static state
|
# static state
|
||||||
for e in events:
|
for e in events:
|
||||||
|
@ -46,5 +44,4 @@ def begin(events):
|
||||||
|
|
||||||
out('#include "trace/event-internal.h"',
|
out('#include "trace/event-internal.h"',
|
||||||
'',
|
'',
|
||||||
'#endif /* TRACE__GENERATED_EVENTS_H */',
|
'#endif /* TRACE__GENERATED_EVENTS_H */')
|
||||||
)
|
|
||||||
|
|
|
@ -16,23 +16,29 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#ifndef TRACE__GENERATED_TRACERS_H',
|
'#ifndef TRACE__GENERATED_TRACERS_H',
|
||||||
'#define TRACE__GENERATED_TRACERS_H',
|
'#define TRACE__GENERATED_TRACERS_H',
|
||||||
'',
|
'',
|
||||||
'#include "qemu-common.h"')
|
'#include "qemu-common.h"',
|
||||||
|
'')
|
||||||
|
|
||||||
def end(events):
|
backend.generate_begin(events)
|
||||||
out('#endif /* TRACE__GENERATED_TRACERS_H */')
|
|
||||||
|
|
||||||
def nop(events):
|
|
||||||
for e in events:
|
for e in events:
|
||||||
out('',
|
out('',
|
||||||
'static inline void %(api)s(%(args)s)',
|
'static inline void %(api)s(%(args)s)',
|
||||||
'{',
|
'{',
|
||||||
'}',
|
api=e.api(),
|
||||||
api = e.api(),
|
args=e.args)
|
||||||
args = e.args,
|
|
||||||
)
|
if "disable" not in e.properties:
|
||||||
|
backend.generate(e)
|
||||||
|
|
||||||
|
out('}')
|
||||||
|
|
||||||
|
backend.generate_end(events)
|
||||||
|
|
||||||
|
out('#endif /* TRACE__GENERATED_TRACERS_H */')
|
||||||
|
|
|
@ -6,7 +6,7 @@ Generate .stp file (DTrace with SystemTAP only).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
__author__ = "Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||||
__copyright__ = "Copyright 2012, Lluís Vilanova <vilanova@ac.upc.edu>"
|
__copyright__ = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
|
||||||
__license__ = "GPL version 2 or (at your option) any later version"
|
__license__ = "GPL version 2 or (at your option) any later version"
|
||||||
|
|
||||||
__maintainer__ = "Stefan Hajnoczi"
|
__maintainer__ = "Stefan Hajnoczi"
|
||||||
|
@ -14,7 +14,43 @@ __email__ = "stefanha@linux.vnet.ibm.com"
|
||||||
|
|
||||||
|
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
from tracetool.backend.dtrace import binary, probeprefix
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
# Technically 'self' is not used by systemtap yet, but
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */')
|
# they recommended we keep it in the reserved list anyway
|
||||||
|
RESERVED_WORDS = (
|
||||||
|
'break', 'catch', 'continue', 'delete', 'else', 'for',
|
||||||
|
'foreach', 'function', 'global', 'if', 'in', 'limit',
|
||||||
|
'long', 'next', 'probe', 'return', 'self', 'string',
|
||||||
|
'try', 'while'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(events, backend):
|
||||||
|
events = [e for e in events
|
||||||
|
if "disable" not in e.properties]
|
||||||
|
|
||||||
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
|
'')
|
||||||
|
|
||||||
|
for e in events:
|
||||||
|
# Define prototype for probe arguments
|
||||||
|
out('probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")',
|
||||||
|
'{',
|
||||||
|
probeprefix=probeprefix(),
|
||||||
|
name=e.name,
|
||||||
|
binary=binary())
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
if len(e.args) > 0:
|
||||||
|
for name in e.args.names():
|
||||||
|
# Append underscore to reserved keywords
|
||||||
|
if name in RESERVED_WORDS:
|
||||||
|
name += '_'
|
||||||
|
out(' %s = $arg%d;' % (name, i))
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
out('}')
|
||||||
|
|
||||||
|
out()
|
||||||
|
|
|
@ -16,7 +16,10 @@ __email__ = "stefanha@redhat.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
|
events = [e for e in events
|
||||||
|
if "disabled" not in e.properties]
|
||||||
|
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#define TRACEPOINT_DEFINE',
|
'#define TRACEPOINT_DEFINE',
|
||||||
|
|
|
@ -16,7 +16,10 @@ __email__ = "stefanha@redhat.com"
|
||||||
from tracetool import out
|
from tracetool import out
|
||||||
|
|
||||||
|
|
||||||
def begin(events):
|
def generate(events, backend):
|
||||||
|
events = [e for e in events
|
||||||
|
if "disabled" not in e.properties]
|
||||||
|
|
||||||
out('/* This file is autogenerated by tracetool, do not edit. */',
|
out('/* This file is autogenerated by tracetool, do not edit. */',
|
||||||
'',
|
'',
|
||||||
'#undef TRACEPOINT_PROVIDER',
|
'#undef TRACEPOINT_PROVIDER',
|
||||||
|
@ -50,7 +53,40 @@ def begin(events):
|
||||||
'#endif',
|
'#endif',
|
||||||
'')
|
'')
|
||||||
|
|
||||||
def end(events):
|
for e in events:
|
||||||
|
if len(e.args) > 0:
|
||||||
|
out('TRACEPOINT_EVENT(',
|
||||||
|
' qemu,',
|
||||||
|
' %(name)s,',
|
||||||
|
' TP_ARGS(%(args)s),',
|
||||||
|
' TP_FIELDS(',
|
||||||
|
name=e.name,
|
||||||
|
args=", ".join(", ".join(i) for i in e.args))
|
||||||
|
|
||||||
|
for t, n in e.args:
|
||||||
|
if ('int' in t) or ('long' in t) or ('unsigned' in t) or ('size_t' in t):
|
||||||
|
out(' ctf_integer(' + t + ', ' + n + ', ' + n + ')')
|
||||||
|
elif ('double' in t) or ('float' in t):
|
||||||
|
out(' ctf_float(' + t + ', ' + n + ', ' + n + ')')
|
||||||
|
elif ('char *' in t) or ('char*' in t):
|
||||||
|
out(' ctf_string(' + n + ', ' + n + ')')
|
||||||
|
elif ('void *' in t) or ('void*' in t):
|
||||||
|
out(' ctf_integer_hex(unsigned long, ' + n + ', ' + n + ')')
|
||||||
|
|
||||||
|
out(' )',
|
||||||
|
')',
|
||||||
|
'')
|
||||||
|
|
||||||
|
else:
|
||||||
|
out('TRACEPOINT_EVENT(',
|
||||||
|
' qemu,',
|
||||||
|
' %(name)s,',
|
||||||
|
' TP_ARGS(void),',
|
||||||
|
' TP_FIELDS()',
|
||||||
|
')',
|
||||||
|
'',
|
||||||
|
name=e.name)
|
||||||
|
|
||||||
out('#endif /* TRACE__GENERATED_UST_H */',
|
out('#endif /* TRACE__GENERATED_UST_H */',
|
||||||
'',
|
'',
|
||||||
'/* This part must be outside ifdef protection */',
|
'/* This part must be outside ifdef protection */',
|
||||||
|
|
|
@ -31,7 +31,7 @@ $(obj)/generated-events.h: $(obj)/generated-events.h-timestamp
|
||||||
$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
|
$(obj)/generated-events.h-timestamp: $(SRC_PATH)/trace-events
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=events-h \
|
--format=events-h \
|
||||||
--backend=events \
|
--backend=$(TRACE_BACKEND) \
|
||||||
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
|
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
|
||||||
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
|
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ $(obj)/generated-events.c: $(obj)/generated-events.c-timestamp $(BUILD_DIR)/conf
|
||||||
$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
|
$(obj)/generated-events.c-timestamp: $(SRC_PATH)/trace-events
|
||||||
$(call quiet-command,$(TRACETOOL) \
|
$(call quiet-command,$(TRACETOOL) \
|
||||||
--format=events-c \
|
--format=events-c \
|
||||||
--backend=events \
|
--backend=$(TRACE_BACKEND) \
|
||||||
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
|
< $< > $@," GEN $(patsubst %-timestamp,%,$@)")
|
||||||
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
|
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue