qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2
@ 2012-02-15 15:46 Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 01/14] Converting tracetool.sh to tracetool.py Harsh Prateek Bora
                   ` (14 more replies)
  0 siblings, 15 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

This patchset introduces 2 major updates:

1) Tracetool Improvements (Conversion from shell script to python)
2) Simpletrace v2 log format (Support for variable args, strings)

Existing simple trace can log upto 6 args per trace event and does not
support strings in trace record format. Introducing new trace format as
discussed earlier on list to support variable number/size of arguments.
Basic testing of new tracelog format is successful. Stress testing not yet
done.

Apply patches, then run:

make distclean
./configure with --enable-trace-backend=simple
make
sudo make install

Sample tracelog showing strings support:
[harsh@harshbora v9fs]$ scripts/simpletrace.py trace-events trace-23261
v9fs_version 0.000 tag=65535 id=100 msize=8192 version=9P2000.L
v9fs_version_return 17.530 tag=65535 id=100 msize=8192 version=9P2000.L
v9fs_attach 180.121 tag=1 id=104 fid=0 afid=18446744073709551615
uname=nobody aname=

Note: Other backends are only compile tested.

Version History:

v4:
- Addressed Stefan's review comments for tracetool, trace/simple.*
- Adressed Fast producer, Slow consumer problem
- Isolated tracetool python conversion patch from simpletrace v2 changes.
- Included improvements and fixes from Lluis Vilanova
TODO: Update simpletrace.py for simpletrace v2 log format.

v3:
- Added support for LTTng ust trace backend in tracetool.py

v2:
- Updated tracetool.py to support nop, stderr, dtrace backend

v1:
- Working protoype with tracetool.py converted only for simpletrace backend


Harsh Prateek Bora (4):
  Converting tracetool.sh to tracetool.py
  monitor: remove unused do_info_trace
  Simpletrace v2: Handle var num of args, strings.
  simpletrace.py: Support for simpletrace v2 log format

Lluís Vilanova (10):
  trace: [tracetool] Do not rebuild event list in backend code
  trace: [tracetool] Simplify event line parsing
  trace: [tracetool] Do not precompute the event number
  trace: [tracetool] Add support for event properties
  trace: [tracetool] Process the "disable" event property
  trace: [tracetool] Rewrite event argument parsing
  trace: [tracetool] Make format-specific code optional with access to
    events
  trace: [tracetool] Automatically establish available backends and
    formats
  trace: Provide a per-event status define for conditional compilation
  trace: [tracetool] Add error-reporting functions

 Makefile.objs          |    6 +-
 Makefile.target        |   13 +-
 configure              |    7 +-
 docs/tracing.txt       |   50 ++++-
 monitor.c              |   16 --
 scripts/simpletrace.py |  112 ++++++++-
 scripts/tracetool      |  643 ------------------------------------------------
 scripts/tracetool.py   |  635 +++++++++++++++++++++++++++++++++++++++++++++++
 trace/simple.c         |  226 ++++++++++--------
 trace/simple.h         |   38 +++-
 10 files changed, 949 insertions(+), 797 deletions(-)
 delete mode 100755 scripts/tracetool
 create mode 100755 scripts/tracetool.py

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 01/14] Converting tracetool.sh to tracetool.py
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 02/14] trace: [tracetool] Do not rebuild event list in backend code Harsh Prateek Bora
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 Makefile.objs        |    6 +-
 Makefile.target      |   10 +-
 configure            |    7 +-
 scripts/tracetool    |  643 --------------------------------------------------
 scripts/tracetool.py |  534 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 546 insertions(+), 654 deletions(-)
 delete mode 100755 scripts/tracetool
 create mode 100755 scripts/tracetool.py

diff --git a/Makefile.objs b/Makefile.objs
index 804bc3c..984034a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -344,12 +344,12 @@ else
 trace.h: trace.h-timestamp
 endif
 trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
 	@cmp -s $@ trace.h || cp $@ trace.h
 
 trace.c: trace.c-timestamp
 trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
 	@cmp -s $@ trace.c || cp $@ trace.c
 
 trace.o: trace.c $(GENERATED_HEADERS)
@@ -362,7 +362,7 @@ trace-dtrace.h: trace-dtrace.dtrace
 # rule file. So we use '.dtrace' instead
 trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
 trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
 	@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
 
 trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
diff --git a/Makefile.target b/Makefile.target
index 1e90df7..07b21d1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -50,11 +50,11 @@ TARGET_TYPE=system
 endif
 
 $(QEMU_PROG).stp:
-	$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \
-		--$(TRACE_BACKEND) \
-		--binary $(bindir)/$(QEMU_PROG) \
-		--target-arch $(TARGET_ARCH) \
-		--target-type $(TARGET_TYPE) \
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \
+		--backend=$(TRACE_BACKEND) \
+		--binary=$(bindir)/$(QEMU_PROG) \
+		--target-arch=$(TARGET_ARCH) \
+		--target-type=$(TARGET_TYPE) \
 		--stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp,"  GEN   $(QEMU_PROG).stp")
 else
 stap:
diff --git a/configure b/configure
index 19e8394..40a18d8 100755
--- a/configure
+++ b/configure
@@ -1040,7 +1040,7 @@ echo "  --disable-docs           disable documentation build"
 echo "  --disable-vhost-net      disable vhost-net acceleration support"
 echo "  --enable-vhost-net       enable vhost-net acceleration support"
 echo "  --enable-trace-backend=B Set trace backend"
-echo "                           Available backends:" $("$source_path"/scripts/tracetool --list-backends)
+echo "                           Available backends:" $("$source_path"/scripts/tracetool.py --list-backends)
 echo "  --with-trace-file=NAME   Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
@@ -2477,7 +2477,7 @@ fi
 ##########################################
 # check if trace backend exists
 
-sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
+$python "$source_path/scripts/tracetool.py" "--backend=$trace_backend" --check-backend  > /dev/null 2> /dev/null
 if test "$?" -ne 0 ; then
   echo
   echo "Error: invalid trace backend"
@@ -2495,7 +2495,8 @@ if test "$trace_backend" = "ust"; then
 int main(void) { return 0; }
 EOF
   if compile_prog "" "" ; then
-    LIBS="-lust $LIBS"
+    LIBS="-lust -lurcu-bp $LIBS"
+    libs_qga+="-lust -lurcu-bp"
   else
     echo
     echo "Error: Trace backend 'ust' missing libust header files"
diff --git a/scripts/tracetool b/scripts/tracetool
deleted file mode 100755
index 4c9951d..0000000
--- a/scripts/tracetool
+++ /dev/null
@@ -1,643 +0,0 @@
-#!/bin/sh
-#
-# Code generator for trace events
-#
-# Copyright IBM, Corp. 2010
-#
-# This work is licensed under the terms of the GNU GPL, version 2.  See
-# the COPYING file in the top-level directory.
-
-# Disable pathname expansion, makes processing text with '*' characters simpler
-set -f
-
-usage()
-{
-    cat >&2 <<EOF
-usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
-Generate tracing code for a file on stdin.
-
-Backends:
-  --nop     Tracing disabled
-  --simple  Simple built-in backend
-  --stderr  Stderr built-in backend
-  --ust     LTTng User Space Tracing backend
-  --dtrace  DTrace/SystemTAP backend
-
-Output formats:
-  -h     Generate .h file
-  -c     Generate .c file
-  -d     Generate .d file (DTrace only)
-  --stap Generate .stp file (DTrace with SystemTAP only)
-
-Options:
-  --binary       [path]    Full path to QEMU binary
-  --target-arch  [arch]    QEMU emulator target arch
-  --target-type  [type]    QEMU emulator target type ('system' or 'user')
-  --probe-prefix [prefix]  Prefix for dtrace probe names
-                           (default: qemu-\$targettype-\$targetarch)
-
-EOF
-    exit 1
-}
-
-# Print a line without interpreting backslash escapes
-#
-# The built-in echo command may interpret backslash escapes without an option
-# to disable this behavior.
-puts()
-{
-    printf "%s\n" "$1"
-}
-
-# Get the name of a trace event
-get_name()
-{
-    local name
-    name=${1%%\(*}
-    echo "${name##* }"
-}
-
-# Get the given property of a trace event
-# 1: trace-events line
-# 2: property name
-# -> return 0 if property is present, or 1 otherwise
-has_property()
-{
-    local props prop
-    props=${1%%\(*}
-    props=${props% *}
-    for prop in $props; do
-        if [ "$prop" = "$2" ]; then
-            return 0
-        fi
-    done
-    return 1
-}
-
-# Get the argument list of a trace event, including types and names
-get_args()
-{
-    local args
-    args=${1#*\(}
-    args=${args%%\)*}
-    echo "$args"
-}
-
-# Get the argument name list of a trace event
-get_argnames()
-{
-    local nfields field name sep
-    nfields=0
-    sep="$2"
-    for field in $(get_args "$1"); do
-        nfields=$((nfields + 1))
-
-        # Drop pointer star
-        field=${field#\*}
-
-        # Only argument names have commas at the end
-        name=${field%,}
-        test "$field" = "$name" && continue
-
-        printf "%s%s " $name $sep
-    done
-
-    # Last argument name
-    if [ "$nfields" -gt 1 ]
-    then
-        printf "%s" "$name"
-    fi
-}
-
-# Get the number of arguments to a trace event
-get_argc()
-{
-    local name argc
-    argc=0
-    for name in $(get_argnames "$1", ","); do
-        argc=$((argc + 1))
-    done
-    echo $argc
-}
-
-# Get the format string including double quotes for a trace event
-get_fmt()
-{
-    puts "${1#*)}"
-}
-
-linetoh_begin_nop()
-{
-    return
-}
-
-linetoh_nop()
-{
-    local name args
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-
-    # Define an empty function for the trace event
-    cat <<EOF
-static inline void trace_$name($args)
-{
-}
-EOF
-}
-
-linetoh_end_nop()
-{
-    return
-}
-
-linetoc_begin_nop()
-{
-    return
-}
-
-linetoc_nop()
-{
-    # No need for function definitions in nop backend
-    return
-}
-
-linetoc_end_nop()
-{
-    return
-}
-
-linetoh_begin_simple()
-{
-    cat <<EOF
-#include "trace/simple.h"
-EOF
-
-    simple_event_num=0
-}
-
-cast_args_to_uint64_t()
-{
-    local arg
-    for arg in $(get_argnames "$1", ","); do
-        printf "%s" "(uint64_t)(uintptr_t)$arg"
-    done
-}
-
-linetoh_simple()
-{
-    local name args argc trace_args
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    argc=$(get_argc "$1")
-
-    trace_args="$simple_event_num"
-    if [ "$argc" -gt 0 ]
-    then
-        trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
-    fi
-
-    cat <<EOF
-static inline void trace_$name($args)
-{
-    trace$argc($trace_args);
-}
-EOF
-
-    simple_event_num=$((simple_event_num + 1))
-}
-
-linetoh_end_simple()
-{
-    cat <<EOF
-#define NR_TRACE_EVENTS $simple_event_num
-extern TraceEvent trace_list[NR_TRACE_EVENTS];
-EOF
-}
-
-linetoc_begin_simple()
-{
-    cat <<EOF
-#include "trace.h"
-
-TraceEvent trace_list[] = {
-EOF
-    simple_event_num=0
-
-}
-
-linetoc_simple()
-{
-    local name
-    name=$(get_name "$1")
-    cat <<EOF
-{.tp_name = "$name", .state=0},
-EOF
-    simple_event_num=$((simple_event_num + 1))
-}
-
-linetoc_end_simple()
-{
-    cat <<EOF
-};
-EOF
-}
-
-#STDERR
-linetoh_begin_stderr()
-{
-    cat <<EOF
-#include <stdio.h>
-#include "trace/stderr.h"
-
-extern TraceEvent trace_list[];
-EOF
-
-    stderr_event_num=0
-}
-
-linetoh_stderr()
-{
-    local name args argnames argc fmt
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    argnames=$(get_argnames "$1" ",")
-    argc=$(get_argc "$1")
-    fmt=$(get_fmt "$1")
-
-    if [ "$argc" -gt 0 ]; then
-        argnames=", $argnames"
-    fi
-
-    cat <<EOF
-static inline void trace_$name($args)
-{
-    if (trace_list[$stderr_event_num].state != 0) {
-        fprintf(stderr, "$name " $fmt "\n" $argnames);
-    }
-}
-EOF
-    stderr_event_num=$((stderr_event_num + 1))
-
-}
-
-linetoh_end_stderr()
-{
-    cat <<EOF
-#define NR_TRACE_EVENTS $stderr_event_num
-EOF
-}
-
-linetoc_begin_stderr()
-{
-    cat <<EOF
-#include "trace.h"
-
-TraceEvent trace_list[] = {
-EOF
-    stderr_event_num=0
-}
-
-linetoc_stderr()
-{
-    local name
-    name=$(get_name "$1")
-    cat <<EOF
-{.tp_name = "$name", .state=0},
-EOF
-    stderr_event_num=$(($stderr_event_num + 1))
-}
-
-linetoc_end_stderr()
-{
-    cat <<EOF
-};
-EOF
-}
-#END OF STDERR
-
-# Clean up after UST headers which pollute the namespace
-ust_clean_namespace() {
-    cat <<EOF
-#undef mutex_lock
-#undef mutex_unlock
-#undef inline
-#undef wmb
-EOF
-}
-
-linetoh_begin_ust()
-{
-    echo "#include <ust/tracepoint.h>"
-    ust_clean_namespace
-}
-
-linetoh_ust()
-{
-    local name args argnames
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    argnames=$(get_argnames "$1", ",")
-
-    cat <<EOF
-DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
-#define trace_$name trace_ust_$name
-EOF
-}
-
-linetoh_end_ust()
-{
-    return
-}
-
-linetoc_begin_ust()
-{
-    cat <<EOF
-#include <ust/marker.h>
-$(ust_clean_namespace)
-#include "trace.h"
-EOF
-}
-
-linetoc_ust()
-{
-    local name args argnames fmt
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    argnames=$(get_argnames "$1", ",")
-    [ -z "$argnames" ] || argnames=", $argnames"
-    fmt=$(get_fmt "$1")
-
-    cat <<EOF
-DEFINE_TRACE(ust_$name);
-
-static void ust_${name}_probe($args)
-{
-    trace_mark(ust, $name, $fmt$argnames);
-}
-EOF
-
-    # Collect names for later
-    names="$names $name"
-}
-
-linetoc_end_ust()
-{
-    cat <<EOF
-static void __attribute__((constructor)) trace_init(void)
-{
-EOF
-
-    for name in $names; do
-        cat <<EOF
-    register_trace_ust_$name(ust_${name}_probe);
-EOF
-    done
-
-    echo "}"
-}
-
-linetoh_begin_dtrace()
-{
-    cat <<EOF
-#include "trace-dtrace.h"
-EOF
-}
-
-linetoh_dtrace()
-{
-    local name args argnames nameupper
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    argnames=$(get_argnames "$1", ",")
-
-    nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
-
-    # Define an empty function for the trace event
-    cat <<EOF
-static inline void trace_$name($args) {
-    if (QEMU_${nameupper}_ENABLED()) {
-        QEMU_${nameupper}($argnames);
-    }
-}
-EOF
-}
-
-linetoh_end_dtrace()
-{
-    return
-}
-
-linetoc_begin_dtrace()
-{
-    return
-}
-
-linetoc_dtrace()
-{
-    # No need for function definitions in dtrace backend
-    return
-}
-
-linetoc_end_dtrace()
-{
-    return
-}
-
-linetod_begin_dtrace()
-{
-    cat <<EOF
-provider qemu {
-EOF
-}
-
-linetod_dtrace()
-{
-    local name args
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-
-    # DTrace provider syntax expects foo() for empty
-    # params, not foo(void)
-    if [ "$args" = "void" ]; then
-       args=""
-    fi
-
-    # Define prototype for probe arguments
-    cat <<EOF
-        probe $name($args);
-EOF
-}
-
-linetod_end_dtrace()
-{
-    cat <<EOF
-};
-EOF
-}
-
-linetostap_begin_dtrace()
-{
-    return
-}
-
-linetostap_dtrace()
-{
-    local i arg name args arglist
-    name=$(get_name "$1")
-    args=$(get_args "$1")
-    arglist=$(get_argnames "$1", "")
-
-    # Define prototype for probe arguments
-    cat <<EOF
-probe $probeprefix.$name = process("$binary").mark("$name")
-{
-EOF
-
-    i=1
-    for arg in $arglist
-    do
-        # 'limit' is a reserved keyword
-        if [ "$arg" = "limit" ]; then
-          arg="_limit"
-        fi
-        cat <<EOF
-  $arg = \$arg$i;
-EOF
-        i="$((i+1))"
-    done
-
-    cat <<EOF
-}
-EOF
-}
-
-linetostap_end_dtrace()
-{
-    return
-}
-
-# Process stdin by calling begin, line, and end functions for the backend
-convert()
-{
-    local begin process_line end str disable
-    begin="lineto$1_begin_$backend"
-    process_line="lineto$1_$backend"
-    end="lineto$1_end_$backend"
-
-    "$begin"
-
-    while read -r str; do
-        # Skip comments and empty lines
-        test -z "${str%%#*}" && continue
-
-        echo
-        # Process the line.  The nop backend handles disabled lines.
-        if has_property "$str" "disable"; then
-            "lineto$1_nop" "$str"
-        else
-            "$process_line" "$str"
-        fi
-    done
-
-    echo
-    "$end"
-}
-
-tracetoh()
-{
-    cat <<EOF
-#ifndef TRACE_H
-#define TRACE_H
-
-/* This file is autogenerated by tracetool, do not edit. */
-
-#include "qemu-common.h"
-EOF
-    convert h
-    echo "#endif /* TRACE_H */"
-}
-
-tracetoc()
-{
-    echo "/* This file is autogenerated by tracetool, do not edit. */"
-    convert c
-}
-
-tracetod()
-{
-    if [ $backend != "dtrace" ]; then
-       echo "DTrace probe generator not applicable to $backend backend"
-       exit 1
-    fi
-    echo "/* This file is autogenerated by tracetool, do not edit. */"
-    convert d
-}
-
-tracetostap()
-{
-    if [ $backend != "dtrace" ]; then
-       echo "SystemTAP tapset generator not applicable to $backend backend"
-       exit 1
-    fi
-    if [ -z "$binary" ]; then
-       echo "--binary is required for SystemTAP tapset generator"
-       exit 1
-    fi
-    if [ -z "$probeprefix" -a -z "$targettype" ]; then
-       echo "--target-type is required for SystemTAP tapset generator"
-       exit 1
-    fi
-    if [ -z "$probeprefix" -a -z "$targetarch" ]; then
-       echo "--target-arch is required for SystemTAP tapset generator"
-       exit 1
-    fi
-    if [ -z "$probeprefix" ]; then
-        probeprefix="qemu.$targettype.$targetarch";
-    fi
-    echo "/* This file is autogenerated by tracetool, do not edit. */"
-    convert stap
-}
-
-
-backend=
-output=
-binary=
-targettype=
-targetarch=
-probeprefix=
-
-
-until [ -z "$1" ]
-do
-  case "$1" in
-    "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
-
-    "--binary") shift ; binary="$1" ;;
-    "--target-arch") shift ; targetarch="$1" ;;
-    "--target-type") shift ; targettype="$1" ;;
-    "--probe-prefix") shift ; probeprefix="$1" ;;
-
-    "-h" | "-c" | "-d") output="${1#-}" ;;
-    "--stap") output="${1#--}" ;;
-
-    "--check-backend") exit 0 ;; # used by ./configure to test for backend
-
-    "--list-backends") # used by ./configure to list available backends
-          echo "nop simple stderr ust dtrace"
-          exit 0
-          ;;
-
-    *)
-      usage;;
-  esac
-  shift
-done
-
-if [ "$backend" = "" -o "$output" = "" ]; then
-  usage
-fi
-
-gen="traceto$output"
-"$gen"
-
-exit 0
diff --git a/scripts/tracetool.py b/scripts/tracetool.py
new file mode 100755
index 0000000..079ec7a
--- /dev/null
+++ b/scripts/tracetool.py
@@ -0,0 +1,534 @@
+#!/usr/bin/env python
+# Code generator for trace events
+#
+# Copyright IBM, Corp. 2011
+#
+# This work is licensed under the terms of the GNU GPL, version 2.  See
+# the COPYING file in the top-level directory.
+#
+#
+
+import sys
+import getopt
+
+def usage():
+    print "Tracetool: Generate tracing code for trace events file on stdin"
+    print "Usage:"
+    print sys.argv[0], "--backend=[nop|simple|stderr|dtrace|ust] [-h|-c|-d|--stap]"
+    print '''
+Backends:
+  --nop     Tracing disabled
+  --simple  Simple built-in backend
+  --stderr  Stderr built-in backend
+  --dtrace  DTrace/SystemTAP backend
+  --ust     LTTng User Space Tracing backend
+
+Output formats:
+  -h     Generate .h file
+  -c     Generate .c file
+  -d     Generate .d file (DTrace only)
+  --stap Generate .stp file (DTrace with SystemTAP only)
+
+Options:
+  --binary       [path]    Full path to QEMU binary
+  --target-arch  [arch]    QEMU emulator target arch
+  --target-type  [type]    QEMU emulator target type ('system' or 'user')
+  --probe-prefix [prefix]  Prefix for dtrace probe names
+                           (default: qemu-targettype-targetarch)
+'''
+    sys.exit(1)
+
+def get_name(line, sep='('):
+    head, sep, tail = line.partition(sep)
+    property, sep, name = head.rpartition(' ')
+    return name
+
+def get_properties(line, sep='('):
+    head, sep, tail = line.partition(sep)
+    property, sep, name = head.rpartition(' ')
+    return property.split()
+
+def get_args(line, sep1='(', sep2=')'):
+    head, sep1, tail = line.partition(sep1)
+    args, sep2, fmt_str = tail.partition(sep2)
+    return args
+
+def get_argnames(line, sep=','):
+    nfields = 0
+    str = []
+    args = get_args(line)
+    for field in args.split():
+      nfields = nfields + 1
+      # Drop pointer star
+      type, ptr, tail = field.partition('*')
+      if type != field:
+        field = tail
+
+      name, sep, tail = field.partition(',')
+
+      if name == field:
+        continue
+      str.append(name)
+      str.append(", ")
+
+    if nfields > 1:
+      str.append(name)
+      return ''.join(str)
+    else:
+      return ''
+
+def get_argc(line):
+    argc = 0
+    argnames = get_argnames(line)
+    if argnames:
+      for name in argnames.split(','):
+        argc = argc + 1
+    return argc
+
+def get_fmt(line, sep=')'):
+    event, sep, fmt = line.partition(sep)
+    return fmt.rstrip('\n')
+
+def calc_sizeofargs(line):
+    args = get_args(line)
+    argc = get_argc(line)
+    str = []
+    newstr = ""
+    if argc > 0:
+      str = args.split(',')
+      for elem in str:
+        if is_string(elem): #string
+          type, sep, var = elem.rpartition('*')
+          newstr = newstr+"4 + strlen("+var.lstrip()+") + "
+        else:
+          newstr = newstr + '8 + '
+    newstr = newstr + '0' # takes care of last +
+    return newstr
+
+
+def trace_h_begin():
+    print '''#ifndef TRACE_H
+#define TRACE_H
+
+/* This file is autogenerated by tracetool, do not edit. */
+
+#include "qemu-common.h"'''
+
+
+def trace_h_end():
+    print '#endif /* TRACE_H */'
+
+
+def trace_c_begin():
+    print '/* This file is autogenerated by tracetool, do not edit. */'
+
+def trace_c_end():
+    pass # nop, required for trace_gen
+
+def nop_h(events):
+    print
+    for event in events:
+        print '''static inline void trace_%(name)s(%(args)s)
+{
+}
+''' % {
+    'name': event.name,
+    'args': event.args
+}
+    return
+
+def nop_c(events):
+    pass # nop, reqd for converters
+
+def simple_h(events):
+    print '#include "trace/simple.h"'
+    print
+
+    for event in events:
+        if event.argc:
+            argstr = event.argnames.split()
+            arg_prefix = '(uint64_t)(uintptr_t)'
+            cast_args = arg_prefix + arg_prefix.join(argstr)
+            simple_args = (str(event.num) + ', ' + cast_args)
+        else:
+            simple_args = str(event.num)
+
+        print '''static inline void trace_%(name)s(%(args)s)
+{
+    trace%(argc)d(%(trace_args)s);
+}''' % {
+    'name': event.name,
+    'args': event.args,
+    'argc': event.argc,
+    'trace_args': simple_args
+}
+        print
+    print '#define NR_TRACE_EVENTS %d' % (event.num + 1)
+    print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];'
+
+
+def is_string(arg):
+    strtype = ('const char*', 'char*', 'const char *', 'char *')
+    if arg.lstrip().startswith(strtype):
+        return True
+    else:
+        return False
+
+def simple_c(events):
+    print '#include "trace.h"'
+    print
+    print 'TraceEvent trace_list[] = {'
+    print
+
+    for event in events:
+        print '{.tp_name = "%(name)s", .state=0},' % {
+    'name': event.name,
+}
+        print
+    print '};'
+
+def stderr_h(events):
+    print '''#include <stdio.h>
+#include "trace/stderr.h"
+
+extern TraceEvent trace_list[];'''
+    for event in events:
+        argnames = event.argnames
+        if event.argc > 0:
+            argnames = ', ' + event.argnames
+        else:
+            argnames = ''
+        print '''
+static inline void trace_%(name)s(%(args)s)
+{
+    if (trace_list[%(event_num)s].state != 0) {
+        fprintf(stderr, "%(name)s " %(fmt)s "\\n" %(argnames)s);
+    }
+}''' % {
+    'name': event.name,
+    'args': event.args,
+    'event_num': event.num,
+    'fmt': event.fmt,
+    'argnames': argnames
+}
+    print
+    print '#define NR_TRACE_EVENTS %d' % (event.num + 1)
+
+def stderr_c(events):
+    print '''#include "trace.h"
+
+TraceEvent trace_list[] = {
+'''
+    for event in events:
+        print '{.tp_name = "%(name)s", .state=0},' % {
+    'name': event.name
+}
+        print
+    print '};'
+
+def ust_h(events):
+    print '''#include <ust/tracepoint.h>
+#undef mutex_lock
+#undef mutex_unlock
+#undef inline
+#undef wmb'''
+
+    for event in events:
+        if event.argc > 0:
+            print '''
+DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s));
+#define trace_%(name)s trace_ust_%(name)s''' % {
+    'name': event.name,
+    'args': event.args,
+    'argnames': event.argnames
+}
+        else:
+            print '''
+_DECLARE_TRACEPOINT_NOARGS(ust_%(name)s);
+#define trace_%(name)s trace_ust_%(name)s''' % {
+    'name': event.name,
+}
+    print
+
+def ust_c(events):
+    print '''#include <ust/marker.h>
+#undef mutex_lock
+#undef mutex_unlock
+#undef inline
+#undef wmb
+#include "trace.h"'''
+    eventlist = list(events)
+    for event in eventlist:
+        argnames = event.argnames
+        if event.argc > 0:
+            argnames = ', ' + event.argnames
+            print '''
+DEFINE_TRACE(ust_%(name)s);
+
+static void ust_%(name)s_probe(%(args)s)
+{
+    trace_mark(ust, %(name)s, %(fmt)s%(argnames)s);
+}''' % {
+    'name': event.name,
+    'args': event.args,
+    'fmt': event.fmt,
+    'argnames': argnames
+}
+        else:
+            print '''
+DEFINE_TRACE(ust_%(name)s);
+
+static void ust_%(name)s_probe(%(args)s)
+{
+    trace_mark(ust, %(name)s, UST_MARKER_NOARGS);
+}''' % {
+    'name': event.name,
+    'args': event.args,
+}
+
+    # register probes
+    print '''
+static void __attribute__((constructor)) trace_init(void)
+{'''
+    for event in eventlist:
+        print '    register_trace_ust_%(name)s(ust_%(name)s_probe);' % {
+    'name': event.name
+}
+    print '}'
+
+def dtrace_h(events):
+    print '#include "trace-dtrace.h"'
+    print
+    for event in events:
+        print '''static inline void trace_%(name)s(%(args)s) {
+    if (QEMU_%(uppername)s_ENABLED()) {
+        QEMU_%(uppername)s(%(argnames)s);
+    }
+}
+''' % {
+    'name': event.name,
+    'args': event.args,
+    'uppername': event.name.upper(),
+    'argnames': event.argnames,
+}
+
+def dtrace_c(events):
+    pass # No need for function definitions in dtrace backend
+
+def dtrace_d(events):
+    print 'provider qemu {'
+    for event in events:
+        args = event.args
+
+        # DTrace provider syntax expects foo() for empty
+        # params, not foo(void)
+        if args == 'void':
+            args = ''
+
+        # Define prototype for probe arguments
+        print '''
+        probe %(name)s(%(args)s);''' % {
+        'name': event.name,
+        'args': args
+}
+    print
+    print '};'
+
+def dtrace_stp(events):
+    for event in events:
+        # Define prototype for probe arguments
+        print '''
+probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")
+{''' % {
+    'probeprefix': probeprefix,
+    'name': event.name,
+    'binary': binary
+}
+        i = 1
+        if event.argc > 0:
+            for arg in event.argnames.split(','):
+                # 'limit' is a reserved keyword
+                if arg == 'limit':
+                    arg = '_limit'
+                print '  %s = $arg%d;' % (arg.lstrip(), i)
+                i += 1
+        print '}'
+    print
+
+def trace_stap_begin():
+    print '/* This file is autogenerated by tracetool, do not edit. */'
+
+def trace_stap_end():
+    pass #nop, reqd for trace_gen
+
+def trace_d_begin():
+    print '/* This file is autogenerated by tracetool, do not edit. */'
+
+def trace_d_end():
+    pass #nop, reqd for trace_gen
+
+
+# Registry of backends and their converter functions
+converters = {
+    'simple': {
+        'h': simple_h,
+        'c': simple_c,
+    },
+
+    'nop': {
+        'h': nop_h,
+        'c': nop_c,
+    },
+
+    'stderr': {
+        'h': stderr_h,
+        'c': stderr_c,
+    },
+
+    'dtrace': {
+        'h': dtrace_h,
+        'c': dtrace_c,
+        'd': dtrace_d,
+        'stap': dtrace_stp
+    },
+
+    'ust': {
+        'h': ust_h,
+        'c': ust_c,
+    },
+
+}
+
+# Trace file header and footer code generators
+trace_gen = {
+    'h': {
+        'begin': trace_h_begin,
+        'end': trace_h_end,
+    },
+    'c': {
+        'begin': trace_c_begin,
+        'end': trace_c_end,
+    },
+    'd': {
+        'begin': trace_d_begin,
+        'end': trace_d_end,
+    },
+    'stap': {
+        'begin': trace_stap_begin,
+        'end': trace_stap_end,
+    },
+}
+
+# A trace event
+class Event(object):
+    def __init__(self, num, line):
+        self.num = num
+        self.args = get_args(line)
+        self.arglist = self.args.split(',')
+        self.name = get_name(line)
+        self.argc = get_argc(line)
+        self.argnames = get_argnames(line)
+        self.sizestr = calc_sizeofargs(line)
+        self.fmt = get_fmt(line)
+        self.properties = get_properties(line)
+
+# Generator that yields Event objects given a trace-events file object
+def read_events(fobj):
+    event_num = 0
+    for line in fobj:
+        if not line.strip():
+            continue
+        if line.lstrip().startswith('#'):
+	    continue
+        yield Event(event_num, line)
+        event_num += 1
+
+binary = ""
+probeprefix = ""
+
+def main():
+    global binary, probeprefix
+    targettype = ""
+    targetarch = ""
+    supported_backends = ["simple", "nop", "stderr", "dtrace", "ust"]
+    short_options = "hcd"
+    long_options = ["stap", "backend=", "binary=", "target-arch=", "target-type=", "probe-prefix=", "list-backends", "check-backend"]
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], short_options, long_options)
+    except getopt.GetoptError, err:
+        # print help information and exit:
+        print str(err) # will print something like "option -a not recognized"
+        usage()
+        sys.exit(2)
+    for opt, arg in opts:
+        if opt == '-h':
+            output = 'h'
+        elif opt == '-c':
+            output = 'c'
+        elif opt == '-d':
+            output = 'd'
+        elif opt == '--stap':
+            output = 'stap'
+        elif opt == '--backend':
+            backend = arg
+        elif opt == '--binary':
+            binary = arg
+        elif opt == '--target-arch':
+            targetarch = arg
+        elif opt == '--target-type':
+            targettype = arg
+        elif opt == '--probe-prefix':
+            probeprefix = arg
+        elif opt == '--list-backends':
+            print 'simple, nop, stderr, dtrace, ust'
+            sys.exit(0)
+        elif opt == "--check-backend":
+            if any(backend in s for s in supported_backends):
+                sys.exit(0)
+            else:
+                sys.exit(1)
+        else:
+            #assert False, "unhandled option"
+            print "unhandled option: ", opt
+            usage()
+
+    if backend == "" or output == "":
+        usage()
+        sys.exit(0)
+
+    if backend != 'dtrace' and output == 'd':
+        print 'DTrace probe generator not applicable to %s backend' % backend
+        sys.exit(1)
+
+    if output == 'stap':
+        if backend != "dtrace":
+            print 'SystemTAP tapset generator not applicable to %s backend' % backend
+            sys.exit(1)
+        if binary == "":
+            print '--binary is required for SystemTAP tapset generator'
+            sys.exit(1)
+        if not probeprefix and  not targettype:
+            print '--target-type is required for SystemTAP tapset generator'
+            sys.exit(1)
+        if not probeprefix and  not targetarch:
+            print '--target-arch is required for SystemTAP tapset generator'
+            sys.exit(1)
+        if probeprefix == "":
+            probeprefix = 'qemu.' + targettype + '.' + targetarch
+
+    disabled_events, enabled_events = [], []
+    for e in read_events(sys.stdin):
+        if 'disable' in e.properties:
+            disabled_events.append(e)
+        else:
+            enabled_events.append(e)
+
+    trace_gen[output]['begin']()
+    if output == 'h': # disabled events
+        converters['nop'][output](disabled_events)
+    converters[backend][output](enabled_events)
+    trace_gen[output]['end']()
+
+if __name__ == "__main__":
+    main()
+
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 02/14] trace: [tracetool] Do not rebuild event list in backend code
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 01/14] Converting tracetool.sh to tracetool.py Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 03/14] trace: [tracetool] Simplify event line parsing Harsh Prateek Bora
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 079ec7a..274fa70 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -257,8 +257,7 @@ def ust_c(events):
 #undef inline
 #undef wmb
 #include "trace.h"'''
-    eventlist = list(events)
-    for event in eventlist:
+    for event in events:
         argnames = event.argnames
         if event.argc > 0:
             argnames = ', ' + event.argnames
@@ -290,7 +289,7 @@ static void ust_%(name)s_probe(%(args)s)
     print '''
 static void __attribute__((constructor)) trace_init(void)
 {'''
-    for event in eventlist:
+    for event in events:
         print '    register_trace_ust_%(name)s(ust_%(name)s_probe);' % {
     'name': event.name
 }
@@ -435,13 +434,15 @@ class Event(object):
 # Generator that yields Event objects given a trace-events file object
 def read_events(fobj):
     event_num = 0
+    res = []
     for line in fobj:
         if not line.strip():
             continue
         if line.lstrip().startswith('#'):
 	    continue
-        yield Event(event_num, line)
+        res.append(Event(event_num, line))
         event_num += 1
+    return res
 
 binary = ""
 probeprefix = ""
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 03/14] trace: [tracetool] Simplify event line parsing
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 01/14] Converting tracetool.sh to tracetool.py Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 02/14] trace: [tracetool] Do not rebuild event list in backend code Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 04/14] trace: [tracetool] Do not precompute the event number Harsh Prateek Bora
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   50 +++++++++++++++++---------------------------------
 1 files changed, 17 insertions(+), 33 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 274fa70..84003f5 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -10,6 +10,7 @@
 
 import sys
 import getopt
+import re
 
 def usage():
     print "Tracetool: Generate tracing code for trace events file on stdin"
@@ -38,25 +39,14 @@ Options:
 '''
     sys.exit(1)
 
-def get_name(line, sep='('):
-    head, sep, tail = line.partition(sep)
-    property, sep, name = head.rpartition(' ')
-    return name
-
 def get_properties(line, sep='('):
     head, sep, tail = line.partition(sep)
     property, sep, name = head.rpartition(' ')
     return property.split()
 
-def get_args(line, sep1='(', sep2=')'):
-    head, sep1, tail = line.partition(sep1)
-    args, sep2, fmt_str = tail.partition(sep2)
-    return args
-
-def get_argnames(line, sep=','):
+def get_argnames(args):
     nfields = 0
     str = []
-    args = get_args(line)
     for field in args.split():
       nfields = nfields + 1
       # Drop pointer star
@@ -77,21 +67,7 @@ def get_argnames(line, sep=','):
     else:
       return ''
 
-def get_argc(line):
-    argc = 0
-    argnames = get_argnames(line)
-    if argnames:
-      for name in argnames.split(','):
-        argc = argc + 1
-    return argc
-
-def get_fmt(line, sep=')'):
-    event, sep, fmt = line.partition(sep)
-    return fmt.rstrip('\n')
-
-def calc_sizeofargs(line):
-    args = get_args(line)
-    argc = get_argc(line)
+def calc_sizeofargs(args, argc):
     str = []
     newstr = ""
     if argc > 0:
@@ -419,16 +395,24 @@ trace_gen = {
 }
 
 # A trace event
+cre = re.compile("(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
+
 class Event(object):
     def __init__(self, num, line):
         self.num = num
-        self.args = get_args(line)
+        m = cre.match(line)
+        assert m is not None
+        groups = m.groupdict('')
+        self.args = groups["args"]
         self.arglist = self.args.split(',')
-        self.name = get_name(line)
-        self.argc = get_argc(line)
-        self.argnames = get_argnames(line)
-        self.sizestr = calc_sizeofargs(line)
-        self.fmt = get_fmt(line)
+        self.name = groups["name"]
+        if len(self.arglist) == 1 and self.arglist[0] == "void":
+            self.argc = 0
+        else:
+            self.argc = len(self.arglist)
+        self.argnames = get_argnames(self.args)
+        self.sizestr = calc_sizeofargs(self.args, self.argc)
+        self.fmt = groups["fmt"]
         self.properties = get_properties(line)
 
 # Generator that yields Event objects given a trace-events file object
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 04/14] trace: [tracetool] Do not precompute the event number
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (2 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 03/14] trace: [tracetool] Simplify event line parsing Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 05/14] trace: [tracetool] Add support for event properties Harsh Prateek Bora
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   21 +++++++++------------
 1 files changed, 9 insertions(+), 12 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 84003f5..1085fc4 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -120,14 +120,14 @@ def simple_h(events):
     print '#include "trace/simple.h"'
     print
 
-    for event in events:
+    for num, event in enumerate(events):
         if event.argc:
             argstr = event.argnames.split()
             arg_prefix = '(uint64_t)(uintptr_t)'
             cast_args = arg_prefix + arg_prefix.join(argstr)
-            simple_args = (str(event.num) + ', ' + cast_args)
+            simple_args = (str(num) + ', ' + cast_args)
         else:
-            simple_args = str(event.num)
+            simple_args = str(num)
 
         print '''static inline void trace_%(name)s(%(args)s)
 {
@@ -139,7 +139,7 @@ def simple_h(events):
     'trace_args': simple_args
 }
         print
-    print '#define NR_TRACE_EVENTS %d' % (event.num + 1)
+    print '#define NR_TRACE_EVENTS %d' % len(events)
     print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];'
 
 
@@ -168,7 +168,7 @@ def stderr_h(events):
 #include "trace/stderr.h"
 
 extern TraceEvent trace_list[];'''
-    for event in events:
+    for num, event in enumerate(events):
         argnames = event.argnames
         if event.argc > 0:
             argnames = ', ' + event.argnames
@@ -183,12 +183,12 @@ static inline void trace_%(name)s(%(args)s)
 }''' % {
     'name': event.name,
     'args': event.args,
-    'event_num': event.num,
+    'event_num': num,
     'fmt': event.fmt,
     'argnames': argnames
 }
     print
-    print '#define NR_TRACE_EVENTS %d' % (event.num + 1)
+    print '#define NR_TRACE_EVENTS %d' % len(events)
 
 def stderr_c(events):
     print '''#include "trace.h"
@@ -398,8 +398,7 @@ trace_gen = {
 cre = re.compile("(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
 
 class Event(object):
-    def __init__(self, num, line):
-        self.num = num
+    def __init__(self, line):
         m = cre.match(line)
         assert m is not None
         groups = m.groupdict('')
@@ -417,15 +416,13 @@ class Event(object):
 
 # Generator that yields Event objects given a trace-events file object
 def read_events(fobj):
-    event_num = 0
     res = []
     for line in fobj:
         if not line.strip():
             continue
         if line.lstrip().startswith('#'):
 	    continue
-        res.append(Event(event_num, line))
-        event_num += 1
+        res.append(Event(line))
     return res
 
 binary = ""
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 05/14] trace: [tracetool] Add support for event properties
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (3 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 04/14] trace: [tracetool] Do not precompute the event number Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 06/14] trace: [tracetool] Process the "disable" event property Harsh Prateek Bora
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 1085fc4..3502524 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -39,11 +39,6 @@ Options:
 '''
     sys.exit(1)
 
-def get_properties(line, sep='('):
-    head, sep, tail = line.partition(sep)
-    property, sep, name = head.rpartition(' ')
-    return property.split()
-
 def get_argnames(args):
     nfields = 0
     str = []
@@ -395,7 +390,9 @@ trace_gen = {
 }
 
 # A trace event
-cre = re.compile("(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
+cre = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
+
+VALID_PROPS = set(["disable"])
 
 class Event(object):
     def __init__(self, line):
@@ -412,7 +409,10 @@ class Event(object):
         self.argnames = get_argnames(self.args)
         self.sizestr = calc_sizeofargs(self.args, self.argc)
         self.fmt = groups["fmt"]
-        self.properties = get_properties(line)
+        self.properties = groups["props"].split()
+        unknown_props = set(self.properties) - VALID_PROPS
+        if len(unknown_props) > 0:
+            raise ValueError("Unknown properties: %s" % ", ".join(unknown_props))
 
 # Generator that yields Event objects given a trace-events file object
 def read_events(fobj):
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 06/14] trace: [tracetool] Process the "disable" event property
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (4 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 05/14] trace: [tracetool] Add support for event properties Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 07/14] trace: [tracetool] Rewrite event argument parsing Harsh Prateek Bora
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 3502524..1cf5c8f 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -304,6 +304,9 @@ def dtrace_d(events):
     print
     print '};'
 
+def dtrace_nop_d(events):
+    pass
+
 def dtrace_stp(events):
     for event in events:
         # Define prototype for probe arguments
@@ -325,6 +328,9 @@ probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")
         print '}'
     print
 
+def dtrace_nop_stp(events):
+    pass
+
 def trace_stap_begin():
     print '/* This file is autogenerated by tracetool, do not edit. */'
 
@@ -348,6 +354,8 @@ converters = {
     'nop': {
         'h': nop_h,
         'c': nop_c,
+        'd': dtrace_nop_d,
+        'stap': dtrace_nop_stp,
     },
 
     'stderr': {
@@ -498,17 +506,11 @@ def main():
         if probeprefix == "":
             probeprefix = 'qemu.' + targettype + '.' + targetarch
 
-    disabled_events, enabled_events = [], []
-    for e in read_events(sys.stdin):
-        if 'disable' in e.properties:
-            disabled_events.append(e)
-        else:
-            enabled_events.append(e)
+    events = read_events(sys.stdin)
 
     trace_gen[output]['begin']()
-    if output == 'h': # disabled events
-        converters['nop'][output](disabled_events)
-    converters[backend][output](enabled_events)
+    converters[backend][output]([ e for e in events if 'disable' not in e.properties ])
+    converters['nop'][output]([ e for e in events if 'disable' in e.properties ])
     trace_gen[output]['end']()
 
 if __name__ == "__main__":
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 07/14] trace: [tracetool] Rewrite event argument parsing
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (5 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 06/14] trace: [tracetool] Process the "disable" event property Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 08/14] trace: [tracetool] Make format-specific code optional with access to events Harsh Prateek Bora
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |  136 +++++++++++++++++++++++---------------------------
 1 files changed, 62 insertions(+), 74 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 1cf5c8f..986dc4d 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -39,44 +39,6 @@ Options:
 '''
     sys.exit(1)
 
-def get_argnames(args):
-    nfields = 0
-    str = []
-    for field in args.split():
-      nfields = nfields + 1
-      # Drop pointer star
-      type, ptr, tail = field.partition('*')
-      if type != field:
-        field = tail
-
-      name, sep, tail = field.partition(',')
-
-      if name == field:
-        continue
-      str.append(name)
-      str.append(", ")
-
-    if nfields > 1:
-      str.append(name)
-      return ''.join(str)
-    else:
-      return ''
-
-def calc_sizeofargs(args, argc):
-    str = []
-    newstr = ""
-    if argc > 0:
-      str = args.split(',')
-      for elem in str:
-        if is_string(elem): #string
-          type, sep, var = elem.rpartition('*')
-          newstr = newstr+"4 + strlen("+var.lstrip()+") + "
-        else:
-          newstr = newstr + '8 + '
-    newstr = newstr + '0' # takes care of last +
-    return newstr
-
-
 def trace_h_begin():
     print '''#ifndef TRACE_H
 #define TRACE_H
@@ -116,11 +78,11 @@ def simple_h(events):
     print
 
     for num, event in enumerate(events):
-        if event.argc:
-            argstr = event.argnames.split()
-            arg_prefix = '(uint64_t)(uintptr_t)'
+        if len(event.args):
+            argstr = event.args.names()
+            arg_prefix = ', (uint64_t)(uintptr_t)'
             cast_args = arg_prefix + arg_prefix.join(argstr)
-            simple_args = (str(num) + ', ' + cast_args)
+            simple_args = (str(num) + cast_args)
         else:
             simple_args = str(num)
 
@@ -130,7 +92,7 @@ def simple_h(events):
 }''' % {
     'name': event.name,
     'args': event.args,
-    'argc': event.argc,
+    'argc': len(event.args),
     'trace_args': simple_args
 }
         print
@@ -138,13 +100,6 @@ def simple_h(events):
     print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];'
 
 
-def is_string(arg):
-    strtype = ('const char*', 'char*', 'const char *', 'char *')
-    if arg.lstrip().startswith(strtype):
-        return True
-    else:
-        return False
-
 def simple_c(events):
     print '#include "trace.h"'
     print
@@ -164,11 +119,9 @@ def stderr_h(events):
 
 extern TraceEvent trace_list[];'''
     for num, event in enumerate(events):
-        argnames = event.argnames
-        if event.argc > 0:
-            argnames = ', ' + event.argnames
-        else:
-            argnames = ''
+        argnames = ", ".join(event.args.names())
+        if len(event.args) > 0:
+            argnames = ", " + argnames
         print '''
 static inline void trace_%(name)s(%(args)s)
 {
@@ -205,13 +158,13 @@ def ust_h(events):
 #undef wmb'''
 
     for event in events:
-        if event.argc > 0:
+        if len(event.args) > 0:
             print '''
 DECLARE_TRACE(ust_%(name)s, TP_PROTO(%(args)s), TP_ARGS(%(argnames)s));
 #define trace_%(name)s trace_ust_%(name)s''' % {
     'name': event.name,
     'args': event.args,
-    'argnames': event.argnames
+    'argnames': ", ".join(event.args.names())
 }
         else:
             print '''
@@ -229,9 +182,9 @@ def ust_c(events):
 #undef wmb
 #include "trace.h"'''
     for event in events:
-        argnames = event.argnames
-        if event.argc > 0:
-            argnames = ', ' + event.argnames
+        argnames = ", ".join(event.args.names())
+        if len(event.args) > 0:
+            argnames = ', ' + argnames
             print '''
 DEFINE_TRACE(ust_%(name)s);
 
@@ -279,7 +232,7 @@ def dtrace_h(events):
     'name': event.name,
     'args': event.args,
     'uppername': event.name.upper(),
-    'argnames': event.argnames,
+    'argnames': ", ".join(event.args.names()),
 }
 
 def dtrace_c(events):
@@ -318,12 +271,12 @@ probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")
     'binary': binary
 }
         i = 1
-        if event.argc > 0:
-            for arg in event.argnames.split(','):
+        if len(event.args) > 0:
+            for name in event.args.names():
                 # 'limit' is a reserved keyword
-                if arg == 'limit':
-                    arg = '_limit'
-                print '  %s = $arg%d;' % (arg.lstrip(), i)
+                if name == 'limit':
+                    name = '_limit'
+                print '  %s = $arg%d;' % (name.lstrip(), i)
                 i += 1
         print '}'
     print
@@ -397,6 +350,47 @@ trace_gen = {
     },
 }
 
+# Event arguments
+def type_is_string(type_):
+    strtype = ('const char*', 'char*', 'const char *', 'char *')
+    return type_.lstrip().startswith(strtype)
+
+class Arguments:
+    def __init__ (self, arg_str):
+        self._args = []
+        for arg in arg_str.split(","):
+            arg = arg.strip()
+            parts = arg.split()
+            head, sep, tail = parts[-1].rpartition("*")
+            parts = parts[:-1]
+            if tail == "void":
+                assert len(parts) == 0 and sep == ""
+                continue
+            arg_type = " ".join(parts + [ " ".join([head, sep]).strip() ]).strip()
+            self._args.append((arg_type, tail))
+
+    def __iter__(self):
+        return iter(self._args)
+
+    def __len__(self):
+        return len(self._args)
+
+    def __str__(self):
+        if len(self._args) == 0:
+            return "void"
+        else:
+            return ", ".join([ " ".join([t, n]) for t,n in self._args ])
+
+    def names(self):
+        return [ name for _, name in self._args ]
+
+    def types(self):
+        return [ type_ for type_, _ in self._args ]
+
+    def size_str(self):
+        res = ""
+        return res
+
 # A trace event
 cre = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
 
@@ -407,17 +401,11 @@ class Event(object):
         m = cre.match(line)
         assert m is not None
         groups = m.groupdict('')
-        self.args = groups["args"]
-        self.arglist = self.args.split(',')
         self.name = groups["name"]
-        if len(self.arglist) == 1 and self.arglist[0] == "void":
-            self.argc = 0
-        else:
-            self.argc = len(self.arglist)
-        self.argnames = get_argnames(self.args)
-        self.sizestr = calc_sizeofargs(self.args, self.argc)
         self.fmt = groups["fmt"]
         self.properties = groups["props"].split()
+        self.args = Arguments(groups["args"])
+
         unknown_props = set(self.properties) - VALID_PROPS
         if len(unknown_props) > 0:
             raise ValueError("Unknown properties: %s" % ", ".join(unknown_props))
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 08/14] trace: [tracetool] Make format-specific code optional with access to events
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (6 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 07/14] trace: [tracetool] Rewrite event argument parsing Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 09/14] trace: [tracetool] Automatically establish available backends and formats Harsh Prateek Bora
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   32 ++++++++++----------------------
 1 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 986dc4d..2d6f9ee 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -39,7 +39,7 @@ Options:
 '''
     sys.exit(1)
 
-def trace_h_begin():
+def trace_h_begin(events):
     print '''#ifndef TRACE_H
 #define TRACE_H
 
@@ -47,17 +47,12 @@ def trace_h_begin():
 
 #include "qemu-common.h"'''
 
-
-def trace_h_end():
+def trace_h_end(events):
     print '#endif /* TRACE_H */'
 
-
-def trace_c_begin():
+def trace_c_begin(events):
     print '/* This file is autogenerated by tracetool, do not edit. */'
 
-def trace_c_end():
-    pass # nop, required for trace_gen
-
 def nop_h(events):
     print
     for event in events:
@@ -284,18 +279,12 @@ probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")
 def dtrace_nop_stp(events):
     pass
 
-def trace_stap_begin():
+def trace_stap_begin(events):
     print '/* This file is autogenerated by tracetool, do not edit. */'
 
-def trace_stap_end():
-    pass #nop, reqd for trace_gen
-
-def trace_d_begin():
+def trace_d_begin(events):
     print '/* This file is autogenerated by tracetool, do not edit. */'
 
-def trace_d_end():
-    pass #nop, reqd for trace_gen
-
 
 # Registry of backends and their converter functions
 converters = {
@@ -331,22 +320,19 @@ converters = {
 }
 
 # Trace file header and footer code generators
-trace_gen = {
+formats = {
     'h': {
         'begin': trace_h_begin,
         'end': trace_h_end,
     },
     'c': {
         'begin': trace_c_begin,
-        'end': trace_c_end,
     },
     'd': {
         'begin': trace_d_begin,
-        'end': trace_d_end,
     },
     'stap': {
         'begin': trace_stap_begin,
-        'end': trace_stap_end,
     },
 }
 
@@ -496,10 +482,12 @@ def main():
 
     events = read_events(sys.stdin)
 
-    trace_gen[output]['begin']()
+    if 'begin' in formats[output]:
+        formats[output]['begin'](events)
     converters[backend][output]([ e for e in events if 'disable' not in e.properties ])
     converters['nop'][output]([ e for e in events if 'disable' in e.properties ])
-    trace_gen[output]['end']()
+    if 'end' in formats[output]:
+        formats[output]['end'](events)
 
 if __name__ == "__main__":
     main()
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 09/14] trace: [tracetool] Automatically establish available backends and formats
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (7 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 08/14] trace: [tracetool] Make format-specific code optional with access to events Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 10/14] trace: Provide a per-event status define for conditional compilation Harsh Prateek Bora
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 Makefile.objs        |    6 +-
 Makefile.target      |    3 +-
 scripts/tracetool.py |  321 ++++++++++++++++++++++++++++++++------------------
 3 files changed, 211 insertions(+), 119 deletions(-)

diff --git a/Makefile.objs b/Makefile.objs
index 984034a..acb51b6 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -344,12 +344,12 @@ else
 trace.h: trace.h-timestamp
 endif
 trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=h --backend=$(TRACE_BACKEND) < $< > $@,"  GEN   trace.h")
 	@cmp -s $@ trace.h || cp $@ trace.h
 
 trace.c: trace.c-timestamp
 trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=c --backend=$(TRACE_BACKEND) < $< > $@,"  GEN   trace.c")
 	@cmp -s $@ trace.c || cp $@ trace.c
 
 trace.o: trace.c $(GENERATED_HEADERS)
@@ -362,7 +362,7 @@ trace-dtrace.h: trace-dtrace.dtrace
 # rule file. So we use '.dtrace' instead
 trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
 trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --backend=$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
+	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py --format=d --backend=$(TRACE_BACKEND) < $< > $@,"  GEN   trace-dtrace.dtrace")
 	@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
 
 trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
diff --git a/Makefile.target b/Makefile.target
index 07b21d1..6706767 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -51,11 +51,12 @@ endif
 
 $(QEMU_PROG).stp:
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/tracetool.py \
+		--format=stap \
 		--backend=$(TRACE_BACKEND) \
 		--binary=$(bindir)/$(QEMU_PROG) \
 		--target-arch=$(TARGET_ARCH) \
 		--target-type=$(TARGET_TYPE) \
-		--stap < $(SRC_PATH)/trace-events > $(QEMU_PROG).stp,"  GEN   $(QEMU_PROG).stp")
+		< $(SRC_PATH)/trace-events > $(QEMU_PROG).stp,"  GEN   $(QEMU_PROG).stp")
 else
 stap:
 endif
diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 2d6f9ee..947b808 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -12,33 +12,107 @@ import sys
 import getopt
 import re
 
-def usage():
-    print "Tracetool: Generate tracing code for trace events file on stdin"
-    print "Usage:"
-    print sys.argv[0], "--backend=[nop|simple|stderr|dtrace|ust] [-h|-c|-d|--stap]"
-    print '''
-Backends:
-  --nop     Tracing disabled
-  --simple  Simple built-in backend
-  --stderr  Stderr built-in backend
-  --dtrace  DTrace/SystemTAP backend
-  --ust     LTTng User Space Tracing backend
-
-Output formats:
-  -h     Generate .h file
-  -c     Generate .c file
-  -d     Generate .d file (DTrace only)
-  --stap Generate .stp file (DTrace with SystemTAP only)
+######################################################################
+# format auto-registration
+
+class _Tag:
+    pass
+
+_formats = {}
+
+BEGIN = _Tag()
+END = _Tag()
+_DESCR = _Tag()
+
+def for_format(format_, when, descr = None):
+    """Decorator for format generator functions."""
+
+    if when is not BEGIN and when is not END:
+        raise ValueError("Invalid 'when' tag")
+    if format_ in _formats and when in _formats[format_]:
+        raise ValueError("Format '%s' already set for given 'when' tag" % format_)
+
+    if format_ not in _formats:
+        _formats[format_] = {}
+    if descr is not None:
+        if _DESCR in _formats[format_]:
+            raise ValueError("Description already set")
+        _formats[format_][_DESCR] = descr
+
+    def func(f):
+        _formats[format_][when] = f
+        return f
+    return func
+
+def get_format(format_, when):
+    """Get a format generator function."""
+
+    def nop(*args, **kwargs):
+        pass
+    if format_ in _formats and when in _formats[format_]:
+        return _formats[format_][when]
+    else:
+        return nop
+
+def get_format_descr(format_):
+    """Get the description of a format generator."""
+
+    if format_ in _formats and _DESCR in _formats[format_]:
+        return _formats[format_][_DESCR]
+    else:
+        return ""
 
-Options:
-  --binary       [path]    Full path to QEMU binary
-  --target-arch  [arch]    QEMU emulator target arch
-  --target-type  [type]    QEMU emulator target type ('system' or 'user')
-  --probe-prefix [prefix]  Prefix for dtrace probe names
-                           (default: qemu-targettype-targetarch)
-'''
-    sys.exit(1)
 
+
+######################################################################
+# backend auto-registration and format compatibility
+
+_backends = {}
+
+def for_backend(backend, format_, descr = None):
+    if backend not in _backends:
+        _backends[backend] = {}
+    if format_ in _backends[backend]:
+        raise ValueError("Backend '%s' already set for backend '%s'" % (backend, format_))
+    if format_ not in _formats:
+        raise ValueError("Unknown format '%s'" % format_)
+
+    if descr is not None:
+        if _DESCR in _backends[backend]:
+            raise ValueError("Description already set")
+        _backends[backend][_DESCR] = descr
+
+    def func(f):
+        _backends[backend][format_] = f
+        return f
+    return func
+
+def get_backend(format_, backend):
+    if backend not in _backends:
+        raise ValueError("Unknown backend '%s'" % backend)
+    if format_ not in _formats:
+        raise ValueError("Unknown format '%s'" % format_)
+    if format_ not in _backends[backend]:
+        raise ValueError("Format '%s' not supported with backend '%s'" % (format_, backend))
+    return _backends[backend][format_]
+
+def get_backend_descr(backend):
+    """Get the description of a backend."""
+
+    if backend in _backends and _DESCR in _backends[backend]:
+        return _backends[backend][_DESCR]
+    else:
+        return ""
+
+
+
+######################################################################
+# formats
+
+##################################################
+# format: h
+
+@for_format("h", BEGIN, "Generate .h file")
 def trace_h_begin(events):
     print '''#ifndef TRACE_H
 #define TRACE_H
@@ -47,12 +121,27 @@ def trace_h_begin(events):
 
 #include "qemu-common.h"'''
 
+@for_format("h", END)
 def trace_h_end(events):
     print '#endif /* TRACE_H */'
 
+
+##################################################
+# format: c
+
+@for_format("c", BEGIN, "Generate .c file")
 def trace_c_begin(events):
     print '/* This file is autogenerated by tracetool, do not edit. */'
 
+
+
+######################################################################
+# backends
+
+##################################################
+# backend: nop
+
+@for_backend("nop", "h", "Tracing disabled")
 def nop_h(events):
     print
     for event in events:
@@ -63,11 +152,15 @@ def nop_h(events):
     'name': event.name,
     'args': event.args
 }
-    return
 
+@for_backend("nop", "c")
 def nop_c(events):
     pass # nop, reqd for converters
 
+##################################################
+# backend: simple
+
+@for_backend("simple", "h", "Simple built-in backend")
 def simple_h(events):
     print '#include "trace/simple.h"'
     print
@@ -95,6 +188,7 @@ def simple_h(events):
     print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];'
 
 
+@for_backend("simple", "c")
 def simple_c(events):
     print '#include "trace.h"'
     print
@@ -108,6 +202,10 @@ def simple_c(events):
         print
     print '};'
 
+##################################################
+# backend: stderr
+
+@for_backend("stderr", "h", "Stderr built-in backend")
 def stderr_h(events):
     print '''#include <stdio.h>
 #include "trace/stderr.h"
@@ -133,6 +231,7 @@ static inline void trace_%(name)s(%(args)s)
     print
     print '#define NR_TRACE_EVENTS %d' % len(events)
 
+@for_backend("stderr", "c")
 def stderr_c(events):
     print '''#include "trace.h"
 
@@ -145,6 +244,11 @@ TraceEvent trace_list[] = {
         print
     print '};'
 
+
+##################################################
+# backend: ust
+
+@for_backend("ust", "h", "LTTng User Space Tracing backend")
 def ust_h(events):
     print '''#include <ust/tracepoint.h>
 #undef mutex_lock
@@ -169,6 +273,7 @@ _DECLARE_TRACEPOINT_NOARGS(ust_%(name)s);
 }
     print
 
+@for_backend("ust", "c")
 def ust_c(events):
     print '''#include <ust/marker.h>
 #undef mutex_lock
@@ -214,6 +319,10 @@ static void __attribute__((constructor)) trace_init(void)
 }
     print '}'
 
+##################################################
+# backend: dtrace
+
+@for_backend("dtrace", "h", "DTrace/SystemTAP backend")
 def dtrace_h(events):
     print '#include "trace-dtrace.h"'
     print
@@ -230,9 +339,15 @@ def dtrace_h(events):
     'argnames': ", ".join(event.args.names()),
 }
 
+@for_backend("dtrace", "c")
 def dtrace_c(events):
     pass # No need for function definitions in dtrace backend
 
+@for_format("d", BEGIN, "Generate .d file (DTrace probes)")
+def trace_d_begin(events):
+    print '/* This file is autogenerated by tracetool, do not edit. */'
+
+@for_backend("dtrace", "d")
 def dtrace_d(events):
     print 'provider qemu {'
     for event in events:
@@ -252,9 +367,15 @@ def dtrace_d(events):
     print
     print '};'
 
+@for_backend("nop", "d")
 def dtrace_nop_d(events):
     pass
 
+
+@for_format("stap", BEGIN, "Generate .stp file (SystemTAP tapsets)")
+def trace_stap_begin(events):
+    print '/* This file is autogenerated by tracetool, do not edit. */'
+
 def dtrace_stp(events):
     for event in events:
         # Define prototype for probe arguments
@@ -279,64 +400,9 @@ probe %(probeprefix)s.%(name)s = process("%(binary)s").mark("%(name)s")
 def dtrace_nop_stp(events):
     pass
 
-def trace_stap_begin(events):
-    print '/* This file is autogenerated by tracetool, do not edit. */'
-
-def trace_d_begin(events):
-    print '/* This file is autogenerated by tracetool, do not edit. */'
-
-
-# Registry of backends and their converter functions
-converters = {
-    'simple': {
-        'h': simple_h,
-        'c': simple_c,
-    },
-
-    'nop': {
-        'h': nop_h,
-        'c': nop_c,
-        'd': dtrace_nop_d,
-        'stap': dtrace_nop_stp,
-    },
-
-    'stderr': {
-        'h': stderr_h,
-        'c': stderr_c,
-    },
-
-    'dtrace': {
-        'h': dtrace_h,
-        'c': dtrace_c,
-        'd': dtrace_d,
-        'stap': dtrace_stp
-    },
-
-    'ust': {
-        'h': ust_h,
-        'c': ust_c,
-    },
-
-}
-
-# Trace file header and footer code generators
-formats = {
-    'h': {
-        'begin': trace_h_begin,
-        'end': trace_h_end,
-    },
-    'c': {
-        'begin': trace_c_begin,
-    },
-    'd': {
-        'begin': trace_d_begin,
-    },
-    'stap': {
-        'begin': trace_stap_begin,
-    },
-}
-
+######################################################################
 # Event arguments
+
 def type_is_string(type_):
     strtype = ('const char*', 'char*', 'const char *', 'char *')
     return type_.lstrip().startswith(strtype)
@@ -377,7 +443,10 @@ class Arguments:
         res = ""
         return res
 
+
+######################################################################
 # A trace event
+
 cre = re.compile("((?P<props>.*)\s+)?(?P<name>[^(\s]+)\((?P<args>[^)]*)\)\s*(?P<fmt>\".*)?")
 
 VALID_PROPS = set(["disable"])
@@ -407,32 +476,51 @@ def read_events(fobj):
         res.append(Event(line))
     return res
 
+######################################################################
+# Main
+
+format_ = ""
 binary = ""
 probeprefix = ""
 
+def usage():
+    print "Tracetool: Generate tracing code for trace events file on stdin"
+    print "Usage:"
+    print sys.argv[0], " --format=<format> --backend=<backend>"
+    print
+    print "Output formats:"
+    for f in _formats:
+        print "   %-10s %s" % (f, get_format_descr(f))
+    print
+    print "Backends:"
+    for b in _backends:
+        print "   %-10s %s" % (b, get_backend_descr(b))
+    print """
+Options:
+  --binary       [path]    Full path to QEMU binary
+  --target-arch  [arch]    QEMU emulator target arch
+  --target-type  [type]    QEMU emulator target type ('system' or 'user')
+  --probe-prefix [prefix]  Prefix for dtrace probe names
+                           (default: qemu-targettype-targetarch)
+"""
+
+    sys.exit(1)
+
 def main():
-    global binary, probeprefix
+    global format_, binary, probeprefix
     targettype = ""
     targetarch = ""
-    supported_backends = ["simple", "nop", "stderr", "dtrace", "ust"]
-    short_options = "hcd"
-    long_options = ["stap", "backend=", "binary=", "target-arch=", "target-type=", "probe-prefix=", "list-backends", "check-backend"]
+    long_options = ["format=", "backend=", "binary=", "target-arch=", "target-type=", "probe-prefix=", "list-backends", "check-backend"]
     try:
-        opts, args = getopt.getopt(sys.argv[1:], short_options, long_options)
+        opts, args = getopt.getopt(sys.argv[1:], "", long_options)
     except getopt.GetoptError, err:
         # print help information and exit:
         print str(err) # will print something like "option -a not recognized"
         usage()
         sys.exit(2)
     for opt, arg in opts:
-        if opt == '-h':
-            output = 'h'
-        elif opt == '-c':
-            output = 'c'
-        elif opt == '-d':
-            output = 'd'
-        elif opt == '--stap':
-            output = 'stap'
+        if opt == '--format':
+            format_ = arg
         elif opt == '--backend':
             backend = arg
         elif opt == '--binary':
@@ -444,30 +532,27 @@ def main():
         elif opt == '--probe-prefix':
             probeprefix = arg
         elif opt == '--list-backends':
-            print 'simple, nop, stderr, dtrace, ust'
+            print ', '.join(_backends)
             sys.exit(0)
         elif opt == "--check-backend":
-            if any(backend in s for s in supported_backends):
+            if backend in _backends:
                 sys.exit(0)
             else:
                 sys.exit(1)
         else:
-            #assert False, "unhandled option"
             print "unhandled option: ", opt
             usage()
 
-    if backend == "" or output == "":
+    if format_ not in _formats:
+        print "Unknown format: %s" % format_
+        print
+        usage()
+    if backend not in _backends:
+        print "Unknown backend: %s" % backend
+        print
         usage()
-        sys.exit(0)
-
-    if backend != 'dtrace' and output == 'd':
-        print 'DTrace probe generator not applicable to %s backend' % backend
-        sys.exit(1)
 
-    if output == 'stap':
-        if backend != "dtrace":
-            print 'SystemTAP tapset generator not applicable to %s backend' % backend
-            sys.exit(1)
+    if format_ == 'stap':
         if binary == "":
             print '--binary is required for SystemTAP tapset generator'
             sys.exit(1)
@@ -482,12 +567,18 @@ def main():
 
     events = read_events(sys.stdin)
 
-    if 'begin' in formats[output]:
-        formats[output]['begin'](events)
-    converters[backend][output]([ e for e in events if 'disable' not in e.properties ])
-    converters['nop'][output]([ e for e in events if 'disable' in e.properties ])
-    if 'end' in formats[output]:
-        formats[output]['end'](events)
+    try:
+        # just force format/backend compatibility check
+        bfun = get_backend(format_, backend)
+        bnop = get_backend(format_, "nop")
+    except Exception as e:
+        sys.stderr.write(str(e) + "\n\n")
+        usage()
+
+    get_format(format_, BEGIN)(events)
+    bfun([ e for e in events if "disable" not in e.properties ])
+    bnop([ e for e in events if "disable" in e.properties ])
+    get_format(format_, END)(events)
 
 if __name__ == "__main__":
     main()
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 10/14] trace: Provide a per-event status define for conditional compilation
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (8 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 09/14] trace: [tracetool] Automatically establish available backends and formats Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 11/14] trace: [tracetool] Add error-reporting functions Harsh Prateek Bora
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

NOTE: This is a port of a patch in Stefanha's tracing tree to the new
pythonic tracetool version.

Adds a 'TRACE_${NAME}_ENABLED' preprocessor define for each tracing event
in "trace.h".

This lets the user conditionally compile code with a relatively high
execution cost that is only necessary when producing the tracing
information for an event that is enabled.

Note that events using this define will probably have the "disable"
property by default, in order to avoid such costs on regular builds.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 docs/tracing.txt     |   50 ++++++++++++++++++++++++++++++++++++++++++--------
 scripts/tracetool.py |    7 +++++++
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 95ca16c..ab9048c 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -39,12 +39,12 @@ generate code for the trace events.  Trace events are invoked directly from
 source code like this:
 
     #include "trace.h"  /* needed for trace event prototype */
-    
+
     void *qemu_vmalloc(size_t size)
     {
         void *ptr;
         size_t align = QEMU_VMALLOC_ALIGN;
-     
+
         if (size < align) {
             align = getpagesize();
         }
@@ -98,12 +98,6 @@ respectively.  This ensures portability between 32- and 64-bit platforms.
 4. Name trace events after their function.  If there are multiple trace events
    in one function, append a unique distinguisher at the end of the name.
 
-5. If specific trace events are going to be called a huge number of times, this
-   might have a noticeable performance impact even when the trace events are
-   programmatically disabled. In this case you should declare the trace event
-   with the "disable" property, which will effectively disable it at compile
-   time (using the "nop" backend).
-
 == Generic interface and monitor commands ==
 
 You can programmatically query and control the dynamic state of trace events
@@ -227,3 +221,43 @@ probes:
                       --target-type system \
                       --target-arch x86_64 \
                       <trace-events >qemu.stp
+
+== Trace event properties ==
+
+Each event in the "trace-events" file can be prefixed with a space-separated
+list of zero or more of the following event properties.
+
+=== "disable" ===
+
+If a specific trace event is going to be invoked a huge number of times, this
+might have a noticeable performance impact even when the event is
+programmatically disabled.
+
+In this case you should declare such event with the "disable" property. This
+will effectively disable the event at compile time (by using the "nop" backend),
+thus having no performance impact at all on regular builds (i.e., unless you
+edit the "trace-events" file).
+
+In addition, there might be cases where relatively complex computations must be
+performed to generate values that are only used as arguments for a trace
+function. In these cases you can use the macro 'TRACE_${EVENT_NAME}_ENABLED' to
+guard such computations and avoid its compilation when the event is disabled:
+
+    #include "trace.h"  /* needed for trace event prototype */
+
+    void *qemu_vmalloc(size_t size)
+    {
+        void *ptr;
+        size_t align = QEMU_VMALLOC_ALIGN;
+
+        if (size < align) {
+            align = getpagesize();
+        }
+        ptr = qemu_memalign(align, size);
+        if (TRACE_QEMU_VMALLOC_ENABLED) { /* preprocessor macro */
+            void *complex;
+            /* some complex computations to produce the 'complex' value */
+            trace_qemu_vmalloc(size, ptr, complex);
+        }
+        return ptr;
+    }
diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 947b808..dc93a1a 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -123,6 +123,13 @@ def trace_h_begin(events):
 
 @for_format("h", END)
 def trace_h_end(events):
+    for e in events:
+        if 'disable' in e.properties:
+            enabled = 0
+        else:
+            enabled = 1
+        print "#define TRACE_%s_ENABLED %d" % (e.name.upper(), enabled)
+    print
     print '#endif /* TRACE_H */'
 
 
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 11/14] trace: [tracetool] Add error-reporting functions
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (9 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 10/14] trace: Provide a per-event status define for conditional compilation Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 12/14] monitor: remove unused do_info_trace Harsh Prateek Bora
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

From: Lluís Vilanova <vilanova@ac.upc.edu>

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   27 +++++++++++++++------------
 1 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index dc93a1a..6cbbdd7 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -63,6 +63,13 @@ def get_format_descr(format_):
         return ""
 
 
+def error_write(*lines):
+    sys.stderr.writelines(lines)
+
+def error(*lines):
+    error_write(*lines)
+    sys.exit(1)
+
 
 ######################################################################
 # backend auto-registration and format compatibility
@@ -521,8 +528,9 @@ def main():
     try:
         opts, args = getopt.getopt(sys.argv[1:], "", long_options)
     except getopt.GetoptError, err:
-        # print help information and exit:
-        print str(err) # will print something like "option -a not recognized"
+        # print help information and exit
+        # will print something like "option -a not recognized"
+        error_write(str(err)+"\n")
         usage()
         sys.exit(2)
     for opt, arg in opts:
@@ -551,24 +559,19 @@ def main():
             usage()
 
     if format_ not in _formats:
-        print "Unknown format: %s" % format_
-        print
+        error_write("Unknown format: %s\n\n" % format_)
         usage()
     if backend not in _backends:
-        print "Unknown backend: %s" % backend
-        print
+        error_write("Unknown backend: %s\n\n" % backend)
         usage()
 
     if format_ == 'stap':
         if binary == "":
-            print '--binary is required for SystemTAP tapset generator'
-            sys.exit(1)
+            error("--binary is required for SystemTAP tapset generator\n")
         if not probeprefix and  not targettype:
-            print '--target-type is required for SystemTAP tapset generator'
-            sys.exit(1)
+            error("--target-type is required for SystemTAP tapset generator\n")
         if not probeprefix and  not targetarch:
-            print '--target-arch is required for SystemTAP tapset generator'
-            sys.exit(1)
+            error("--target-arch is required for SystemTAP tapset generator\n")
         if probeprefix == "":
             probeprefix = 'qemu.' + targettype + '.' + targetarch
 
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 12/14] monitor: remove unused do_info_trace
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (10 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 11/14] trace: [tracetool] Add error-reporting functions Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 13/14] Simpletrace v2: Handle var num of args, strings Harsh Prateek Bora
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

Going forward with simpletrace v2 variable size trace records, we cannot
have a generic function to print trace event info and therefore this
interface becomes invalid.

As per Stefan Hajnoczi:

"This command is only available from the human monitor.  It's not very
useful because it historically hasn't been able to pretty-print events
or show them in the right order (we use a ringbuffer but it prints
them out from index 0).

Therefore, I don't think we're under any obligation to keep this
command around.  No one has complained about it's limitations - I
think this is a sign that no one has used it.  I'd be okay with a
patch that removes it."

Ref: http://lists.gnu.org/archive/html/qemu-devel/2012-01/msg01268.html

Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 monitor.c |   16 ----------------
 1 files changed, 0 insertions(+), 16 deletions(-)

diff --git a/monitor.c b/monitor.c
index ffda0fe..365ce47 100644
--- a/monitor.c
+++ b/monitor.c
@@ -942,13 +942,6 @@ static void do_info_cpu_stats(Monitor *mon)
 }
 #endif
 
-#if defined(CONFIG_TRACE_SIMPLE)
-static void do_info_trace(Monitor *mon)
-{
-    st_print_trace((FILE *)mon, &monitor_fprintf);
-}
-#endif
-
 static void do_trace_print_events(Monitor *mon)
 {
     trace_print_events((FILE *)mon, &monitor_fprintf);
@@ -3033,15 +3026,6 @@ static const mon_cmd_t info_cmds[] = {
         .help       = "show roms",
         .mhandler.info = do_info_roms,
     },
-#if defined(CONFIG_TRACE_SIMPLE)
-    {
-        .name       = "trace",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show current contents of trace buffer",
-        .mhandler.info = do_info_trace,
-    },
-#endif
     {
         .name       = "trace-events",
         .args_type  = "",
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 13/14] Simpletrace v2: Handle var num of args, strings.
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (11 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 12/14] monitor: remove unused do_info_trace Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 14/14] simpletrace.py: Support for simpletrace v2 log format Harsh Prateek Bora
  2012-02-28 20:23 ` [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Lluís Vilanova
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

Advantages over existing simpletrace backend:
- More than 6 elements (vitually unlimited) arguments can be traced.
- This allows to trace strings (variable size element) as well.

Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/tracetool.py |   82 ++++++++++++++-----
 trace/simple.c       |  226 ++++++++++++++++++++++++++++----------------------
 trace/simple.h       |   38 +++++++--
 3 files changed, 218 insertions(+), 128 deletions(-)

diff --git a/scripts/tracetool.py b/scripts/tracetool.py
index 6cbbdd7..1073818 100755
--- a/scripts/tracetool.py
+++ b/scripts/tracetool.py
@@ -178,43 +178,83 @@ def nop_c(events):
 def simple_h(events):
     print '#include "trace/simple.h"'
     print
-
-    for num, event in enumerate(events):
-        if len(event.args):
-            argstr = event.args.names()
-            arg_prefix = ', (uint64_t)(uintptr_t)'
-            cast_args = arg_prefix + arg_prefix.join(argstr)
-            simple_args = (str(num) + cast_args)
-        else:
-            simple_args = str(num)
-
-        print '''static inline void trace_%(name)s(%(args)s)
-{
-    trace%(argc)d(%(trace_args)s);
-}''' % {
+    for event in events:
+        print 'void trace_%(name)s(%(args)s);' % {
     'name': event.name,
-    'args': event.args,
-    'argc': len(event.args),
-    'trace_args': simple_args
+    'args': event.args
 }
-        print
+    print
     print '#define NR_TRACE_EVENTS %d' % len(events)
     print 'extern TraceEvent trace_list[NR_TRACE_EVENTS];'
 
-
 @for_backend("simple", "c")
 def simple_c(events):
     print '#include "trace.h"'
+    print '#include "trace/simple.h"'
     print
     print 'TraceEvent trace_list[] = {'
     print
-
     for event in events:
         print '{.tp_name = "%(name)s", .state=0},' % {
-    'name': event.name,
+    'name': event.name
 }
         print
     print '};'
+    print
+
+    for num, event in enumerate(events):
+        sizes = []
+        for type_, name in event.args:
+            if type_is_string(type_):
+                sizes.append("4 + strlen(%s)" % name)
+            else:
+                sizes.append("8")
+        sizestr = " + ".join(sizes)
+        if len(event.args) == 0:
+            sizestr = '0'
+
+        print '''void trace_%(name)s(%(args)s)
+{
+    TraceBufferRecord rec;
+
+    if (!trace_list[%(event_id)s].state) {
+        return;
+    }
+
+    if (trace_record_start(&rec, %(event_id)s, %(sizestr)s)) {
+        return; /* Trace Buffer Full, Event Dropped ! */
+    }
+''' % {
+    'name': event.name,
+    'args': event.args,
+    'event_id': num,
+    'sizestr': sizestr,
+}
+        if len(event.args) > 0:
+            for type_, name in event.args:
+                # string
+                if type_is_string(type_):
+                    print '''
+    trace_record_write_str(&rec, %(name)s);''' % {
+    'name': name
+}
+                # pointer var (not string)
+                elif type_.endswith('*'):
+                    print '''
+    trace_record_write_u64(&rec, (uint64_t)(uint64_t *)%(name)s);''' % {
+    'name': name
+}
+                # primitive data type
+                else:
+                    print '''
+    trace_record_write_u64(&rec, (uint64_t)%(name)s);''' % {
+    'name': name
+}
+
+        print '''
+    trace_record_finish(&rec);
+}
+'''
 
 ##################################################
 # backend: stderr
diff --git a/trace/simple.c b/trace/simple.c
index b639dda..de5c3d3 100644
--- a/trace/simple.c
+++ b/trace/simple.c
@@ -27,7 +27,7 @@
 #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
 
 /** Trace file version number, bump if format changes */
-#define HEADER_VERSION 0
+#define HEADER_VERSION 2
 
 /** Records were dropped event ID */
 #define DROPPED_EVENT_ID (~(uint64_t)0 - 1)
@@ -35,23 +35,6 @@
 /** Trace record is valid */
 #define TRACE_RECORD_VALID ((uint64_t)1 << 63)
 
-/** Trace buffer entry */
-typedef struct {
-    uint64_t event;
-    uint64_t timestamp_ns;
-    uint64_t x1;
-    uint64_t x2;
-    uint64_t x3;
-    uint64_t x4;
-    uint64_t x5;
-    uint64_t x6;
-} TraceRecord;
-
-enum {
-    TRACE_BUF_LEN = 4096,
-    TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4,
-};
-
 /*
  * Trace records are written out by a dedicated thread.  The thread waits for
  * records to become available, writes them out, and then waits again.
@@ -62,11 +45,35 @@ static GCond *trace_empty_cond;
 static bool trace_available;
 static bool trace_writeout_enabled;
 
-static TraceRecord trace_buf[TRACE_BUF_LEN];
+enum {
+    TRACE_BUF_LEN = 4096 * 64,
+    TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4,
+};
+
+uint8_t trace_buf[TRACE_BUF_LEN];
 static unsigned int trace_idx;
+static unsigned int writeout_idx;
+static uint64_t dropped_events;
 static FILE *trace_fp;
 static char *trace_file_name = NULL;
 
+/* * Trace buffer entry */
+typedef struct {
+    uint64_t event; /*   TraceEventID */
+    uint64_t timestamp_ns;
+    uint32_t length;   /*    in bytes */
+    uint32_t reserved; /*    unused */
+    uint8_t arguments[]; /*  arguments position affects ST_REC_HDR_LEN */
+} TraceRecord;
+
+/* * Trace record header length */
+#define ST_REC_HDR_LEN 24
+
+int trace_alloc_record(TraceBufferRecord *rec, TraceEventID event, uint32_t datasize);
+static void read_from_buffer(unsigned int idx, uint8_t *dataptr, uint32_t size);
+static void write_to_buffer(unsigned int idx, uint8_t *dataptr, uint32_t size);
+void trace_mark_record_complete(TraceBufferRecord *rec);
+
 /**
  * Read a trace record from the trace buffer
  *
@@ -75,16 +82,22 @@ static char *trace_file_name = NULL;
  *
  * Returns false if the record is not valid.
  */
-static bool get_trace_record(unsigned int idx, TraceRecord *record)
+static bool get_trace_record(unsigned int idx, TraceRecord **recordptr)
 {
-    if (!(trace_buf[idx].event & TRACE_RECORD_VALID)) {
+    uint8_t temp_rec[ST_REC_HDR_LEN];
+    TraceRecord *record = (TraceRecord *) temp_rec;
+    read_from_buffer(idx, temp_rec, ST_REC_HDR_LEN);
+
+    if (!(record->event & TRACE_RECORD_VALID)) {
         return false;
     }
 
     __sync_synchronize(); /* read memory barrier before accessing record */
 
-    *record = trace_buf[idx];
-    record->event &= ~TRACE_RECORD_VALID;
+    *recordptr = g_malloc(record->length);
+    /* make a copy of record to avoid being overwritten */
+    read_from_buffer(idx, (uint8_t *)*recordptr, record->length);
+    (*recordptr)->event &= ~TRACE_RECORD_VALID;
     return true;
 }
 
@@ -120,29 +133,31 @@ static void wait_for_trace_records_available(void)
 
 static gpointer writeout_thread(gpointer opaque)
 {
-    TraceRecord record;
-    unsigned int writeout_idx = 0;
-    unsigned int num_available, idx;
+    TraceRecord *recordptr;
+    unsigned int idx = 0;
     size_t unused __attribute__ ((unused));
 
     for (;;) {
         wait_for_trace_records_available();
 
-        num_available = trace_idx - writeout_idx;
-        if (num_available > TRACE_BUF_LEN) {
-            record = (TraceRecord){
-                .event = DROPPED_EVENT_ID,
-                .x1 = num_available,
-            };
-            unused = fwrite(&record, sizeof(record), 1, trace_fp);
-            writeout_idx += num_available;
+        if (dropped_events) {
+            recordptr = g_malloc(ST_REC_HDR_LEN + sizeof(dropped_events));
+            recordptr->event = DROPPED_EVENT_ID,
+            recordptr->timestamp_ns = get_clock();
+            recordptr->length = ST_REC_HDR_LEN + sizeof(dropped_events),
+            recordptr->reserved = 0;
+            *(uint64_t *) &(recordptr->arguments[0]) = dropped_events;
+            dropped_events = 0;
+            unused = fwrite(recordptr, recordptr->length, 1, trace_fp);
         }
 
-        idx = writeout_idx % TRACE_BUF_LEN;
-        while (get_trace_record(idx, &record)) {
-            trace_buf[idx].event = 0; /* clear valid bit */
-            unused = fwrite(&record, sizeof(record), 1, trace_fp);
-            idx = ++writeout_idx % TRACE_BUF_LEN;
+        while (get_trace_record(idx, &recordptr)) {
+            unused = fwrite(recordptr, recordptr->length, 1, trace_fp);
+            writeout_idx += recordptr->length;
+            g_free(recordptr);
+            recordptr = (TraceRecord *) &trace_buf[idx];
+            recordptr->event = 0;
+            idx = writeout_idx % TRACE_BUF_LEN;
         }
 
         fflush(trace_fp);
@@ -150,72 +165,101 @@ static gpointer writeout_thread(gpointer opaque)
     return NULL;
 }
 
-static void trace(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3,
-                  uint64_t x4, uint64_t x5, uint64_t x6)
+int trace_record_start(TraceBufferRecord *rec, TraceEventID id, size_t arglen)
 {
-    unsigned int idx;
-    uint64_t timestamp;
-
-    if (!trace_list[event].state) {
-        return;
-    }
-
-    timestamp = get_clock();
-
-    idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, 1) % TRACE_BUF_LEN;
-    trace_buf[idx] = (TraceRecord){
-        .event = event,
-        .timestamp_ns = timestamp,
-        .x1 = x1,
-        .x2 = x2,
-        .x3 = x3,
-        .x4 = x4,
-        .x5 = x5,
-        .x6 = x6,
-    };
-    __sync_synchronize(); /* write barrier before marking as valid */
-    trace_buf[idx].event |= TRACE_RECORD_VALID;
-
-    if ((idx + 1) % TRACE_BUF_FLUSH_THRESHOLD == 0) {
-        flush_trace_file(false);
-    }
+    return trace_alloc_record(rec, id, arglen); /* return 0 on success */
 }
 
-void trace0(TraceEventID event)
+void trace_record_write_u64(TraceBufferRecord *rec, uint64_t val)
 {
-    trace(event, 0, 0, 0, 0, 0, 0);
+    write_to_buffer(rec->rec_off, (uint8_t *)&val, sizeof(uint64_t));
+    rec->rec_off += sizeof(uint64_t);
 }
 
-void trace1(TraceEventID event, uint64_t x1)
+void trace_record_write_str(TraceBufferRecord *rec, const char *s)
 {
-    trace(event, x1, 0, 0, 0, 0, 0);
+    /* Write string length first */
+    uint32_t slen = strlen(s);
+    write_to_buffer(rec->rec_off, (uint8_t *)&slen, sizeof(slen));
+    rec->rec_off += sizeof(slen);
+    /* Write actual string now */
+    write_to_buffer(rec->rec_off, (uint8_t *)s, slen);
+    rec->rec_off += slen;
 }
 
-void trace2(TraceEventID event, uint64_t x1, uint64_t x2)
+void trace_record_finish(TraceBufferRecord *rec)
 {
-    trace(event, x1, x2, 0, 0, 0, 0);
+    trace_mark_record_complete(rec);
 }
 
-void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3)
+int trace_alloc_record(TraceBufferRecord *rec, TraceEventID event, uint32_t datasize)
 {
-    trace(event, x1, x2, x3, 0, 0, 0);
+    unsigned int idx, rec_off;
+    uint32_t rec_len = ST_REC_HDR_LEN + datasize;
+    uint64_t timestamp_ns = get_clock();
+
+    if ((rec_len + trace_idx - writeout_idx) > TRACE_BUF_LEN) {
+        /* Trace Buffer Full, Event dropped ! */
+        dropped_events++;
+        return 1;
+    }
+    idx = g_atomic_int_exchange_and_add((gint *)&trace_idx, rec_len) % TRACE_BUF_LEN;
+
+    /*  To check later if threshold crossed */
+    rec->next_tbuf_idx = trace_idx % TRACE_BUF_LEN;
+
+    rec_off = idx;
+    write_to_buffer(rec_off, (uint8_t*)&event, sizeof(event));
+    rec_off += sizeof(event);
+    write_to_buffer(rec_off, (uint8_t*)&timestamp_ns, sizeof(timestamp_ns));
+    rec_off += sizeof(timestamp_ns);
+    write_to_buffer(rec_off, (uint8_t*)&rec_len, sizeof(rec_len));
+    rec_off += sizeof(rec_len);
+
+    rec->tbuf_idx = idx;
+    rec->rec_off  = (idx + ST_REC_HDR_LEN) % TRACE_BUF_LEN;
+    return 0;
 }
 
-void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4)
+static void read_from_buffer(unsigned int idx, uint8_t *dataptr, uint32_t size)
 {
-    trace(event, x1, x2, x3, x4, 0, 0);
+    uint32_t x = 0;
+    while (x < size) {
+        if (idx >= TRACE_BUF_LEN) {
+            idx = idx % TRACE_BUF_LEN;
+        }
+        dataptr[x++] = trace_buf[idx++];
+    }
 }
 
-void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5)
+static void write_to_buffer(unsigned int idx, uint8_t *dataptr, uint32_t size)
 {
-    trace(event, x1, x2, x3, x4, x5, 0);
+    uint32_t x = 0;
+    while (x < size) {
+        if (idx >= TRACE_BUF_LEN) {
+            idx = idx % TRACE_BUF_LEN;
+        }
+        trace_buf[idx++] = dataptr[x++];
+    }
 }
 
-void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6)
+void trace_mark_record_complete(TraceBufferRecord *rec)
 {
-    trace(event, x1, x2, x3, x4, x5, x6);
+    uint8_t temp_rec[ST_REC_HDR_LEN];
+    TraceRecord *record = (TraceRecord *) temp_rec;
+    read_from_buffer(rec->tbuf_idx, temp_rec, ST_REC_HDR_LEN);
+    __sync_synchronize(); /* write barrier before marking as valid */
+    record->event |= TRACE_RECORD_VALID;
+    write_to_buffer(rec->tbuf_idx, temp_rec, ST_REC_HDR_LEN);
+
+    if (rec->next_tbuf_idx > TRACE_BUF_FLUSH_THRESHOLD &&
+        rec->tbuf_idx <= TRACE_BUF_FLUSH_THRESHOLD) {
+        flush_trace_file(false);
+    }
 }
 
+
+
 void st_set_trace_file_enabled(bool enable)
 {
     if (enable == !!trace_fp) {
@@ -231,7 +275,8 @@ void st_set_trace_file_enabled(bool enable)
         static const TraceRecord header = {
             .event = HEADER_EVENT_ID,
             .timestamp_ns = HEADER_MAGIC,
-            .x1 = HEADER_VERSION,
+            /* Older log readers will check for version at next location */
+            .length = HEADER_VERSION,
         };
 
         trace_fp = fopen(trace_file_name, "wb");
@@ -288,23 +333,6 @@ void st_print_trace_file_status(FILE *stream, int (*stream_printf)(FILE *stream,
                   trace_file_name, trace_fp ? "on" : "off");
 }
 
-void st_print_trace(FILE *stream, int (*stream_printf)(FILE *stream, const char *fmt, ...))
-{
-    unsigned int i;
-
-    for (i = 0; i < TRACE_BUF_LEN; i++) {
-        TraceRecord record;
-
-        if (!get_trace_record(i, &record)) {
-            continue;
-        }
-        stream_printf(stream, "Event %" PRIu64 " : %" PRIx64 " %" PRIx64
-                      " %" PRIx64 " %" PRIx64 " %" PRIx64 " %" PRIx64 "\n",
-                      record.event, record.x1, record.x2,
-                      record.x3, record.x4, record.x5,
-                      record.x6);
-    }
-}
 
 void st_flush_trace_buffer(void)
 {
diff --git a/trace/simple.h b/trace/simple.h
index 466e75b..6755e99 100644
--- a/trace/simple.h
+++ b/trace/simple.h
@@ -22,17 +22,39 @@ typedef struct {
     bool state;
 } TraceEvent;
 
-void trace0(TraceEventID event);
-void trace1(TraceEventID event, uint64_t x1);
-void trace2(TraceEventID event, uint64_t x1, uint64_t x2);
-void trace3(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3);
-void trace4(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4);
-void trace5(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5);
-void trace6(TraceEventID event, uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6);
-void st_print_trace(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);
 bool st_set_trace_file(const char *file);
 void st_flush_trace_buffer(void);
 
+typedef struct {
+    unsigned int tbuf_idx;
+    unsigned int next_tbuf_idx;
+    unsigned int rec_off;
+} TraceBufferRecord;
+
+/**
+ * Initialize a trace record and claim space for it in the buffer
+ *
+ * @arglen  number of bytes required for arguments
+ */
+int trace_record_start(TraceBufferRecord *rec, TraceEventID id, size_t arglen);
+
+/**
+ * Append a 64-bit argument to a trace record
+ */
+void trace_record_write_u64(TraceBufferRecord *rec, uint64_t val);
+
+/**
+ * Append a string argument to a trace record
+ */
+void trace_record_write_str(TraceBufferRecord *rec, const char *s);
+
+/**
+ * Mark a trace record completed
+ *
+ * Don't append any more arguments to the trace record after calling this.
+ */
+void trace_record_finish(TraceBufferRecord *rec);
+
 #endif /* TRACE_SIMPLE_H */
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [Qemu-devel] [RFC PATCH v4 14/14] simpletrace.py: Support for simpletrace v2 log format
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (12 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 13/14] Simpletrace v2: Handle var num of args, strings Harsh Prateek Bora
@ 2012-02-15 15:46 ` Harsh Prateek Bora
  2012-02-28 20:23 ` [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Lluís Vilanova
  14 siblings, 0 replies; 19+ messages in thread
From: Harsh Prateek Bora @ 2012-02-15 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanha, vilanova, aneesh.kumar

Note: This patch is NOT FOR UPSTREAM, still under development.
Use it for developer testing of the new v2 log format only.

Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
---
 scripts/simpletrace.py |  112 +++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 101 insertions(+), 11 deletions(-)

diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
index f55e5e6..3f66438 100755
--- a/scripts/simpletrace.py
+++ b/scripts/simpletrace.py
@@ -12,16 +12,37 @@
 import struct
 import re
 import inspect
+import sys
+from tracetool import *
 
 header_event_id = 0xffffffffffffffff
 header_magic    = 0xf2b177cb0aa429b4
 header_version  = 0
+log_header_ver  = 2
 dropped_event_id = 0xfffffffffffffffe
 
 trace_fmt = '=QQQQQQQQ'
+header_fmt = '=QQII'
+header_len = struct.calcsize(header_fmt)
 trace_len = struct.calcsize(trace_fmt)
 event_re  = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*')
 
+def get_event_argtypes(fobj):
+    """Parse a trace-events file into {event_num: (name, type arg, ...)}."""
+
+    events = {dropped_event_id: ('name', 'args')}
+    event_num = 0
+    for line in fobj:
+        m = event_re.match(line.strip())
+        if m is None:
+            continue
+
+        disable, name, args = m.groups()
+        events[event_num] = tuple(args.split(','))
+        event_num += 1
+    return events
+
+
 def parse_events(fobj):
     """Parse a trace-events file into {event_num: (name, arg1, ...)}."""
 
@@ -48,15 +69,16 @@ def read_record(fobj):
         return None
     return struct.unpack(trace_fmt, s)
 
+def read_header(fobj):
+    '''Read a trace record header'''
+    s = fobj.read(header_len)
+    if len(s) != header_len:
+        return None
+    return struct.unpack(header_fmt, s)
+
+
 def read_trace_file(fobj):
     """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, arg1, ..., arg6)."""
-    header = read_record(fobj)
-    if header is None or \
-       header[0] != header_event_id or \
-       header[1] != header_magic or \
-       header[2] != header_version:
-        raise ValueError('not a trace file or incompatible version')
-
     while True:
         rec = read_record(fobj)
         if rec is None:
@@ -64,6 +86,62 @@ def read_trace_file(fobj):
 
         yield rec
 
+def process_event(event_id, fobj):
+    params = etypes[event_id]
+    for elem in params:
+        if type_is_string(elem):
+            l = fobj.read(4)
+            (len,) = struct.unpack('=L', l)
+            s = fobj.read(len)
+            type, sep, var = elem.rpartition('*')
+            print '%(arg)s=%(val)s' % { 'arg': var.lstrip(), 'val': s },
+        elif '*' in elem:
+            (value,) = struct.unpack('=Q', fobj.read(8))
+            type, sep, var = elem.rpartition('*')
+            print '%(arg)s=0x%(val)u' % { 'arg': var.lstrip(), 'val': value },
+        else:
+            (value,) = struct.unpack('=Q', fobj.read(8))
+            type, sep, var = elem.rpartition(' ')
+            print '%(arg)s=%(val)u' % { 'arg': var.lstrip(), 'val': value },
+    print
+    return
+
+etypes = get_event_argtypes(open(sys.argv[1], 'r'))
+def processv2(fobj):
+    '''Process simpletrace v2 log trace records'''
+    events = parse_events(open(sys.argv[1], 'r'))
+    #print events
+    max_events = len(events) - 1
+    last_timestamp = None
+    while True:
+        # read record header
+        rechdr = read_header(fobj)
+        if rechdr is None:
+            print "No more records"
+            break
+
+        if rechdr[0] >= max_events and rechdr[0] != dropped_event_id:
+            print "Invalid Event ID found, Trace Log may be corrupted !!!"
+            sys.exit(1)
+
+        if rechdr[0] == dropped_event_id:
+            (value,) = struct.unpack('=Q', fobj.read(8))
+            print 'Events dropped ! Number of events dropped =', value
+            continue
+
+        if last_timestamp is None:
+            last_timestamp = rechdr[1]
+        delta_ns = rechdr[1] - last_timestamp
+        last_timestamp = rechdr[1]
+
+        print events[rechdr[0]][0],  '%0.3f' % (delta_ns / 1000.0),
+        # read data
+        # process_event(rec[0], fobj)
+        # rechdr[2] is record length (including header)
+        #print etypes[rechdr[0]]
+        #data = fobj.read(rechdr[2] - header_len)
+        process_event(rechdr[0], fobj)
+
 class Analyzer(object):
     """A trace file analyzer which processes trace records.
 
@@ -90,8 +168,6 @@ def process(events, log, analyzer):
     """Invoke an analyzer on each event in a log."""
     if isinstance(events, str):
         events = parse_events(open(events, 'r'))
-    if isinstance(log, str):
-        log = open(log, 'rb')
 
     def build_fn(analyzer, event):
         fn = getattr(analyzer, event[0], None)
@@ -129,8 +205,10 @@ def run(analyzer):
         sys.exit(1)
 
     events = parse_events(open(sys.argv[1], 'r'))
-    process(events, sys.argv[2], analyzer)
+    process(events, log, analyzer)
+
 
+log = open(sys.argv[2], 'rb')
 if __name__ == '__main__':
     class Formatter(Analyzer):
         def __init__(self):
@@ -148,4 +226,16 @@ if __name__ == '__main__':
                 fields.append('%s=0x%x' % (event[i], rec[i + 1]))
             print ' '.join(fields)
 
-    run(Formatter())
+    header = read_header(log)
+    if header is None or \
+        header[0] != header_event_id or \
+        header[1] != header_magic:
+         raise ValueError('not a valid trace file')
+    if header[2] == 0:   # version 1
+        # ver 1 tracelog header contains few more unused bytes
+        temp = log.read(40) # read those bytes and continue
+        run(Formatter())
+    elif header[2] == 2: # version 2
+        processv2(log)
+    else:
+        raise ValueError('trace file version not supported')
-- 
1.7.1.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2
  2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
                   ` (13 preceding siblings ...)
  2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 14/14] simpletrace.py: Support for simpletrace v2 log format Harsh Prateek Bora
@ 2012-02-28 20:23 ` Lluís Vilanova
  2012-03-01  6:03   ` Harsh Bora
  14 siblings, 1 reply; 19+ messages in thread
From: Lluís Vilanova @ 2012-02-28 20:23 UTC (permalink / raw)
  To: Harsh Prateek Bora; +Cc: stefanha, qemu-devel, aneesh.kumar

Harsh Prateek Bora writes:

> This patchset introduces 2 major updates:
> 1) Tracetool Improvements (Conversion from shell script to python)
> 2) Simpletrace v2 log format (Support for variable args, strings)

ping


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2
  2012-02-28 20:23 ` [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Lluís Vilanova
@ 2012-03-01  6:03   ` Harsh Bora
  2012-03-01 13:30     ` Harsh Bora
  0 siblings, 1 reply; 19+ messages in thread
From: Harsh Bora @ 2012-03-01  6:03 UTC (permalink / raw)
  To: Lluís Vilanova; +Cc: stefanha, qemu-devel, aneesh.kumar

On 02/29/2012 01:53 AM, Lluís Vilanova wrote:
> Harsh Prateek Bora writes:
>
>> This patchset introduces 2 major updates:
>> 1) Tracetool Improvements (Conversion from shell script to python)
>> 2) Simpletrace v2 log format (Support for variable args, strings)
>
> ping
>

Hi Lluis,
I have actually moved into another project and therefore struggling to 
find time for the last patch to update the log reader script. I am 
planning to work over it this weekend.

BTW, I hope, tracetool conversion (shell script to python) patches can 
be reviewed/merged early as they are independent of simpletrace v2. Stefan ?

regards,
Harsh

>
> Lluis
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2
  2012-03-01  6:03   ` Harsh Bora
@ 2012-03-01 13:30     ` Harsh Bora
  2012-03-01 19:06       ` Lluís Vilanova
  0 siblings, 1 reply; 19+ messages in thread
From: Harsh Bora @ 2012-03-01 13:30 UTC (permalink / raw)
  To: Lluís Vilanova; +Cc: stefanha, qemu-devel, aneesh.kumar

On 03/01/2012 11:33 AM, Harsh Bora wrote:
> On 02/29/2012 01:53 AM, Lluís Vilanova wrote:
>> Harsh Prateek Bora writes:
>>
>>> This patchset introduces 2 major updates:
>>> 1) Tracetool Improvements (Conversion from shell script to python)
>>> 2) Simpletrace v2 log format (Support for variable args, strings)
>>
>> ping
>>
>
> Hi Lluis,

Okay, I just gave it a shot now and sent the updated patch series (RFC 
PATCH v5) with updated log reader script as well. Thanks for the 
patience though !

Stefan, Would you like to consider reviewing/merging "RFC v5 PATCH" 
series now ?

regards,
Harsh

> regards,
> Harsh
>
>>
>> Lluis
>>
>
>

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2
  2012-03-01 13:30     ` Harsh Bora
@ 2012-03-01 19:06       ` Lluís Vilanova
  0 siblings, 0 replies; 19+ messages in thread
From: Lluís Vilanova @ 2012-03-01 19:06 UTC (permalink / raw)
  To: Harsh Bora; +Cc: stefanha, qemu-devel, aneesh.kumar

Harsh Bora writes:

> On 03/01/2012 11:33 AM, Harsh Bora wrote:
>> On 02/29/2012 01:53 AM, Lluís Vilanova wrote:
>>> Harsh Prateek Bora writes:
>>> 
>>>> This patchset introduces 2 major updates:
>>>> 1) Tracetool Improvements (Conversion from shell script to python)
>>>> 2) Simpletrace v2 log format (Support for variable args, strings)
>>> 
>>> ping
>>> 
>> 
>> Hi Lluis,

> Okay, I just gave it a shot now and sent the updated patch series (RFC PATCH v5)
> with updated log reader script as well. Thanks for the patience though !

Thanks a lot!



> Stefan, Would you like to consider reviewing/merging "RFC v5 PATCH" series now ?


Lluis

-- 
 "And it's much the same thing with knowledge, for whenever you learn
 something new, the whole world becomes that much richer."
 -- The Princess of Pure Reason, as told by Norton Juster in The Phantom
 Tollbooth

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2012-03-01 19:07 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-15 15:46 [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 01/14] Converting tracetool.sh to tracetool.py Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 02/14] trace: [tracetool] Do not rebuild event list in backend code Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 03/14] trace: [tracetool] Simplify event line parsing Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 04/14] trace: [tracetool] Do not precompute the event number Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 05/14] trace: [tracetool] Add support for event properties Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 06/14] trace: [tracetool] Process the "disable" event property Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 07/14] trace: [tracetool] Rewrite event argument parsing Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 08/14] trace: [tracetool] Make format-specific code optional with access to events Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 09/14] trace: [tracetool] Automatically establish available backends and formats Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 10/14] trace: Provide a per-event status define for conditional compilation Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 11/14] trace: [tracetool] Add error-reporting functions Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 12/14] monitor: remove unused do_info_trace Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 13/14] Simpletrace v2: Handle var num of args, strings Harsh Prateek Bora
2012-02-15 15:46 ` [Qemu-devel] [RFC PATCH v4 14/14] simpletrace.py: Support for simpletrace v2 log format Harsh Prateek Bora
2012-02-28 20:23 ` [Qemu-devel] [RFC PATCH v4 00/14] Tracing Improvements, Simpletrace v2 Lluís Vilanova
2012-03-01  6:03   ` Harsh Bora
2012-03-01 13:30     ` Harsh Bora
2012-03-01 19:06       ` Lluís Vilanova

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).