trace: Multi-backend tracing

Adds support to compile QEMU with multiple tracing backends at the same time.

For example, you can compile QEMU with:

  $ ./configure --enable-trace-backends=ftrace,dtrace

Where 'ftrace' can be handy for having an in-flight record of events, and 'dtrace' can be later used to extract more information from the system.

This patch allows having both available without recompiling QEMU.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Lluís Vilanova 2014-05-27 15:02:14 +02:00 committed by Stefan Hajnoczi
parent 82432638eb
commit 5b808275f3
20 changed files with 152 additions and 233 deletions

View File

@ -66,16 +66,16 @@ matrix:
compiler: gcc compiler: gcc
# All the trace backends (apart from dtrace) # All the trace backends (apart from dtrace)
- env: TARGETS=i386-softmmu,x86_64-softmmu - env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=stderr" EXTRA_CONFIG="--enable-trace-backends=stderr"
compiler: gcc compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu - env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=simple" EXTRA_CONFIG="--enable-trace-backends=simple"
compiler: gcc compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu - env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_CONFIG="--enable-trace-backend=ftrace" EXTRA_CONFIG="--enable-trace-backends=ftrace"
TEST_CMD="" TEST_CMD=""
compiler: gcc compiler: gcc
- env: TARGETS=i386-softmmu,x86_64-softmmu - env: TARGETS=i386-softmmu,x86_64-softmmu
EXTRA_PKGS="liblttng-ust-dev liburcu-dev" EXTRA_PKGS="liblttng-ust-dev liburcu-dev"
EXTRA_CONFIG="--enable-trace-backend=ust" EXTRA_CONFIG="--enable-trace-backends=ust"
compiler: gcc compiler: gcc

View File

@ -52,12 +52,12 @@ GENERATED_HEADERS += trace/generated-events.h
GENERATED_SOURCES += trace/generated-events.c GENERATED_SOURCES += trace/generated-events.c
GENERATED_HEADERS += trace/generated-tracers.h GENERATED_HEADERS += trace/generated-tracers.h
ifeq ($(TRACE_BACKEND),dtrace) ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
GENERATED_HEADERS += trace/generated-tracers-dtrace.h GENERATED_HEADERS += trace/generated-tracers-dtrace.h
endif endif
GENERATED_SOURCES += trace/generated-tracers.c GENERATED_SOURCES += trace/generated-tracers.c
ifeq ($(TRACE_BACKEND),ust) ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
GENERATED_HEADERS += trace/generated-ust-provider.h GENERATED_HEADERS += trace/generated-ust-provider.h
GENERATED_SOURCES += trace/generated-ust.c GENERATED_SOURCES += trace/generated-ust.c
endif endif

View File

@ -49,7 +49,7 @@ endif
$(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events $(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=stap \ --format=stap \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
--binary=$(bindir)/$(QEMU_PROG) \ --binary=$(bindir)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \ --target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \ --target-type=$(TARGET_TYPE) \
@ -58,7 +58,7 @@ $(QEMU_PROG).stp-installed: $(SRC_PATH)/trace-events
$(QEMU_PROG).stp: $(SRC_PATH)/trace-events $(QEMU_PROG).stp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=stap \ --format=stap \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
--binary=$(realpath .)/$(QEMU_PROG) \ --binary=$(realpath .)/$(QEMU_PROG) \
--target-name=$(TARGET_NAME) \ --target-name=$(TARGET_NAME) \
--target-type=$(TARGET_TYPE) \ --target-type=$(TARGET_TYPE) \

47
configure vendored
View File

@ -182,6 +182,10 @@ path_of() {
return 1 return 1
} }
have_backend () {
echo "$trace_backends" | grep "$1" >/dev/null
}
# default parameters # default parameters
source_path=`dirname "$0"` source_path=`dirname "$0"`
cpu="" cpu=""
@ -293,7 +297,7 @@ pkgversion=""
pie="" pie=""
zero_malloc="" zero_malloc=""
qom_cast_debug="yes" qom_cast_debug="yes"
trace_backend="nop" trace_backends="nop"
trace_file="trace" trace_file="trace"
spice="" spice=""
rbd="" rbd=""
@ -753,7 +757,10 @@ for opt do
;; ;;
--target-list=*) target_list="$optarg" --target-list=*) target_list="$optarg"
;; ;;
--enable-trace-backend=*) trace_backend="$optarg" --enable-trace-backends=*) trace_backends="$optarg"
;;
# XXX: backwards compatibility
--enable-trace-backend=*) trace_backends="$optarg"
;; ;;
--with-trace-file=*) trace_file="$optarg" --with-trace-file=*) trace_file="$optarg"
;; ;;
@ -1320,7 +1327,7 @@ Advanced options (experts only):
--disable-docs disable documentation build --disable-docs disable documentation build
--disable-vhost-net disable vhost-net acceleration support --disable-vhost-net disable vhost-net acceleration support
--enable-vhost-net enable vhost-net acceleration support --enable-vhost-net enable vhost-net acceleration support
--enable-trace-backend=B Set trace backend --enable-trace-backends=B Set trace backend
Available backends: $($python $source_path/scripts/tracetool.py --list-backends) Available backends: $($python $source_path/scripts/tracetool.py --list-backends)
--with-trace-file=NAME Full PATH,NAME of file to store traces --with-trace-file=NAME Full PATH,NAME of file to store traces
Default:trace-<pid> Default:trace-<pid>
@ -3666,15 +3673,15 @@ fi
########################################## ##########################################
# check if trace backend exists # check if trace backend exists
$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend > /dev/null 2> /dev/null $python "$source_path/scripts/tracetool.py" "--backends=$trace_backends" --check-backends > /dev/null 2> /dev/null
if test "$?" -ne 0 ; then if test "$?" -ne 0 ; then
error_exit "invalid trace backend" \ error_exit "invalid trace backends" \
"Please choose a supported trace backend." "Please choose supported trace backends."
fi fi
########################################## ##########################################
# For 'ust' backend, test if ust headers are present # For 'ust' backend, test if ust headers are present
if test "$trace_backend" = "ust"; then if have_backend "ust"; then
cat > $TMPC << EOF cat > $TMPC << EOF
#include <lttng/tracepoint.h> #include <lttng/tracepoint.h>
int main(void) { return 0; } int main(void) { return 0; }
@ -3700,7 +3707,7 @@ fi
########################################## ##########################################
# For 'dtrace' backend, test if 'dtrace' command is present # For 'dtrace' backend, test if 'dtrace' command is present
if test "$trace_backend" = "dtrace"; then if have_backend "dtrace"; then
if ! has 'dtrace' ; then if ! has 'dtrace' ; then
error_exit "dtrace command is not found in PATH $PATH" error_exit "dtrace command is not found in PATH $PATH"
fi fi
@ -4170,7 +4177,7 @@ echo "uuid support $uuid"
echo "libcap-ng support $cap_ng" echo "libcap-ng support $cap_ng"
echo "vhost-net support $vhost_net" echo "vhost-net support $vhost_net"
echo "vhost-scsi support $vhost_scsi" echo "vhost-scsi support $vhost_scsi"
echo "Trace backend $trace_backend" echo "Trace backends $trace_backends"
if test "$trace_backend" = "simple"; then if test "$trace_backend" = "simple"; then
echo "Trace output file $trace_file-<pid>" echo "Trace output file $trace_file-<pid>"
fi fi
@ -4664,43 +4671,35 @@ if test "$tpm" = "yes"; then
fi fi
fi fi
# use default implementation for tracing backend-specific routines echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
trace_default=yes if have_backend "nop"; then
echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
if test "$trace_backend" = "nop"; then
echo "CONFIG_TRACE_NOP=y" >> $config_host_mak echo "CONFIG_TRACE_NOP=y" >> $config_host_mak
fi fi
if test "$trace_backend" = "simple"; then if have_backend "simple"; then
echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak echo "CONFIG_TRACE_SIMPLE=y" >> $config_host_mak
trace_default=no
# Set the appropriate trace file. # Set the appropriate trace file.
trace_file="\"$trace_file-\" FMT_pid" trace_file="\"$trace_file-\" FMT_pid"
fi fi
if test "$trace_backend" = "stderr"; then if have_backend "stderr"; then
echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak echo "CONFIG_TRACE_STDERR=y" >> $config_host_mak
trace_default=no
fi fi
if test "$trace_backend" = "ust"; then if have_backend "ust"; then
echo "CONFIG_TRACE_UST=y" >> $config_host_mak echo "CONFIG_TRACE_UST=y" >> $config_host_mak
fi fi
if test "$trace_backend" = "dtrace"; then if have_backend "dtrace"; then
echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak echo "CONFIG_TRACE_DTRACE=y" >> $config_host_mak
if test "$trace_backend_stap" = "yes" ; then if test "$trace_backend_stap" = "yes" ; then
echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak echo "CONFIG_TRACE_SYSTEMTAP=y" >> $config_host_mak
fi fi
fi fi
if test "$trace_backend" = "ftrace"; then if have_backend "ftrace"; then
if test "$linux" = "yes" ; then if test "$linux" = "yes" ; then
echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak echo "CONFIG_TRACE_FTRACE=y" >> $config_host_mak
trace_default=no
else else
feature_not_found "ftrace(trace backend)" "ftrace requires Linux" feature_not_found "ftrace(trace backend)" "ftrace requires Linux"
fi fi
fi fi
echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak echo "CONFIG_TRACE_FILE=$trace_file" >> $config_host_mak
if test "$trace_default" = "yes"; then
echo "CONFIG_TRACE_DEFAULT=y" >> $config_host_mak
fi
if test "$rdma" = "yes" ; then if test "$rdma" = "yes" ; then
echo "CONFIG_RDMA=y" >> $config_host_mak echo "CONFIG_RDMA=y" >> $config_host_mak

View File

@ -9,7 +9,7 @@ for debugging, profiling, and observing execution.
1. Build with the 'simple' trace backend: 1. Build with the 'simple' trace backend:
./configure --enable-trace-backend=simple ./configure --enable-trace-backends=simple
make make
2. Create a file with the events you want to trace: 2. Create a file with the events you want to trace:
@ -142,7 +142,7 @@ script.
The trace backend is chosen at configure time and only one trace backend can The trace backend is chosen at configure time and only one trace backend can
be built into the binary: be built into the binary:
./configure --trace-backend=simple ./configure --trace-backends=simple
For a list of supported trace backends, try ./configure --help or see below. For a list of supported trace backends, try ./configure --help or see below.

View File

@ -433,7 +433,7 @@ int main(int argc, char **argv)
} }
break; break;
case 'T': case 'T':
if (!trace_backend_init(optarg, NULL)) { if (!trace_init_backends(optarg, NULL)) {
exit(1); /* error message will have been printed */ exit(1); /* error message will have been printed */
} }
break; break;

View File

@ -6,7 +6,7 @@ Command-line wrapper for the tracetool machinery.
""" """
__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"
@ -32,7 +32,7 @@ def error_opt(msg = None):
format_descr = "\n".join([ " %-15s %s" % (n, d) format_descr = "\n".join([ " %-15s %s" % (n, d)
for n,d in tracetool.format.get_list() ]) for n,d in tracetool.format.get_list() ])
error_write("""\ error_write("""\
Usage: %(script)s --format=<format> --backend=<backend> [<options>] Usage: %(script)s --format=<format> --backends=<backends> [<options>]
Backends: Backends:
%(backends)s %(backends)s
@ -43,7 +43,7 @@ Formats:
Options: Options:
--help This help message. --help This help message.
--list-backends Print list of available backends. --list-backends Print list of available backends.
--check-backend Check if the given backend is valid. --check-backends Check if the given backend is valid.
--binary <path> Full path to QEMU binary. --binary <path> Full path to QEMU binary.
--target-type <type> QEMU emulator target type ('system' or 'user'). --target-type <type> QEMU emulator target type ('system' or 'user').
--target-name <name> QEMU emulator target name. --target-name <name> QEMU emulator target name.
@ -65,16 +65,17 @@ def main(args):
global _SCRIPT global _SCRIPT
_SCRIPT = args[0] _SCRIPT = args[0]
long_opts = [ "backend=", "format=", "help", "list-backends", "check-backend" ] long_opts = ["backends=", "format=", "help", "list-backends",
long_opts += [ "binary=", "target-type=", "target-name=", "probe-prefix=" ] "check-backends"]
long_opts += ["binary=", "target-type=", "target-name=", "probe-prefix="]
try: try:
opts, args = getopt.getopt(args[1:], "", long_opts) opts, args = getopt.getopt(args[1:], "", long_opts)
except getopt.GetoptError, err: except getopt.GetoptError, err:
error_opt(str(err)) error_opt(str(err))
check_backend = False check_backends = False
arg_backend = "" arg_backends = []
arg_format = "" arg_format = ""
binary = None binary = None
target_type = None target_type = None
@ -84,8 +85,8 @@ def main(args):
if opt == "--help": if opt == "--help":
error_opt() error_opt()
elif opt == "--backend": elif opt == "--backends":
arg_backend = arg arg_backends = arg.split(",")
elif opt == "--format": elif opt == "--format":
arg_format = arg arg_format = arg
@ -93,8 +94,8 @@ def main(args):
public_backends = tracetool.backend.get_list(only_public = True) public_backends = tracetool.backend.get_list(only_public = True)
out(", ".join([ b for b,_ in public_backends ])) out(", ".join([ b for b,_ in public_backends ]))
sys.exit(0) sys.exit(0)
elif opt == "--check-backend": elif opt == "--check-backends":
check_backend = True check_backends = True
elif opt == "--binary": elif opt == "--binary":
binary = arg binary = arg
@ -108,14 +109,14 @@ def main(args):
else: else:
error_opt("unhandled option: %s" % opt) error_opt("unhandled option: %s" % opt)
if arg_backend is None: if len(arg_backends) == 0:
error_opt("backend not set") error_opt("no backends specified")
if check_backend: if check_backends:
if tracetool.backend.exists(arg_backend): for backend in arg_backends:
sys.exit(0) if not tracetool.backend.exists(backend):
else: sys.exit(1)
sys.exit(1) sys.exit(0)
if arg_format == "stap": if arg_format == "stap":
if binary is None: if binary is None:
@ -126,11 +127,11 @@ def main(args):
error_opt("--target-name is required for SystemTAP tapset generator") error_opt("--target-name is required for SystemTAP tapset generator")
if probe_prefix is None: if probe_prefix is None:
probe_prefix = ".".join([ "qemu", target_type, target_name ]) probe_prefix = ".".join(["qemu", target_type, target_name])
try: try:
tracetool.generate(sys.stdin, arg_format, arg_backend, tracetool.generate(sys.stdin, arg_format, arg_backends,
binary = binary, probe_prefix = probe_prefix) binary=binary, probe_prefix=probe_prefix)
except tracetool.TracetoolError, e: except tracetool.TracetoolError, e:
error_opt(str(e)) error_opt(str(e))

View File

@ -233,9 +233,9 @@ def try_import(mod_name, attr_name=None, attr_default=None):
return False, None return False, None
def generate(fevents, format, backend, def generate(fevents, format, backends,
binary=None, probe_prefix=None): binary=None, probe_prefix=None):
"""Generate the output for the given (format, backend) pair. """Generate the output for the given (format, backends) pair.
Parameters Parameters
---------- ----------
@ -243,8 +243,8 @@ def generate(fevents, format, backend,
Event description file. Event description file.
format : str format : str
Output format name. Output format name.
backend : str backends : list
Output backend name. Output backend names.
binary : str or None binary : str or None
See tracetool.backend.dtrace.BINARY. See tracetool.backend.dtrace.BINARY.
probe_prefix : str or None probe_prefix : str or None
@ -258,15 +258,13 @@ def generate(fevents, format, backend,
raise TracetoolError("format not set") raise TracetoolError("format not set")
if not tracetool.format.exists(format): if not tracetool.format.exists(format):
raise TracetoolError("unknown format: %s" % format) raise TracetoolError("unknown format: %s" % format)
format = format.replace("-", "_")
backend = str(backend) if len(backends) is 0:
if len(backend) is 0: raise TracetoolError("no backends specified")
raise TracetoolError("backend not set") for backend in backends:
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 = tracetool.backend.Wrapper(backends, format)
backend = tracetool.backend.Wrapper(backend, format)
import tracetool.backend.dtrace import tracetool.backend.dtrace
tracetool.backend.dtrace.BINARY = binary tracetool.backend.dtrace.BINARY = binary

View File

@ -99,17 +99,18 @@ def exists(name):
class Wrapper: class Wrapper:
def __init__(self, backend, format): def __init__(self, backends, format):
self._backend = backend.replace("-", "_") self._backends = [backend.replace("-", "_") for backend in backends]
self._format = format.replace("-", "_") self._format = format.replace("-", "_")
assert exists(self._backend) assert all(exists(backend) for backend in self._backends)
assert tracetool.format.exists(self._format) assert tracetool.format.exists(self._format)
def _run_function(self, name, *args, **kwargs): def _run_function(self, name, *args, **kwargs):
func = tracetool.try_import("tracetool.backend." + self._backend, for backend in self._backends:
name % self._format, None)[1] func = tracetool.try_import("tracetool.backend." + backend,
if func is not None: name % self._format, None)[1]
func(*args, **kwargs) if func is not None:
func(*args, **kwargs)
def generate_begin(self, events): def generate_begin(self, events):
self._run_function("generate_%s_begin", events) self._run_function("generate_%s_begin", events)

View File

@ -3,12 +3,12 @@
###################################################################### ######################################################################
# Auto-generated event descriptions for LTTng ust code # Auto-generated event descriptions for LTTng ust code
ifeq ($(TRACE_BACKEND),ust) ifeq ($(findstring ust,$(TRACE_BACKENDS)),ust)
$(obj)/generated-ust-provider.h: $(obj)/generated-ust-provider.h-timestamp $(obj)/generated-ust-provider.h: $(obj)/generated-ust-provider.h-timestamp
$(obj)/generated-ust-provider.h-timestamp: $(SRC_PATH)/trace-events $(obj)/generated-ust-provider.h-timestamp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=ust-events-h \ --format=ust-events-h \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
@ -16,7 +16,7 @@ $(obj)/generated-ust.c: $(obj)/generated-ust.c-timestamp $(BUILD_DIR)/config-hos
$(obj)/generated-ust.c-timestamp: $(SRC_PATH)/trace-events $(obj)/generated-ust.c-timestamp: $(SRC_PATH)/trace-events
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=ust-events-c \ --format=ust-events-c \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
@ -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=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," 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=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
@ -54,23 +54,21 @@ $(obj)/generated-tracers.h: $(obj)/generated-tracers.h-timestamp
$(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(obj)/generated-tracers.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=h \ --format=h \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
###################################################################### ######################################################################
# Auto-generated tracing routines (non-DTrace) # Auto-generated tracing routines (non-DTrace)
ifneq ($(TRACE_BACKEND),dtrace)
$(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp $(obj)/generated-tracers.c: $(obj)/generated-tracers.c-timestamp
@cmp -s $< $@ || cp $< $@ @cmp -s $< $@ || cp $< $@
$(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(obj)/generated-tracers.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=c \ --format=c \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
$(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h $(obj)/generated-tracers.o: $(obj)/generated-tracers.c $(obj)/generated-tracers.h
endif
###################################################################### ######################################################################
@ -79,27 +77,27 @@ endif
# Normal practice is to name DTrace probe file with a '.d' extension # 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 # but that gets picked up by QEMU's Makefile as an external dependency
# rule file. So we use '.dtrace' instead # rule file. So we use '.dtrace' instead
ifeq ($(TRACE_BACKEND),dtrace) ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
$(obj)/generated-tracers.dtrace: $(obj)/generated-tracers.dtrace-timestamp $(obj)/generated-tracers-dtrace.dtrace: $(obj)/generated-tracers-dtrace.dtrace-timestamp
$(obj)/generated-tracers.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak $(obj)/generated-tracers-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
$(call quiet-command,$(TRACETOOL) \ $(call quiet-command,$(TRACETOOL) \
--format=d \ --format=d \
--backend=$(TRACE_BACKEND) \ --backends=$(TRACE_BACKENDS) \
< $< > $@," GEN $(patsubst %-timestamp,%,$@)") < $< > $@," GEN $(patsubst %-timestamp,%,$@)")
@cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@) @cmp -s $@ $(patsubst %-timestamp,%,$@) || cp $@ $(patsubst %-timestamp,%,$@)
$(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers.dtrace $(obj)/generated-tracers-dtrace.h: $(obj)/generated-tracers-dtrace.dtrace
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN $@") $(call quiet-command,dtrace -o $@ -h -s $<, " GEN $@")
$(obj)/generated-tracers.o: $(obj)/generated-tracers.dtrace $(obj)/generated-tracers-dtrace.o: $(obj)/generated-tracers-dtrace.dtrace
util-obj-y += generated-tracers-dtrace.o
endif endif
###################################################################### ######################################################################
# Backend code # Backend code
util-obj-$(CONFIG_TRACE_DEFAULT) += default.o
util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o 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_FTRACE) += ftrace.o
util-obj-$(CONFIG_TRACE_UST) += generated-ust.o util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
util-obj-y += control.o util-obj-y += control.o

View File

@ -1,7 +1,7 @@
/* /*
* Interface for configuring and controlling the state of tracing events. * Interface for configuring and controlling the state of tracing events.
* *
* Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu> * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
* *
* This work is licensed under the terms of the GNU GPL, version 2 or later. * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
@ -61,7 +61,7 @@ static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
{ {
assert(ev != NULL); assert(ev != NULL);
assert(trace_event_get_state_static(ev)); assert(trace_event_get_state_static(ev));
return trace_event_set_state_dynamic_backend(ev, state); ev->dstate = state;
} }
#endif /* TRACE__CONTROL_INTERNAL_H */ #endif /* TRACE__CONTROL_INTERNAL_H */

View File

@ -1,13 +1,19 @@
/* /*
* Interface for configuring and controlling the state of tracing events. * Interface for configuring and controlling the state of tracing events.
* *
* Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu> * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
* *
* This work is licensed under the terms of the GNU GPL, version 2 or later. * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
*/ */
#include "trace/control.h" #include "trace/control.h"
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
#ifdef CONFIG_TRACE_FTRACE
#include "trace/ftrace.h"
#endif
TraceEvent *trace_event_name(const char *name) TraceEvent *trace_event_name(const char *name)
@ -79,7 +85,20 @@ TraceEvent *trace_event_pattern(const char *pat, TraceEvent *ev)
return NULL; return NULL;
} }
void trace_backend_init_events(const char *fname) 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_static(ev) &&
trace_event_get_state_dynamic(ev));
}
}
static void trace_init_events(const char *fname)
{ {
if (fname == NULL) { if (fname == NULL) {
return; return;
@ -130,3 +149,29 @@ void trace_backend_init_events(const char *fname)
exit(1); exit(1);
} }
} }
bool trace_init_backends(const char *events, const char *file)
{
#ifdef CONFIG_TRACE_SIMPLE
if (!st_init(file)) {
fprintf(stderr, "failed to initialize simple tracing backend.\n");
return false;
}
#else
if (file) {
fprintf(stderr, "error: -trace file=...: "
"option not supported by the selected tracing backends\n");
return false;
}
#endif
#ifdef CONFIG_TRACE_FTRACE
if (!ftrace_init()) {
fprintf(stderr, "failed to initialize ftrace backend.\n");
return false;
}
#endif
trace_init_events(events);
return true;
}

View File

@ -1,7 +1,7 @@
/* /*
* Interface for configuring and controlling the state of tracing events. * Interface for configuring and controlling the state of tracing events.
* *
* Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu> * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
* *
* This work is licensed under the terms of the GNU GPL, version 2 or later. * This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory. * See the COPYING file in the top-level directory.
@ -146,26 +146,17 @@ static bool trace_event_get_state_dynamic(TraceEvent *ev);
*/ */
static void trace_event_set_state_dynamic(TraceEvent *ev, bool state); static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
/**
* trace_event_set_state_dynamic_backend:
*
* Warning: This function must be implemented by each tracing backend.
*/
void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state);
/** /**
* trace_print_events: * trace_print_events:
* *
* Print the state of all events. * Print the state of all events.
*
* Warning: This function must be implemented by each tracing backend.
*/ */
void trace_print_events(FILE *stream, fprintf_function stream_printf); void trace_print_events(FILE *stream, fprintf_function stream_printf);
/** /**
* trace_backend_init: * trace_init_backends:
* @events: Name of file with events to be enabled at startup; may be NULL. * @events: Name of file with events to be enabled at startup; may be NULL.
* Corresponds to commandline option "-trace events=...". * Corresponds to commandline option "-trace events=...".
* @file: Name of trace output file; may be NULL. * @file: Name of trace output file; may be NULL.
@ -173,19 +164,9 @@ void trace_print_events(FILE *stream, fprintf_function stream_printf);
* *
* Initialize the tracing backend. * Initialize the tracing backend.
* *
* Warning: This function must be implemented by each tracing backend. * Returns: Whether the backends could be successfully initialized.
*
* Returns: Whether the backend could be successfully initialized.
*/ */
bool trace_backend_init(const char *events, const char *file); bool trace_init_backends(const char *events, const char *file);
/**
* trace_backend_init_events:
* @fname: Name of file with events to enable; may be NULL.
*
* Generic function to initialize the state of events.
*/
void trace_backend_init_events(const char *fname);
#include "trace/control-internal.h" #include "trace/control-internal.h"

View File

@ -1,40 +0,0 @@
/*
* Default implementation for backend initialization from commandline.
*
* Copyright (C) 2011-2012 Lluís Vilanova <vilanova@ac.upc.edu>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*/
#include "trace/control.h"
void trace_print_events(FILE *stream, fprintf_function stream_printf)
{
fprintf(stderr, "warning: "
"cannot print the trace events with the current backend\n");
stream_printf(stream, "error: "
"operation not supported with the current backend\n");
}
void trace_event_set_state_dynamic_backend(TraceEvent *ev, bool state)
{
fprintf(stderr, "warning: "
"cannot set the state of a trace event with the current backend\n");
}
bool trace_backend_init(const char *events, const char *file)
{
if (events) {
fprintf(stderr, "error: -trace events=...: "
"option not supported by the selected tracing backend\n");
return false;
}
if (file) {
fprintf(stderr, "error: -trace file=...: "
"option not supported by the selected tracing backend\n");
return false;
}
return true;
}

View File

@ -42,35 +42,13 @@ static int find_debugfs(char *debugfs)
return 1; return 1;
} }
void trace_print_events(FILE *stream, fprintf_function stream_printf) bool ftrace_init(void)
{
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)
{ {
char debugfs[PATH_MAX]; char debugfs[PATH_MAX];
char path[PATH_MAX]; char path[PATH_MAX];
int debugfs_found; int debugfs_found;
int trace_fd = -1; 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); debugfs_found = find_debugfs(debugfs);
if (debugfs_found) { if (debugfs_found) {
snprintf(path, PATH_MAX, "%s/tracing/tracing_on", debugfs); 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; return false;
} }
trace_backend_init_events(events);
return true; return true;
} }

View File

@ -1,10 +1,15 @@
#ifndef TRACE_FTRACE_H #ifndef TRACE_FTRACE_H
#define TRACE_FTRACE_H #define TRACE_FTRACE_H
#include <stdbool.h>
#define MAX_TRACE_STRLEN 512 #define MAX_TRACE_STRLEN 512
#define _STR(x) #x #define _STR(x) #x
#define STR(x) _STR(x) #define STR(x) _STR(x)
extern int trace_marker_fd; extern int trace_marker_fd;
bool ftrace_init(void);
#endif /* ! TRACE_FTRACE_H */ #endif /* ! TRACE_FTRACE_H */

View File

@ -368,22 +368,6 @@ void st_flush_trace_buffer(void)
flush_trace_file(true); 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 /* Helper function to create a thread with signals blocked. Use glib's
* portable threads since QEMU abstractions cannot be used due to reentrancy in * 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 * the tracer. Also note the signal masking on POSIX hosts so that the thread
@ -412,7 +396,7 @@ static GThread *trace_thread_create(GThreadFunc fn)
return thread; return thread;
} }
bool trace_backend_init(const char *events, const char *file) bool st_init(const char *file)
{ {
GThread *thread; GThread *thread;
@ -430,7 +414,6 @@ bool trace_backend_init(const char *events, const char *file)
} }
atexit(st_flush_trace_buffer); atexit(st_flush_trace_buffer);
trace_backend_init_events(events);
st_set_trace_file(file); st_set_trace_file(file);
return true; return true;
} }

View File

@ -21,6 +21,7 @@
void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf); void st_print_trace_file_status(FILE *stream, fprintf_function stream_printf);
void st_set_trace_file_enabled(bool enable); void st_set_trace_file_enabled(bool enable);
bool st_set_trace_file(const char *file); bool st_set_trace_file(const char *file);
bool st_init(const char *file);
void st_flush_trace_buffer(void); void st_flush_trace_buffer(void);
typedef struct { typedef struct {

View File

@ -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;
}

4
vl.c
View File

@ -4039,7 +4039,7 @@ int main(int argc, char **argv, char **envp)
} }
if (!is_daemonized()) { if (!is_daemonized()) {
if (!trace_backend_init(trace_events, trace_file)) { if (!trace_init_backends(trace_events, trace_file)) {
exit(1); exit(1);
} }
} }
@ -4559,7 +4559,7 @@ int main(int argc, char **argv, char **envp)
os_setup_post(); os_setup_post();
if (is_daemonized()) { if (is_daemonized()) {
if (!trace_backend_init(trace_events, trace_file)) { if (!trace_init_backends(trace_events, trace_file)) {
exit(1); exit(1);
} }
} }