Browse Source

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>
Lluís Vilanova 11 years ago
parent
commit
5b808275f3
20 changed files with 153 additions and 234 deletions
  1. 4 4
      .travis.yml
  2. 2 2
      Makefile
  3. 2 2
      Makefile.target
  4. 23 24
      configure
  5. 2 2
      docs/tracing.txt
  6. 1 1
      qemu-io.c
  7. 22 21
      scripts/tracetool.py
  8. 11 13
      scripts/tracetool/__init__.py
  9. 8 7
      scripts/tracetool/backend/__init__.py
  10. 15 17
      trace/Makefile.objs
  11. 2 2
      trace/control-internal.h
  12. 47 2
      trace/control.c
  13. 4 23
      trace/control.h
  14. 0 40
      trace/default.c
  15. 1 24
      trace/ftrace.c
  16. 5 0
      trace/ftrace.h
  17. 1 18
      trace/simple.c
  18. 1 0
      trace/simple.h
  19. 0 30
      trace/stderr.c
  20. 2 2
      vl.c

+ 4 - 4
.travis.yml

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

+ 2 - 2
Makefile

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

+ 2 - 2
Makefile.target

@@ -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) \

+ 23 - 24
configure

@@ -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" \
-      "Please choose a supported trace backend."
+  error_exit "invalid trace backends" \
+      "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
-trace_default=yes
-echo "TRACE_BACKEND=$trace_backend" >> $config_host_mak
-if test "$trace_backend" = "nop"; then
+echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
+if have_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

+ 2 - 2
docs/tracing.txt

@@ -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.
 
 

+ 1 - 1
qemu-io.c

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

+ 22 - 21
scripts/tracetool.py

@@ -6,7 +6,7 @@
 """
 """
 
 
 __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 @@ def error_opt(msg = None):
 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 += [ "binary=", "target-type=", "target-name=", "probe-prefix=" ]
+    long_opts = ["backends=", "format=", "help", "list-backends",
+                 "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
-    arg_backend = ""
+    check_backends = False
+    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":
-            arg_backend = arg
+        elif opt == "--backends":
+            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":
-            check_backend = True
+        elif opt == "--check-backends":
+            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:
-        error_opt("backend not set")
+    if len(arg_backends) == 0:
+        error_opt("no backends specified")
 
 
-    if check_backend:
-        if tracetool.backend.exists(arg_backend):
-            sys.exit(0)
-        else:
-            sys.exit(1)
+    if check_backends:
+        for backend in arg_backends:
+            if not tracetool.backend.exists(backend):
+                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,
-                           binary = binary, probe_prefix = probe_prefix)
+        tracetool.generate(sys.stdin, arg_format, arg_backends,
+                           binary=binary, probe_prefix=probe_prefix)
     except tracetool.TracetoolError, e:
     except tracetool.TracetoolError, e:
         error_opt(str(e))
         error_opt(str(e))
 
 

+ 11 - 13
scripts/tracetool/__init__.py

@@ -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
-        Output backend name.
+    backends : list
+        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(backend) is 0:
-        raise TracetoolError("backend not set")
-    if not tracetool.backend.exists(backend):
-        raise TracetoolError("unknown backend: %s" % backend)
-    backend = backend.replace("-", "_")
-    backend = tracetool.backend.Wrapper(backend, format)
+
+    if len(backends) is 0:
+        raise TracetoolError("no backends specified")
+    for backend in backends:
+        if not tracetool.backend.exists(backend):
+            raise TracetoolError("unknown backend: %s" % backend)
+    backend = tracetool.backend.Wrapper(backends, format)
 
 
     import tracetool.backend.dtrace
     import tracetool.backend.dtrace
     tracetool.backend.dtrace.BINARY = binary
     tracetool.backend.dtrace.BINARY = binary

+ 8 - 7
scripts/tracetool/backend/__init__.py

@@ -99,17 +99,18 @@ def exists(name):
 
 
 
 
 class Wrapper:
 class Wrapper:
-    def __init__(self, backend, format):
-        self._backend = backend.replace("-", "_")
+    def __init__(self, backends, format):
+        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,
-                                    name % self._format, None)[1]
-        if func is not None:
-            func(*args, **kwargs)
+        for backend in self._backends:
+            func = tracetool.try_import("tracetool.backend." + backend,
+                                        name % self._format, None)[1]
+            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)

+ 15 - 17
trace/Makefile.objs

@@ -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)
-$(obj)/generated-tracers.dtrace: $(obj)/generated-tracers.dtrace-timestamp
-$(obj)/generated-tracers.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
+ifeq ($(findstring dtrace,$(TRACE_BACKENDS)),dtrace)
+$(obj)/generated-tracers-dtrace.dtrace: $(obj)/generated-tracers-dtrace.dtrace-timestamp
+$(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

+ 2 - 2
trace/control-internal.h

@@ -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 */

+ 47 - 2
trace/control.c

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

+ 4 - 23
trace/control.h

@@ -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 backend could be successfully initialized.
- */
-bool trace_backend_init(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.
+ * Returns: Whether the backends could be successfully initialized.
  */
  */
-void trace_backend_init_events(const char *fname);
+bool trace_init_backends(const char *events, const char *file);
 
 
 
 
 #include "trace/control-internal.h"
 #include "trace/control-internal.h"

+ 0 - 40
trace/default.c

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

+ 1 - 24
trace/ftrace.c

@@ -42,35 +42,13 @@ static int find_debugfs(char *debugfs)
     return 1;
     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_init(void)
 {
 {
     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;
 }
 }

+ 5 - 0
trace/ftrace.h

@@ -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 */

+ 1 - 18
trace/simple.c

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

+ 1 - 0
trace/simple.h

@@ -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 {

+ 0 - 30
trace/stderr.c

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

+ 2 - 2
vl.c

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