bitkeeper revision 1.891.1.8 (40a2299bVaCq0t5_5UXpB7OSB1yLKA)
authormwilli2@equilibrium.research.intel-research.net <mwilli2@equilibrium.research.intel-research.net>
Wed, 12 May 2004 13:41:47 +0000 (13:41 +0000)
committermwilli2@equilibrium.research.intel-research.net <mwilli2@equilibrium.research.intel-research.net>
Wed, 12 May 2004 13:41:47 +0000 (13:41 +0000)
Update xentrace to produce binary output format and xentrace_format to
correctly parse it.

.rootkeys
tools/xentrace/formats
tools/xentrace/xentrace.8
tools/xentrace/xentrace.c
tools/xentrace/xentrace_cpusplit [deleted file]
tools/xentrace/xentrace_cpusplit.1 [deleted file]
tools/xentrace/xentrace_format
tools/xentrace/xentrace_format.1

index ec2ce5f26efdc707dd88f491417929e9337c7d0b..9c00df8f44d6d54c233de51c9c9b99efc473c726 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40a107afN60pFdURgBv9KwEzgRl5mQ tools/xentrace/formats
 4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
 403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
-403a3edb0lzD0Fojc-NYNoXr3SYrnA tools/xentrace/xentrace_cpusplit
-4050c413BnzzZZlZRI1ai6oFXOsHLQ tools/xentrace/xentrace_cpusplit.1
 403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
 4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
 3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
index 95d5cbabc8fe0be6c5d375d088f3455d05ea823f..726c199bd923f3bcaded4a1aa99608775de229f2 100644 (file)
@@ -1,13 +1,13 @@
-0x00010000     CPU%(cpu)d 0x%(tsc)x sched_add_domain(0x%(3)08x)            [ dom id = 0x%(1)08x%(2)08x   ]
-0x00010001     CPU%(cpu)d 0x%(tsc)x sched_rem_domain(0x%08(3)x)            [ dom id = 0x%(1)08x%(2)08x   ]
-0x00010002     CPU%(cpu)d 0x%(tsc)x __wake_up(0x%(3)08x)                   [ dom id = 0x%(1)08x%(2)08x   ]
+0x00010000     CPU%(cpu)d 0x%(tsc)x sched_add_domain(0x%(3)08x)            [ dom id = 0x%(1)x%(2)08x   ]
+0x00010001     CPU%(cpu)d 0x%(tsc)x sched_rem_domain(0x%08(3)x)            [ dom id = 0x%(1)x%(2)08x   ]
+0x00010002     CPU%(cpu)d 0x%(tsc)x __wake_up(0x%(3)08x)                   [ dom id = 0x%(1)x%(2)08x   ]
 0x00010003     CPU%(cpu)d 0x%(tsc)x do_block()                             [ current = 0x%(2)08x         ]
 0x00010004     CPU%(cpu)d 0x%(tsc)x do_yield()                             [ current = %(2)08x         ]
 0x00010005     CPU%(cpu)d 0x%(tsc)x do_set_timer_op(0x%(4)08x, 0x%(5)08x)  [ current = 0x%(3)08x ]
 0x00010006     CPU%(cpu)d 0x%(tsc)x sched_ctl(0x%(1)08x)
-0x00010007     CPU%(cpu)d 0x%(tsc)x sched_adjdom(params)                   [ dom id = 0x%(1)08x%(2)08x   ]
-0x00010008     CPU%(cpu)d 0x%(tsc)x __reschedule(0x%(3)08x)                [ dom id = 0x%(1)08x%(2)08x   ]
-0x00010009     CPU%(cpu)d 0x%(tsc)x switching to task_struct 0x%(1)08x     [ dom id = 0x%(1)08x     ]
+0x00010007     CPU%(cpu)d 0x%(tsc)x sched_adjdom(params)                   [ dom id = 0x%(1)x%(2)08x   ]
+0x00010008     CPU%(cpu)d 0x%(tsc)x __reschedule(0x%(3)08x)                [ dom id = 0x%(1)x%(2)08x   ]
+0x00010009     CPU%(cpu)d 0x%(tsc)x switching to task_struct 0x%(1)08x     [ dom id = 0x%(1)x     ]
 0x0001000A     CPU%(cpu)d 0x%(tsc)x s_timer_fn(unused)
 0x0001000B     CPU%(cpu)d 0x%(tsc)x t_timer_fn(unused)
 0x0001000C     CPU%(cpu)d 0x%(tsc)x dom_timer_fn(data)
index b9720b9fbecc666fb5a6fadea162bd0855153bc8..93c86ac8ad6e7decef5fd4ba1c157d8a34b4115c 100644 (file)
@@ -10,17 +10,22 @@ xentrace \- capture Xen trace buffer data
 ]
 .SH DESCRIPTION
 .B xentrace
-is used to dump data from Xen's per-cpu trace buffers.  Records
-are dumped in ASCII format, onto the standard output or a \fIFILE\fP
-specified on the command line.
-Trace records are formatted as follows:
+is used to capture trace buffer data from Xen.  The data is
+output in the following binary format (host endian):
 .PP
-                    CPU TSC EVENT D1 D2 D3 D4 D5
+    CPU(uint) TSC(u64) EVENT(u32) D1 D2 D3 D4 D5 (all u32)
 .PP
 Where CPU is the processor number, TSC is the record's timestamp
 (the value of the CPU cycle counter), EVENT is the event ID and
 D1...D5 are the trace data.
 
+Data is dumped onto the standard output (which must not be a TTY) or a
+\fIFILE\fP specified on the command line.
+
+The output should be parsed using the tool xentrace_format, which can
+produce human-readable output in ASCII format.
+
+
 .SS Options
 .TP
 .B -t, --log-thresh=l
index edfb907ebd050bce0f2ca656359333177a60a4da..157435baa06f5510096c02a75a2b130454a77d0f 100644 (file)
@@ -26,8 +26,7 @@
 /* from xen/include/hypervisor-ifs */
 #include <trace.h>
 
-extern FILE *stdout;
-
+extern FILE *stderr;
 
 /***** Compile time configuration of defaults ********************************/
 
@@ -53,7 +52,6 @@ int interrupted = 0; /* gets set if we get a SIGHUP */
 void close_handler(int signal)
 {
     interrupted = 1;
-    fprintf(stderr,"Received signal %d, now exiting\n", signal);
 }
 
 /**
@@ -70,23 +68,21 @@ struct timespec millis_to_timespec(unsigned long millis)
     return spec;
 }
 
-
 /**
- * print_rec - plain print an event given a pointer to its start
- * @cpu:       CPU the data came from
- * @data:      pointer to the start of the event data
- * @out:       file stream to print out to
+ * write_rec - output a trace record in binary format
+ * @cpu      - source buffer CPU ID
+ * @rec      - trace record to output
+ * @out      - output stream
  *
- * Takes a pointer to a record and prints out the data.
+ * Outputs the trace record to a filestream, prepending the CPU ID of the
+ * source trace buffer.
  */
-void print_rec(unsigned int cpu, struct t_rec *rec, FILE *out)
-{    
-    fprintf(out, "%u %llu %lu %lu %lu %lu %lu %lu\n",
-           cpu, rec->cycles, rec->event, rec->d1, rec->d2,
-           rec->d3, rec->d4, rec->d5);
+void write_rec(unsigned int cpu, struct t_rec *rec, FILE *out)
+{
+    fwrite(&cpu, sizeof(cpu), 1, out);
+    fwrite(rec, sizeof(*rec), 1, out);
 }
 
-
 /**
  * get_tbufs - get pointer to and size of the trace buffers
  * @phys_addr: location to store physical address if the trace buffers to
@@ -321,11 +317,11 @@ int monitor_tbufs(FILE *logfile)
             {
                 /* output pre-wrap data */
                 for(j = 0; j < prewrap; j++)
-                    print_rec(i, data[i] + tails[i] + j, logfile);
+                    write_rec(i, data[i] + tails[i] + j, logfile);
                 
                 /* output post-wrap data, if any */                    
                 for(j = 0; j < (newdata - prewrap); j++)
-                    print_rec(i, data[i] + j, logfile);  
+                    write_rec(i, data[i] + j, logfile);  
                 
                 tails[i] += newdata;
                 if(tails[i] >= meta[i]->size) tails[i] = 0;
@@ -418,9 +414,10 @@ const struct argp parser_def =
     "Tool to capure Xen trace buffer data"
     "\v"
     "This tool is used to capture trace buffer data from Xen.  The data is "
-    "output as space-separated decimal numbers, represented in ASCII, in "
-    "the following order:\n\n"
-    "  CPU TSC EVENT DATA1 DATA2 DATA3 DATA4 DATA5\n"
+    "output in a binary format, in the following order:\n\n"
+    "  CPU(uint) TSC(u64) EVENT(u32) D1 D2 D3 D4 D5 (all u32)\n\n"
+    "The output should be parsed using the tool xentrace_format, which can "
+    "produce human-readable output in ASCII format."
 };
 
 
@@ -430,8 +427,8 @@ const char *argp_program_bug_address = "<mark.a.williamson@intel.com>";
     
 int main(int argc, char **argv)
 {
-    int ret;
-    FILE *logfile = stdout;
+    int outfd = 1, ret;
+    FILE *logfile;
     struct sigaction act;
 
     opts.outfile = 0;
@@ -441,7 +438,21 @@ int main(int argc, char **argv)
     argp_parse(&parser_def, argc, argv, 0, 0, &opts);
 
     if ( opts.outfile )
-        logfile = fopen(opts.outfile, "w");
+        outfd = open(opts.outfile, O_WRONLY | O_CREAT);
+
+    if(outfd < 0)
+    {
+        perror("Could not open output file");
+        exit(EXIT_FAILURE);
+    }        
+
+    if(isatty(outfd))
+    {
+        fprintf(stderr, "Cannot output to a TTY, specify a log file.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    logfile = fdopen(outfd, "w");
     
     /* ensure that if we get a signal, we'll do cleanup, then exit */
     act.sa_handler = close_handler;
diff --git a/tools/xentrace/xentrace_cpusplit b/tools/xentrace/xentrace_cpusplit
deleted file mode 100644 (file)
index 9847b79..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env python
-
-# by Mark Williamson, (C) 2004 Intel Research Cambridge
-
-# Program for separating trace buffer data into per-cpu log files.
-
-import re, sys, signal
-
-def usage():
-    print >> sys.stderr, \
-          "Usage: " + sys.argv[0] + """ base-name
-          Separates ASCII trace buffer data on stdin into per-CPU trace
-          files.  The trace files are named by appending the CPU number
-          to the base name supplied on the command line.
-
-          Depending on your system and the volume of trace buffer data,
-          this script may not be able to keep up with the output of xentrace
-          if it is piped directly.  In these circumstances you should have
-          xentrace output to a file for processing off-line.
-          """
-    sys.exit(1)
-    
-def sighand(x,y):
-    global interrupted
-    interrupted = 1
-
-signal.signal(signal.SIGTERM, sighand)
-signal.signal(signal.SIGHUP,  sighand)
-signal.signal(signal.SIGINT,  sighand)
-
-r = re.compile("(\d) .*")
-
-if len(sys.argv) < 2:
-    usage()
-else:
-    base_name = sys.argv[1]
-
-files = {}
-interrupted = 0
-
-while not interrupted:
-    try:
-        line = sys.stdin.readline()
-        if not line: break
-        
-        m = r.match(line)
-
-        if not m: print >> sys.stderr, "Invalid input line."
-        
-        cpu = m.group(1)
-        
-        if not files.has_key(base_name + str(cpu)):
-            files[base_name + str(cpu)] = open(base_name + str(cpu), "w")
-            
-        print >> files[base_name + str(cpu)], line,
-
-    except IOError: sys.exit()
-
-# files closed automatically
diff --git a/tools/xentrace/xentrace_cpusplit.1 b/tools/xentrace/xentrace_cpusplit.1
deleted file mode 100644 (file)
index 9b35ed5..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-.TH XENTRACE_CPUSPLIT 1 "11 March 2004" "Xen domain 0 utils"
-.SH NAME
-xentrace_cpusplit \- separate Xen trace data into per-CPU log files
-.SH SYNOPSIS
-.B xentrace_cpusplit
-[
-.I BASE-NAME
-]
-.SH DESCRIPTION
-.B xentrace_cpusplit
-Separates ASCII trace buffer data from stdin into per-CPU trace
-files.  The trace files are named by appending the CPU number
-to the \fIBASE-NAME\fP supplied on the command line.
-
-The trace records in the per-CPU files are in identical format to the
-original output of \fBxentrace\fP and are in chronological order.
-
-Depending on your system and the rate at which trace data is produced,
-this script may not be able to keep up with the output of
-\fBxentrace\fP if it is piped directly.  In these circumstances you
-should have \fBxentrace\fP output to a file for processing off-line.
-
-.SH AUTHOR
-Mark A. Williamson <mark.a.williamson@intel.com>
-
-.SH "SEE ALSO"
-xentrace(8), xentrace_format(1)
index 8da4fc4d68edfb80547b7773553e8941ac0a9d25..4014811249932a0f0fe0a6afea6970d80893a769 100644 (file)
@@ -4,14 +4,15 @@
 
 # Program for reformatting trace buffer output according to user-supplied rules
 
-import re, sys, string, signal
+import re, sys, string, signal, struct
 
 def usage():
     print >> sys.stderr, \
           "Usage: " + sys.argv[0] + """ defs-file
-          Parses trace data in ASCII format and reformats it according to the
-          rules in a file of definitions.  The rules in this file should have
-          the format ({ and } show grouping and are not part of the syntax):
+          Parses trace data in binary format, as output by Xentrace and
+          reformats it according to the rules in a file of definitions.  The
+          rules in this file should have the format ({ and } show grouping
+          and are not part of the syntax):
 
           {event_id}{whitespace}{text format string}
 
@@ -68,31 +69,29 @@ interrupted = 0
 
 defs = read_defs(sys.argv[1])
 
-reg = re.compile('(\d+) (\d+) (\d+) (.*)')
+# structure of trace record + prepended CPU id (as output by xentrace):
+# CPU(I) TSC(Q) EVENT(L) D1(L) D2(L) D3(L) D4(L) D5(L)
+TRCREC = "IQLLLLLL"
 
 while not interrupted:
     try:
-        line = sys.stdin.readline()
+        line = sys.stdin.read(struct.calcsize(TRCREC))
         if not line:
             break
-        
-        m = reg.match(line)
-
-        if not m: print >> sys.stderr, "Invalid input line."
-
-        s = string.split(m.group(4))
 
-        args = {'cpu'   : eval(m.group(1)),
-                'tsc'   : eval(m.group(2)),
-                'event' : eval(m.group(3)) }
+        (cpu, tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line)
 
-        i = 1
-        for item in s:
-            args[str(i)] = eval(item)
-            i += 1
+        args = {'cpu'   : cpu,
+                'tsc'   : tsc,
+                'event' : event,
+                '1'     : d1,
+                '2'     : d2,
+                '3'     : d3,
+                '4'     : d4,
+                '5'     : d5    }
 
-        if defs.has_key(m.group(3)): print defs[m.group(3)] % args
+        if defs.has_key(str(event)): print defs[str(event)] % args
         # silently skip lines we don't have a format for - a 'complain' option
         # should be added if needed
 
-    except IOError: sys.exit()
+    except IOError, struct.error: sys.exit()
index b6f881b6e738c08e2bc252115d29d9a021dfddc4..374ec6df7086e2853e50587510545d9c97135638 100644 (file)
@@ -8,9 +8,9 @@ xentrace_format \- pretty-print Xen trace data
 ]
 .SH DESCRIPTION
 .B xentrace_format
-parses trace data from standard input and reformats it according to
-the rules in a file of definitions (\fIDEFS-FILE\fP), printing to
-standard output.
+parses trace data in \fBxentrace\fP binary format from standard input
+and reformats it according to the rules in a file of definitions
+(\fIDEFS-FILE\fP), printing to standard output.
 
 The rules in \fIDEFS-FILE\fP should have the format shown below: