diff options
author | Lluís Vilanova <vilanova@ac.upc.edu> | 2014-02-23 20:37:40 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2014-05-07 19:07:18 +0200 |
commit | 1dad2ce97345f3424c4990cb232b40a35d5e936b (patch) | |
tree | 1e7ebf28f38266aca24947f76294f8b6ac340bc5 /scripts/tracetool/backend | |
parent | ef0bd3bba674769c7d36bf400fc4fe7ea43244c5 (diff) | |
download | qemu-1dad2ce97345f3424c4990cb232b40a35d5e936b.zip qemu-1dad2ce97345f3424c4990cb232b40a35d5e936b.tar.gz qemu-1dad2ce97345f3424c4990cb232b40a35d5e936b.tar.bz2 |
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>
Diffstat (limited to 'scripts/tracetool/backend')
-rw-r--r-- | scripts/tracetool/backend/__init__.py | 72 | ||||
-rw-r--r-- | scripts/tracetool/backend/dtrace.py | 79 | ||||
-rw-r--r-- | scripts/tracetool/backend/events.py | 23 | ||||
-rw-r--r-- | scripts/tracetool/backend/ftrace.py | 56 | ||||
-rw-r--r-- | scripts/tracetool/backend/simple.py | 130 | ||||
-rw-r--r-- | scripts/tracetool/backend/stderr.py | 42 | ||||
-rw-r--r-- | scripts/tracetool/backend/ust.py | 64 |
7 files changed, 153 insertions, 313 deletions
diff --git a/scripts/tracetool/backend/__init__.py b/scripts/tracetool/backend/__init__.py index 88f94fd..5e36f04 100644 --- a/scripts/tracetool/backend/__init__.py +++ b/scripts/tracetool/backend/__init__.py @@ -30,17 +30,24 @@ PUBLIC If exists and is set to 'True', the backend is considered "public". Backend functions ----------------- -======== ======================================================================= -Function Description -======== ======================================================================= -<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 - considered not compatible with the given format. -======== ======================================================================= +All the following functions are optional, and no output will be generated if +they do not exist. + +=============================== ============================================== +Function Description +=============================== ============================================== +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>" -__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" __maintainer__ = "Stefan Hajnoczi" @@ -91,39 +98,24 @@ def exists(name): return tracetool.try_import("tracetool.backend." + name)[1] -def compatible(backend, format): - """Whether a backend is compatible with the given format.""" - if not exists(backend): - raise ValueError("unknown backend: %s" % backend) - - backend = backend.replace("-", "_") - format = format.replace("-", "_") - - if backend == "nop": - return True - else: - func = tracetool.try_import("tracetool.backend." + backend, - format, None)[1] - return func is not None - - -def _empty(events): - pass +class Wrapper: + def __init__(self, backend, format): + self._backend = backend.replace("-", "_") + self._format = format.replace("-", "_") + assert exists(self._backend) + assert tracetool.format.exists(self._format) -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)) + def _run_function(self, name, *args, **kwargs): + func = tracetool.try_import("tracetool.backend." + self._backend, + name % self._format, None)[1] + if func is not None: + func(*args, **kwargs) - backend = backend.replace("-", "_") - format = format.replace("-", "_") + def generate_begin(self, events): + self._run_function("generate_%s_begin", events) - if backend == "nop": - func = tracetool.try_import("tracetool.format." + format, - "nop", _empty)[1] - else: - func = tracetool.try_import("tracetool.backend." + backend, - format, None)[1] + def generate(self, event): + self._run_function("generate_%s", event) - func(events) + def generate_end(self, events): + self._run_function("generate_%s_end", events) diff --git a/scripts/tracetool/backend/dtrace.py b/scripts/tracetool/backend/dtrace.py index 3c369c4..fabfe99 100644 --- a/scripts/tracetool/backend/dtrace.py +++ b/scripts/tracetool/backend/dtrace.py @@ -21,7 +21,7 @@ PUBLIC = True PROBEPREFIX = None -def _probeprefix(): +def probeprefix(): if PROBEPREFIX is None: raise ValueError("you must set PROBEPREFIX") return PROBEPREFIX @@ -29,81 +29,18 @@ def _probeprefix(): BINARY = None -def _binary(): +def binary(): if BINARY is None: raise ValueError("you must set BINARY") return BINARY -def c(events): - pass - - -def h(events): +def generate_h_begin(events): 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 d(events): - out('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('', - '};') - - -# 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() + +def generate_h(event): + out(' QEMU_%(uppername)s(%(argnames)s);', + uppername=event.name.upper(), + argnames=", ".join(event.args.names())) diff --git a/scripts/tracetool/backend/events.py b/scripts/tracetool/backend/events.py deleted file mode 100644 index 5afce3e..0000000 --- a/scripts/tracetool/backend/events.py +++ /dev/null @@ -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 diff --git a/scripts/tracetool/backend/ftrace.py b/scripts/tracetool/backend/ftrace.py index 888c361..d798c71 100644 --- a/scripts/tracetool/backend/ftrace.py +++ b/scripts/tracetool/backend/ftrace.py @@ -19,36 +19,30 @@ from tracetool import out PUBLIC = True -def c(events): - pass - -def h(events): +def generate_h_begin(events): out('#include "trace/ftrace.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)', - '{', - ' char ftrace_buf[MAX_TRACE_STRLEN];', - ' int unused __attribute__ ((unused));', - ' int trlen;', - ' bool _state = trace_event_get_state(%(event_id)s);', - ' if (_state) {', - ' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,', - ' "%(name)s " %(fmt)s "\\n" %(argnames)s);', - ' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);', - ' unused = write(trace_marker_fd, ftrace_buf, trlen);', - ' }', - '}', - name = e.name, - args = e.args, - event_id = "TRACE_" + e.name.upper(), - fmt = e.fmt.rstrip("\n"), - argnames = argnames, - ) + '') + + +def generate_h(event): + argnames = ", ".join(event.args.names()) + if len(event.args) > 0: + argnames = ", " + argnames + + out(' {', + ' char ftrace_buf[MAX_TRACE_STRLEN];', + ' int unused __attribute__ ((unused));', + ' int trlen;', + ' if (trace_event_get_state(%(event_id)s)) {', + ' trlen = snprintf(ftrace_buf, MAX_TRACE_STRLEN,', + ' "%(name)s " %(fmt)s "\\n" %(argnames)s);', + ' trlen = MIN(trlen, MAX_TRACE_STRLEN - 1);', + ' unused = write(trace_marker_fd, ftrace_buf, trlen);', + ' }', + ' }', + name=event.name, + args=event.args, + event_id="TRACE_" + event.name.upper(), + fmt=event.fmt.rstrip("\n"), + argnames=argnames) diff --git a/scripts/tracetool/backend/simple.py b/scripts/tracetool/backend/simple.py index ca48e12..e8c2cd5 100644 --- a/scripts/tracetool/backend/simple.py +++ b/scripts/tracetool/backend/simple.py @@ -26,76 +26,74 @@ def is_string(arg): else: 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"', '#include "trace/control.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;', + ' }', '', - ) - - for num, event in enumerate(events): - out('void %(api)s(%(args)s)', - '{', - ' TraceBufferRecord rec;', - api = event.api(), - args = event.args, - ) - sizes = [] + ' 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) + + if len(event.args) > 0: for type_, name in event.args: + # string 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) + 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: - sizes.append("8") - sizestr = " + ".join(sizes) - if len(event.args) == 0: - sizestr = '0' - - - 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, - ) + out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);', + name=name) + + out(' trace_record_finish(&rec);', + '}', + '') diff --git a/scripts/tracetool/backend/stderr.py b/scripts/tracetool/backend/stderr.py index 6681e26..2a1e906 100644 --- a/scripts/tracetool/backend/stderr.py +++ b/scripts/tracetool/backend/stderr.py @@ -19,31 +19,21 @@ from tracetool import out PUBLIC = True -def c(events): - pass - -def h(events): +def generate_h_begin(events): out('#include <stdio.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)', - '{', - ' bool _state = trace_event_get_state(%(event_id)s);', - ' if (_state) {', - ' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);', - ' }', - '}', - api = e.api(), - name = e.name, - args = e.args, - event_id = "TRACE_" + e.name.upper(), - fmt = e.fmt.rstrip("\n"), - argnames = argnames, - ) + '') + + +def generate_h(event): + argnames = ", ".join(event.args.names()) + if len(event.args) > 0: + argnames = ", " + argnames + + out(' if (trace_event_get_state(%(event_id)s)) {', + ' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);', + ' }', + event_id="TRACE_" + event.name.upper(), + name=event.name, + fmt=event.fmt.rstrip("\n"), + argnames=argnames) diff --git a/scripts/tracetool/backend/ust.py b/scripts/tracetool/backend/ust.py index 2fca4d2..2f8f44a 100644 --- a/scripts/tracetool/backend/ust.py +++ b/scripts/tracetool/backend/ust.py @@ -18,66 +18,18 @@ from tracetool import out PUBLIC = True -def c(events): - pass - -def h(events): +def generate_h_begin(events): out('#include <lttng/tracepoint.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): - pass - -def ust_events_h(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(' )', - ')', - '') +def generate_h(event): + argnames = ", ".join(event.args.names()) + if len(event.args) > 0: + argnames = ", " + argnames - else: - out('TRACEPOINT_EVENT(', - ' qemu,', - ' %(name)s,', - ' TP_ARGS(void),', - ' TP_FIELDS()', - ')', - '', - name = e.name, - ) + out(' tracepoint(qemu, %(name)s%(tp_args)s);', + name=event.name, + tp_args=argnames) |