mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
bitkeeper revision 1.891.1.8 (40a2299bVaCq0t5_5UXpB7OSB1yLKA)
Update xentrace to produce binary output format and xentrace_format to correctly parse it.
This commit is contained in:
1 parent
e3d8d5ffdd
commit
9b9ca98b6a
8 files changed
+73
-146
No files matched your search
@@ -115,8 +115,6 @@
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+34
-23
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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."
|
||||
(cpu, tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line)
|
||||
|
||||
s = string.split(m.group(4))
|
||||
args = {'cpu' : cpu,
|
||||
'tsc' : tsc,
|
||||
'event' : event,
|
||||
'1' : d1,
|
||||
'2' : d2,
|
||||
'3' : d3,
|
||||
'4' : d4,
|
||||
'5' : d5 }
|
||||
|
||||
args = {'cpu' : eval(m.group(1)),
|
||||
'tsc' : eval(m.group(2)),
|
||||
'event' : eval(m.group(3)) }
|
||||
|
||||
i = 1
|
||||
for item in s:
|
||||
args[str(i)] = eval(item)
|
||||
i += 1
|
||||
|
||||
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()
|
||||
@@ -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:
|
||||
|
||||
|
||||