@@ -52,12 +52,12 @@ GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c
GENERATED_HEADERS += trace/generated-tracers.h
-ifeq ($(TRACE_BACKEND),dtrace)
+ifeq ($(findstring dtrace,$(TRACE_BACKEND)),dtrace)
GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif
GENERATED_SOURCES += trace/generated-tracers.c
-ifeq ($(TRACE_BACKEND),ust)
+ifeq ($(findstring ust,$(TRACE_BACKEND)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c
endif
@@ -3363,7 +3363,7 @@ fi
##########################################
# For 'ust' backend, test if ust headers are present
-if test "$trace_backend" = "ust"; then
+if echo "$trace_backend" | grep ust >/dev/null; then
cat > $TMPC << EOF
#include <lttng/tracepoint.h>
int main(void) { return 0; }
@@ -3389,7 +3389,7 @@ fi
##########################################
# For 'dtrace' backend, test if 'dtrace' command is present
-if test "$trace_backend" = "dtrace"; then
+if echo "$trace_backend" | grep dtrace >/dev/null; then
if ! has 'dtrace' ; then
error_exit "dtrace command is not found in PATH $PATH"
fi
@@ -4280,26 +4280,27 @@ echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
if test "$trace_backend" = "nop"; then
echo "CONFIG_TRACE_NOP=y" >> $config_host_mak
fi
-if test "$trace_backend" = "simple"; then
+
+if echo "$trace_backend" | grep simple >/dev/null; then
echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak
trace_default=no
# Set the appropriate trace file.
trace_file="\"$trace_file-\" FMT_pid"
fi
-if test "$trace_backend" = "stderr"; then
+if echo "$trace_backend" | grep stderr >/dev/null; then
echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak
trace_default=no
fi
-if test "$trace_backend" = "ust"; then
+if echo "$trace_backend" | grep ust >/dev/null; then
echo "CONFIG_TRACE_UST=y" >> $config_host_mak
fi
-if test "$trace_backend" = "dtrace"; then
+if echo "$trace_backend" | grep dtrace >/dev/null; then
echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak
if test "$trace_backend_stap" = "yes" ; then
echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
fi
fi
-if test "$trace_backend" = "ftrace"; then
+if echo "$trace_backend" | grep ftrace >/dev/null; then
if test "$linux" = "yes" ; then
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
trace_default=no
@@ -4307,6 +4308,7 @@ if test "$trace_backend" = "ftrace"; then
feature_not_found "ftrace(trace backend)"
fi
fi
+
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
if test "$trace_default" = "yes"; then
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
@@ -112,10 +112,11 @@ def main(args):
error_opt("backend not set")
if check_backend:
- if tracetool.backend.exists(arg_backend):
- sys.exit(0)
- else:
- sys.exit(1)
+ for backend in arg_backend.split(","):
+ if tracetool.backend.exists(backend):
+ sys.exit(0)
+ else:
+ sys.exit(1)
if arg_format == "stap":
if binary is None:
@@ -242,16 +242,23 @@ def generate(fevents, format, backend,
if not tracetool.format.exists(mformat):
raise TracetoolError("unknown format: %s" % format)
- backend = str(backend)
- if len(backend) is 0:
- raise TracetoolError("backend not set")
- mbackend = backend.replace("-", "_")
- if not tracetool.backend.exists(mbackend):
- raise TracetoolError("unknown backend: %s" % backend)
+ backends = str(backend).split(",")
+ for backend in backends:
+ if len(backend) is 0:
+ raise TracetoolError("backend not set")
- if not tracetool.backend.compatible(mbackend, mformat):
- raise TracetoolError("backend '%s' not compatible with format '%s'" %
- (backend, format))
+ # At least one backend must support the format
+ compat = False
+ for backend in backends:
+ mbackend = backend.replace("-", "_")
+ if not tracetool.backend.exists(mbackend):
+ raise TracetoolError("unknown backend: %s" % backend)
+
+ compat |= tracetool.backend.compatible(mbackend, mformat)
+
+ if not compat:
+ raise TracetoolError("backends '%s' not compatible with format '%s'" %
+ (",".join(backends), format))
import tracetool.backend.dtrace
tracetool.backend.dtrace.BINARY = binary
@@ -259,15 +266,15 @@ def generate(fevents, format, backend,
events = _read_events(fevents)
- if backend == "nop":
+ if backends == ["nop"]:
( e.properies.add("disable") for e in events )
tracetool.format.generate_begin(mformat, events)
- tracetool.backend.generate("nop", format,
+ tracetool.backend.generate(["nop"], format,
[ e
for e in events
if "disable" in e.properties ])
- tracetool.backend.generate(backend, format,
+ tracetool.backend.generate(backends, format,
[ e
for e in events
if "disable" not in e.properties ])
@@ -102,28 +102,34 @@ def compatible(backend, format):
if backend == "nop":
return True
else:
- func = tracetool.try_import("tracetool.backend." + backend,
- format, None)[1]
- return func is not None
+ # Check whether format is declared in supported_formats.
+ supported_formats = tracetool.try_import("tracetool.backend." + backend,
+ "supported_formats")[1]
+ return format in supported_formats
def _empty(events):
pass
-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 generate(backends, format, events):
+ """Generate the per-event output for the given (backends, format) pair."""
- backend = backend.replace("-", "_")
+ # At least one backend must support the format
+ compat = False
+ for backend in backends:
+ compat |= compatible(backend, format)
+ if not compat:
+ raise ValueError("backends '%s' not compatible with format '%s'" %
+ (",".join(backends), format))
+
+ backends = map(lambda x: x.replace("-", "_"), backends)
format = format.replace("-", "_")
- if backend == "nop":
+ if backends == ["nop"]:
func = tracetool.try_import("tracetool.format." + format,
"nop", _empty)[1]
+ func(events)
else:
- func = tracetool.try_import("tracetool.backend." + backend,
+ func = tracetool.try_import("tracetool.backend.common",
format, None)[1]
-
- func(events)
+ func(backends, events)
new file mode 100644
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+Common part of tracing backend.
+"""
+
+__author__ = "Kazuya Saito <saito.kazuya@jp.fujitsu.com>"
+__copyright__ = "Copyright (C) 2014 Fujitsu, Ltd."
+__license__ = "GPL version 2 or (at your option) any later version"
+
+__maintainer__ = "Stefan Hajnoczi"
+__email__ = "stefanha@redhat.com"
+
+
+from tracetool import out
+import tracetool
+
+PUBLIC = False
+
+def c(backends, events):
+ func_head_lst = []
+ func_body_lst = []
+ for backend in backends:
+ func_head_lst.append(tracetool.try_import("tracetool.backend." + backend,
+ "c_head", None)[1])
+ func_body_lst.append(tracetool.try_import("tracetool.backend." + backend,
+ "c_body", None)[1])
+
+ out('#include "trace/control.h"',
+ '#include "trace.h"',
+ '',
+ )
+ for func_head in func_head_lst:
+ func_head()
+
+ for num, event in enumerate(events):
+ out('void trace_%(name)s(%(args)s) {',
+ name = event.name,
+ args = event.args)
+
+ for func_body in func_body_lst:
+ func_body(num, event)
+ out('}')
+
+def h(backends, events):
+ func_head_lst = []
+ func_body_lst = []
+ for backend in backends:
+ func_head_lst.append(tracetool.try_import("tracetool.backend." + backend,
+ "h_head", None)[1])
+ func_body_lst.append(tracetool.try_import("tracetool.backend." + backend,
+ "h_body", None)[1])
+
+ for func_head in func_head_lst:
+ func_head()
+
+ for event in events:
+ out('void trace_%(name)s(%(args)s);',
+ name = event.name,
+ args = event.args)
+
+ for func_body in func_body_lst:
+ func_body(event)
+
+def stap(backends, events):
+ # Only dtrace backend has format "stap"
+ func = tracetool.try_import("tracetool.backend.dtrace",
+ "stap", None)[1]
+ func(events)
+
+def d(backends, events):
+ # Only dtrace backend has format "d"
+ func = tracetool.try_import("tracetool.backend.dtrace",
+ "d", None)[1]
+ func(events)
+
+def events_h(backends, events):
+ # Only events backend has format "events_h"
+ func = tracetool.try_import("tracetool.backend.events",
+ "events_h", None)[1]
+ func(events)
+
+def events_c(backends, events):
+ # Only events backend has format "events_c"
+ func = tracetool.try_import("tracetool.backend.events",
+ "events_c", None)[1]
+ func(events)
+
+def ust_events_c(backends, events):
+ # Only ust backend has format "ust_events_c"
+ func = tracetool.try_import("tracetool.backend.ust",
+ "ust_events_c", None)[1]
+ func(events)
+
+def ust_events_h(backends, events):
+ # Only ust backend has format "ust_events_h"
+ func = tracetool.try_import("tracetool.backend.ust",
+ "ust_events_h", None)[1]
+ func(events)
+
@@ -21,6 +21,8 @@ PUBLIC = True
PROBEPREFIX = None
+supported_formats = ['c', 'h', 'd', 'stap']
+
def _probeprefix():
if PROBEPREFIX is None:
raise ValueError("you must set PROBEPREFIX")
@@ -34,25 +36,25 @@ def _binary():
raise ValueError("you must set BINARY")
return BINARY
-
-def c(events):
+def c_head():
pass
-
-def h(events):
- out('#include "trace/generated-tracers-dtrace.h"',
+def c_body(num, event):
+ out('{ /* dtrace */',
+ ' QEMU_%(uppername)s(%(argnames)s);',
+ '}',
+ uppername = event.name.upper(),
+ argnames = ", ".join(event.args.names()),
+ )
+
+def h_head():
+ out('#define SDT_USE_VARIADIC',
+ '#include <sys/sdt.h>',
+ '#include "trace/generated-tracers-dtrace.h"',
'')
- for e in events:
- out('static inline void trace_%(name)s(%(args)s) {',
- ' QEMU_%(uppername)s(%(argnames)s);',
- '}',
- name = e.name,
- args = e.args,
- uppername = e.name.upper(),
- argnames = ", ".join(e.args.names()),
- )
-
+def h_body(event):
+ pass
def d(events):
out('provider qemu {')
@@ -107,3 +109,4 @@ def stap(events):
out('}')
out()
+
@@ -15,7 +15,7 @@ __license__ = "GPL version 2 or (at your option) any later version"
__maintainer__ = "Stefan Hajnoczi"
__email__ = "stefanha@linux.vnet.ibm.com"
-
+supported_formats = ['events_c', 'events_h']
def events_h(events):
pass
@@ -18,37 +18,41 @@ from tracetool import out
PUBLIC = True
+supported_formats = ['c', 'h']
-def c(events):
- pass
+def c_head():
+ out('#include "trace/ftrace.h"',
+ '',
+ )
-def h(events):
+def c_body(num, event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
+
+ out('{ /* ftrace */',
+ ' 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 = event.name,
+ args = event.args,
+ event_id = "TRACE_" + event.name.upper(),
+ fmt = event.fmt.rstrip("\n"),
+ argnames = argnames,
+ )
+
+def h_head():
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 h_body(event):
+ pass
@@ -18,6 +18,7 @@ from tracetool import out
PUBLIC = True
+supported_formats = ['c', 'h']
def is_string(arg):
strtype = ('const char*', 'char*', 'const char *', 'char *')
@@ -26,76 +27,73 @@ def is_string(arg):
else:
return False
-def c(events):
- out('#include "trace.h"',
- '#include "trace/control.h"',
- '#include "trace/simple.h"',
+def c_head():
+ out('#include "trace/simple.h"',
'',
)
- for num, event in enumerate(events):
- out('void trace_%(name)s(%(args)s)',
- '{',
- ' TraceBufferRecord rec;',
- name = event.name,
- args = event.args,
- )
- sizes = []
+def c_body(num, event):
+ out('{ /* simple */',
+ ' TraceBufferRecord rec;',
+ name = event.name,
+ 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('',
+ ' 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_enum)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(' 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,
+ )
+ # pointer var (not string)
+ elif type_.endswith('*'):
+ out(' trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
name = name,
)
- strsizeinfo = "4 + arg%s_len" % name
- sizes.append(strsizeinfo)
+ # 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 trace_%(name)s(%(args)s);',
- name = event.name,
- args = event.args,
- )
+ out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
+ name = name,
+ )
+
+ out(' trace_record_finish(&rec);',
+ '}',
+ '')
+
+
+def h_head():
+ out('#include "trace/simple.h"',
+ '',
+ )
+def h_body(event):
+ pass
@@ -18,31 +18,34 @@ from tracetool import out
PUBLIC = True
+supported_formats = ['c', 'h']
-def c(events):
+def c_head():
pass
-def h(events):
+def c_body(num, event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
+
+ out('{ /* stderr */',
+ ' bool _state = trace_event_get_state(%(event_id)s);',
+ ' if (_state) {',
+ ' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
+ ' }',
+ '}',
+ name = event.name,
+ args = event.args,
+ event_id = "TRACE_" + event.name.upper(),
+ fmt = event.fmt.rstrip("\n"),
+ argnames = argnames,
+ )
+
+def h_head():
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 trace_%(name)s(%(args)s)',
- '{',
- ' bool _state = trace_event_get_state(%(event_id)s);',
- ' if (_state) {',
- ' fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);',
- ' }',
- '}',
- name = e.name,
- args = e.args,
- event_id = "TRACE_" + e.name.upper(),
- fmt = e.fmt.rstrip("\n"),
- argnames = argnames,
- )
+def h_body(event):
+ pass
@@ -17,29 +17,31 @@ from tracetool import out
PUBLIC = True
+supported_formats = ['c', 'h', 'ust_events_c', 'ust_events_h']
-def c(events):
+def c_head():
pass
+def c_body(num, event):
+ argnames = ", ".join(event.args.names())
+ if len(event.args) > 0:
+ argnames = ", " + argnames
-def h(events):
+ out('{ /* ust */',
+ ' tracepoint(qemu, %(name)s%(tp_args)s);',
+ '}',
+ name = event.name,
+ args = event.args,
+ tp_args = argnames,
+ )
+
+def h_head():
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 trace_%(name)s(%(args)s)',
- '{',
- ' tracepoint(qemu, %(name)s%(tp_args)s);',
- '}',
- '',
- name = e.name,
- args = e.args,
- tp_args = argnames,
- )
+
+def h_body(event):
+ pass
def ust_events_c(events):
pass
@@ -79,4 +81,4 @@ def ust_events_h(events):
')',
'',
name = e.name,
- )
\ No newline at end of file
+ )
@@ -3,7 +3,7 @@
######################################################################
# Auto-generated event descriptions for LTTng ust code
-ifeq ($(TRACE_BACKEND),ust)
+ifeq ($(findstring ust,$(TRACE_BACKEND)),ust)
$(obj)/generated-ust-provider.h: $(obj)/generated-ust-provider.h-timestamp
$(obj)/generated-ust-provider.h-timestamp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \
@@ -60,7 +60,7 @@ $(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/conf
######################################################################
# Auto-generated tracing routines (non-DTrace)
-ifneq ($(TRACE_BACKEND),dtrace)
+ifneq ($(findstring dtrace,$(TRACE_BACKEND)),dtrace)
$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
@cmp -s $< $@ || cp $< $@
$(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
@@ -79,7 +79,14 @@ endif
# Normal practice is to name DTrace probe file with a '.d' extension
# but that gets picked up by QEMU's Makefile as an external dependency
# rule file. So we use '.dtrace' instead
-ifeq ($(TRACE_BACKEND),dtrace)
+ifeq ($(findstring dtrace,$(TRACE_BACKEND)),dtrace)
+$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
+ @cmp -s $< $@ || cp $< $@
+$(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ $(call quiet-command,$(TRACETOOL) \
+ --format=c \
+ --backend=$(TRACE_BACKEND) \
+ < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
$(obj)/generated-tracers.dtrace: $(obj)/generated-tracers.dtrace-timestamp
$(obj)/generated-tracers.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \
@@ -91,15 +98,18 @@ $(obj)/generated-tracers.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)
$(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers.dtrace
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN $@")
-$(obj)/generated-tracers.o: $(obj)/generated-tracers.dtrace
+$(obj)/generated-tracers.o: $(obj)/generated-tracers.dtrace $(obj)/generated-tracers.c $(obj)/generated-tracers.h
endif
######################################################################
# Backend code
-util-obj-$(CONFIG_TRACE_DEFAULT) += default.o
+ifeq ($(CONFIG_TRACE_DEFAULT),y)
+util-obj-y += default.o
+else
+util-obj-y += multi.o
+endif
util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o
-util-obj-$(CONFIG_TRACE_STDERR) += stderr.o
util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
util-obj-y += control.o
@@ -42,35 +42,13 @@ static int find_debugfs(char *debugfs)
return 1;
}
-void trace_print_events(FILE *stream, fprintf_function stream_printf)
-{
- TraceEventID i;
-
- for (i = 0; i < trace_event_count(); i++) {
- TraceEvent *ev = trace_event_id(i);
- stream_printf(stream, "%s [Event ID %u] : state %u\n",
- trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
- }
-}
-
-void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
-{
- ev->dstate = state;
-}
-
-bool trace_backend_init(const char *events, const char *file)
+bool ftrace_backend_init(const char *events, const char *file)
{
char debugfs[PATH_MAX];
char path[PATH_MAX];
int debugfs_found;
int trace_fd = -1;
- if (file) {
- fprintf(stderr, "error: -trace file=...: "
- "option not supported by the selected tracing backend\n");
- return false;
- }
-
debugfs_found = find_debugfs(debugfs);
if (debugfs_found) {
snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs);
@@ -97,6 +75,5 @@ bool trace_backend_init(const char *events, const char *file)
return false;
}
- trace_backend_init_events(events);
return true;
}
@@ -6,5 +6,6 @@
#define STR(x) _STR(x)
extern int trace_marker_fd;
+bool ftrace_backend_init(const char *events, const char *file);
#endif /* ! TRACE_FTRACE_H */
new file mode 100644
@@ -0,0 +1,51 @@
+/*
+ * Multi trace backend
+ */
+
+#include <stdio.h>
+#include "trace.h"
+#include "trace/control.h"
+
+void trace_print_events(FILE *stream, fprintf_function stream_printf)
+{
+ TraceEventID i;
+
+ for (i = 0; i < trace_event_count(); i++) {
+ TraceEvent *ev = trace_event_id(i);
+ stream_printf(stream, "%s [Event ID %u] : state %u\n",
+ trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
+ }
+}
+
+void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
+{
+ ev->dstate = state;
+}
+
+bool trace_backend_init(const char *events, const char *file)
+{
+#ifndef CONFIG_TRACE_SIMPLE
+ if (file) {
+ fprintf(stderr, "error: -trace file=...: "
+ "option not supported by the selected tracing backend\n");
+ return false;
+ }
+#endif
+
+#ifdef CONFIG_TRACE_SIMPLE
+ if (!simpletrace_backend_init(events, file)) {
+ fprintf(stderr, "failed to initialize simple tracing backend.\n");
+ return false;
+ }
+#endif
+
+#ifdef CONFIG_TRACE_FTRACE
+ if (!ftrace_backend_init(events, file)) {
+ fprintf(stderr, "failed to initialize ftrace backend.\n");
+ return false;
+ }
+#endif
+
+ trace_backend_init_events(events);
+ return true;
+}
@@ -366,22 +366,6 @@ void st_flush_trace_buffer(void)
flush_trace_file(true);
}
-void trace_print_events(FILE *stream, fprintf_function stream_printf)
-{
- unsigned int i;
-
- for (i = 0; i < trace_event_count(); i++) {
- TraceEvent *ev = trace_event_id(i);
- stream_printf(stream, "%s [Event ID %u] : state %u\n",
- trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
- }
-}
-
-void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
-{
- ev->dstate = state;
-}
-
/* Helper function to create a thread with signals blocked. Use glib's
* portable threads since QEMU abstractions cannot be used due to reentrancy in
* the tracer. Also note the signal masking on POSIX hosts so that the thread
@@ -410,7 +394,7 @@ static GThread *trace_thread_create(GThreadFunc fn)
return thread;
}
-bool trace_backend_init(const char *events, const char *file)
+bool simpletrace_backend_init(const char *events, const char *file)
{
GThread *thread;
@@ -54,4 +54,5 @@ void trace_record_write_str(TraceBufferRecord *rec, const char *s, uint32_t slen
*/
void trace_record_finish(TraceBufferRecord *rec);
+bool simpletrace_backend_init(const char *events, const char *file);
#endif /* TRACE_SIMPLE_H */
deleted file mode 100644
@@ -1,30 +0,0 @@
-#include "trace.h"
-#include "trace/control.h"
-
-
-void trace_print_events(FILE *stream, fprintf_function stream_printf)
-{
- TraceEventID i;
-
- for (i = 0; i < trace_event_count(); i++) {
- TraceEvent *ev = trace_event_id(i);
- stream_printf(stream, "%s [Event ID %u] : state %u\n",
- trace_event_get_name(ev), i, trace_event_get_state_dynamic(ev));
- }
-}
-
-void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
-{
- ev->dstate = state;
-}
-
-bool trace_backend_init(const char *events, const char *file)
-{
- if (file) {
- fprintf(stderr, "error: -trace file=...: "
- "option not supported by the selected tracing backend\n");
- return false;
- }
- trace_backend_init_events(events);
- return true;
-}
This patch implements "multi tracing backend" which enables several tracing backend simultaneously. QEMU has multiple trace backends, but one of them needs to be chosen at compile time. When investigating issues of QEMU, it'd be much more convenient if we can use multiple trace backends without recompiling, especially 'ftrace backend' and 'dtrace backend'. From the performance perspective, 'ftrace backend' should be the one which runs while the system is in operation, and it provides useful information. But, for some issues, 'dtrace backend' is needed for investigation as 'dtrace backend' provides more information. This patch enables both 'ftrace backend' and 'dtrace backend' (, and some other backends if necessary) at compile time so that we can switch between the two without recompiling. usage: We have only to set some tracing backends as follows. $ ./configure --enable-trace-backend=ftrace,dtrace Of course, we can compile with single backend as well as before. $ ./configure --enable-trace-backend=simple Changes from v1: - Based on tracing-next branch - Support ust backend - Change the way to check whether each tracing backend is included in $trace_backend into the way to use grep - Add comment on compatible checking in tracetool.generate() - Change tracetool.backend.compatible() to check "supported_formats" of each backend - Eliminate CONFIG_TRACE_DTRACE include from tracetool/backend/common.py - Define SDT_USE_VARIADIC in genrated-tracers.h in order to avoid compilation error when enabling dtrace and ust simultaneously - Revert tracetool.backend.dtrace.{d(),stap()} back - Change multi.c:trace_backend_init() to figure out what is wrong when *_backend_init() fails Signed-off-by: Kazuya Saito <saito.kazuya@jp.fujitsu.com> --- Makefile | 4 +- configure | 16 +++-- scripts/tracetool.py | 9 ++- scripts/tracetool/__init__.py | 31 +++++--- scripts/tracetool/backend/__init__.py | 32 +++++---- scripts/tracetool/backend/common.py | 101 ++++++++++++++++++++++++++ scripts/tracetool/backend/dtrace.py | 33 +++++---- scripts/tracetool/backend/events.py | 2 +- scripts/tracetool/backend/ftrace.py | 60 ++++++++------- scripts/tracetool/backend/simple.py | 128 ++++++++++++++++----------------- scripts/tracetool/backend/stderr.py | 43 ++++++----- scripts/tracetool/backend/ust.py | 36 +++++----- trace/Makefile.objs | 22 ++++-- trace/ftrace.c | 25 +------ trace/ftrace.h | 1 + trace/multi.c | 51 +++++++++++++ trace/simple.c | 18 +----- trace/simple.h | 1 + trace/stderr.c | 30 -------- 19 files changed, 382 insertions(+), 261 deletions(-) create mode 100644 scripts/tracetool/backend/common.py create mode 100644 trace/multi.c delete mode 100644 trace/stderr.c