Simpletrace v2: Support multiple arguments, strings.

Existing simpletrace backend allows to trace at max 6 args and does not
support strings. This newer tracelog format gets rid of fixed size records
and therefore allows to trace variable number of args including strings.

Sample trace with strings:
v9fs_version 0.000 tag=0xffff id=0x64 msize=0x2000 version=9P2000.L
v9fs_version_return 6.705 tag=0xffff id=0x64 msize=0x2000 version=9P2000.L

Signed-off-by: Harsh Prateek Bora <harsh@linux.vnet.ibm.com>
Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
This commit is contained in:
Harsh Prateek Bora 2012-07-18 15:15:59 +05:30 committed by Stefan Hajnoczi
parent 88affa1c77
commit 62bab73213
3 changed files with 273 additions and 131 deletions

View file

@ -15,9 +15,16 @@ __email__ = "stefanha@linux.vnet.ibm.com"
from tracetool import out
def is_string(arg):
strtype = ('const char*', 'char*', 'const char *', 'char *')
if arg.lstrip().startswith(strtype):
return True
else:
return False
def c(events):
out('#include "trace.h"',
'#include "trace/simple.h"',
'',
'TraceEvent trace_list[] = {')
@ -26,30 +33,75 @@ def c(events):
name = e.name,
)
out('};')
out('};',
'')
for num, event in enumerate(events):
out('void trace_%(name)s(%(args)s)',
'{',
' TraceBufferRecord rec;',
name = event.name,
args = event.args,
)
sizes = []
for type_, name in event.args:
if is_string(type_):
out(' size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;',
name = name,
)
strsizeinfo = "4 + arg%s_len" % name
sizes.append(strsizeinfo)
else:
sizes.append("8")
sizestr = " + ".join(sizes)
if len(event.args) == 0:
sizestr = '0'
out('',
' if (!trace_list[%(event_id)s].state) {',
' return;',
' }',
'',
' if (trace_record_start(&rec, %(event_id)s, %(size_str)s)) {',
' return; /* Trace Buffer Full, Event Dropped ! */',
' }',
event_id = num,
size_str = sizestr,
)
if len(event.args) > 0:
for type_, name in event.args:
# string
if is_string(type_):
out(' trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
name = name,
)
# pointer var (not string)
elif type_.endswith('*'):
out(' trace_record_write_u64(&rec, (uint64_t)(uint64_t *)%(name)s);',
name = name,
)
# primitive data type
else:
out(' trace_record_write_u64(&rec, (uint64_t)%(name)s);',
name = name,
)
out(' trace_record_finish(&rec);',
'}',
'')
def h(events):
out('#include "trace/simple.h"',
'')
for num, e in enumerate(events):
if len(e.args):
argstr = e.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)
out('static inline void trace_%(name)s(%(args)s)',
'{',
' trace%(argc)d(%(trace_args)s);',
'}',
name = e.name,
args = e.args,
argc = len(e.args),
trace_args = simple_args,
for event in events:
out('void trace_%(name)s(%(args)s);',
name = event.name,
args = event.args,
)
out('')
out('#define NR_TRACE_EVENTS %d' % len(events))
out('extern TraceEvent trace_list[NR_TRACE_EVENTS];')