2014-06-04 12:31:28

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 2/3] Add callchain to generic and tracepoint events.

Add callchain to generic and tracepoint events.
Since this alters the interface for the python scripts,
also adjust the script generation and the provided scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
tools/perf/scripts/python/check-perf-trace.py | 4 +-
.../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
tools/perf/scripts/python/futex-contention.py | 4 +-
tools/perf/scripts/python/net_dropmonitor.py | 2 +-
tools/perf/scripts/python/netdev-times.py | 26 ++---
tools/perf/scripts/python/sched-migration.py | 41 ++++----
tools/perf/scripts/python/sctop.py | 2 +-
tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
tools/perf/scripts/python/syscall-counts.py | 2 +-
.../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
11 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e..38dfb72 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):

class EventHeaders:
def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+ common_pid, common_comm, common_callchain):
self.cpu = common_cpu
self.secs = common_secs
self.nsecs = common_nsecs
self.pid = common_pid
self.comm = common_comm
+ self.callchain = common_callchain

def ts(self):
return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a76..334599c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():

def irq__softirq_entry(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- vec):
+ common_callchain, vec):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)

@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,

def kmem__kmalloc(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- call_site, ptr, bytes_req, bytes_alloc,
+ common_callchain, call_site, ptr, bytes_req, bytes_alloc,
gfp_flags):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 85805fa..24c97a5 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():

def raw_syscalls__sys_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
+ common_callchain, id, ret):
if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a3..0f5cf43 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
process_names = {} # long-lived pid-to-execname mapping

-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, uaddr, op, val, utime, uaddr2, val3):
cmd = op & FUTEX_CMD_MASK
if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
thread_thislock[tid] = uaddr
thread_blocktime[tid] = nsecs(s, ns)

-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, ret):
if thread_blocktime.has_key(tid):
elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b574059..0b6ce8c 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
print_drop_table()

# called from perf, when it finds a correspoinding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, location, protocol):
slocation = str(location)
try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32..4d21ef2 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
(len(rx_skb_list), of_count_rx_skb_list)

# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- irq, irq_name):
+ callchain, irq, irq_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
irq, irq_name)
all_event_list.append(event_info)

-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
all_event_list.append(event_info)

-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
napi, dev_name)
all_event_list.append(event_info)

-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, rc, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, rc ,dev_name)
all_event_list.append(event_info)

-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, protocol, location):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, protocol, location)
all_event_list.append(event_info)

-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr)
all_event_list.append(event_info)

-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec..de66cb3 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():

def sched__sched_stat_runtime(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, runtime, vruntime):
+ common_callchain, comm, pid, runtime, vruntime):
pass

def sched__sched_stat_iowait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_sleep(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_process_fork(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- parent_comm, parent_pid, child_comm, child_pid):
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
pass

def sched__sched_process_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_free(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_migrate_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, orig_cpu,
+ common_callchain, comm, pid, prio, orig_cpu,
dest_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)

def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
+ common_secs, common_nsecs, common_pid, common_comm, common_callchain,
prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio):

headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio)

def sched__sched_wakeup_new(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 1)

def sched__sched_wakeup(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 0)

def sched__sched_wait_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- ret):
+ common_callchain, ret):
pass

def sched__sched_kthread_stop(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid):
+ common_callchain, comm, pid):
pass

-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index 42c267e..df65a30 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index c64d1c5..9b07b39 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):

if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index b435d3f..5899ce5 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 8454dc9..4f81dc7 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
+#include "../machine.h"

PyMODINIT_FUNC initperf_trace_context(void);

@@ -236,12 +237,90 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
return event;
}

+
+static PyObject *python_process_callchain(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al)
+{
+ PyObject *pylist;
+
+ pylist = PyList_New(0);
+ if (!pylist)
+ Py_FatalError("couldn't create Python list");
+
+ if (!symbol_conf.use_callchain || !sample->callchain)
+ goto exit;
+
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
+ sample, NULL, NULL,
+ PERF_MAX_STACK_DEPTH) != 0) {
+ pr_err("Failed to resolve callchain. Skipping\n");
+ goto exit;
+ }
+ callchain_cursor_commit(&callchain_cursor);
+
+
+ while (1) {
+ PyObject *pyelem;
+ struct callchain_cursor_node *node;
+ node = callchain_cursor_current(&callchain_cursor);
+ if (!node)
+ break;
+
+ pyelem = PyDict_New();
+ if (!pyelem)
+ Py_FatalError("couldn't create Python dictionary");
+
+
+ pydict_set_item_string_decref(pyelem, "ip",
+ PyLong_FromUnsignedLongLong(node->ip));
+
+ if (node->sym) {
+ PyObject *pysym = PyDict_New();
+ if (!pysym)
+ Py_FatalError("couldn't create Python dictionary");
+ pydict_set_item_string_decref(pysym, "start",
+ PyLong_FromUnsignedLongLong(node->sym->start));
+ pydict_set_item_string_decref(pysym, "end",
+ PyLong_FromUnsignedLongLong(node->sym->end));
+ pydict_set_item_string_decref(pysym, "binding",
+ PyInt_FromLong(node->sym->binding));
+ pydict_set_item_string_decref(pysym, "name",
+ PyString_FromStringAndSize(node->sym->name,
+ node->sym->namelen));
+ pydict_set_item_string_decref(pyelem, "sym", pysym);
+ }
+
+ if (node->map) {
+ struct map *map = node->map;
+ const char *dsoname = "[unknown]";
+ if (map && map->dso && (map->dso->name || map->dso->long_name)) {
+ if (symbol_conf.show_kernel_path && map->dso->long_name)
+ dsoname = map->dso->long_name;
+ else if (map->dso->name)
+ dsoname = map->dso->name;
+ }
+ pydict_set_item_string_decref(pyelem, "dso",
+ PyString_FromString(dsoname));
+ }
+
+ callchain_cursor_advance(&callchain_cursor);
+ PyList_Append(pylist, pyelem);
+ Py_DECREF(pyelem);
+ }
+
+exit:
+ return pylist;
+}
+
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
+ PyObject *handler, *retval, *context, *t, *obj, *callchain;
+ PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long long val;
@@ -285,18 +364,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
+ pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@@ -329,6 +413,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);

}
+
if (!handler)
PyTuple_SetItem(t, n++, dict);

@@ -360,7 +445,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict;
+ PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;

@@ -400,6 +485,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@@ -596,6 +685,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
+ fprintf(ofp, "common_callchain, ");

not_first = 0;
count = 0;
@@ -638,7 +728,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}

- fprintf(ofp, "\\n\" %% \\\n\t\t(");
+ fprintf(ofp, "\" %% \\\n\t\t(");

not_first = 0;
count = 0;
@@ -674,7 +764,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}

- fprintf(ofp, "),\n\n");
+ fprintf(ofp, ")\n\n");
+
+ fprintf(ofp, "\t\tfor node in common_callchain:");
+ fprintf(ofp, "\n\t\t\tif 'sym' in node:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
+ fprintf(ofp, "\n\t\t\telse:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
+ fprintf(ofp, "\t\tprint \"\\n\"\n\n");
+
}

fprintf(ofp, "def trace_unhandled(event_name, context, "
--
1.8.1.2



Attachments:
smime.p7s (4.83 kB)
S/MIME Cryptographic Signature

2014-06-04 14:46:39

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 2/3] Add callchain to generic and tracepoint events.

2014-06-04 (수), 14:07 +0200, Joseph Schuchart:
> Add callchain to generic and tracepoint events.
> Since this alters the interface for the python scripts,
> also adjust the script generation and the provided scripts.
>
> Signed-off-by: Joseph Schuchart <[email protected]>
> Acked-by: Thomas Ilsche <[email protected]>

Acked-by: Namhyung Kim <[email protected]>

Thanks,
Namhyung


> ---
> .../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
> tools/perf/scripts/python/check-perf-trace.py | 4 +-
> .../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
> tools/perf/scripts/python/futex-contention.py | 4 +-
> tools/perf/scripts/python/net_dropmonitor.py | 2 +-
> tools/perf/scripts/python/netdev-times.py | 26 ++---
> tools/perf/scripts/python/sched-migration.py | 41 ++++----
> tools/perf/scripts/python/sctop.py | 2 +-
> tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
> tools/perf/scripts/python/syscall-counts.py | 2 +-
> .../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
> 11 files changed, 146 insertions(+), 48 deletions(-)
>
> diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> index de7211e..38dfb72 100644
> --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> @@ -107,12 +107,13 @@ def taskState(state):
>
> class EventHeaders:
> def __init__(self, common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm):
> + common_pid, common_comm, common_callchain):
> self.cpu = common_cpu
> self.secs = common_secs
> self.nsecs = common_nsecs
> self.pid = common_pid
> self.comm = common_comm
> + self.callchain = common_callchain
>
> def ts(self):
> return (self.secs * (10 ** 9)) + self.nsecs
> diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
> index 4647a76..334599c 100644
> --- a/tools/perf/scripts/python/check-perf-trace.py
> +++ b/tools/perf/scripts/python/check-perf-trace.py
> @@ -27,7 +27,7 @@ def trace_end():
>
> def irq__softirq_entry(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - vec):
> + common_callchain, vec):
> print_header(event_name, common_cpu, common_secs, common_nsecs,
> common_pid, common_comm)
>
> @@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,
>
> def kmem__kmalloc(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - call_site, ptr, bytes_req, bytes_alloc,
> + common_callchain, call_site, ptr, bytes_req, bytes_alloc,
> gfp_flags):
> print_header(event_name, common_cpu, common_secs, common_nsecs,
> common_pid, common_comm)
> diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
> index 85805fa..24c97a5 100644
> --- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
> +++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
> @@ -39,7 +39,7 @@ def trace_end():
>
> def raw_syscalls__sys_exit(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, ret):
> + common_callchain, id, ret):
> if (for_comm and common_comm != for_comm) or \
> (for_pid and common_pid != for_pid ):
> return
> diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
> index 11e70a3..0f5cf43 100644
> --- a/tools/perf/scripts/python/futex-contention.py
> +++ b/tools/perf/scripts/python/futex-contention.py
> @@ -21,7 +21,7 @@ thread_blocktime = {}
> lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
> process_names = {} # long-lived pid-to-execname mapping
>
> -def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
> +def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
> nr, uaddr, op, val, utime, uaddr2, val3):
> cmd = op & FUTEX_CMD_MASK
> if cmd != FUTEX_WAIT:
> @@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
> thread_thislock[tid] = uaddr
> thread_blocktime[tid] = nsecs(s, ns)
>
> -def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
> +def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
> nr, ret):
> if thread_blocktime.has_key(tid):
> elapsed = nsecs(s, ns) - thread_blocktime[tid]
> diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
> index b574059..0b6ce8c 100755
> --- a/tools/perf/scripts/python/net_dropmonitor.py
> +++ b/tools/perf/scripts/python/net_dropmonitor.py
> @@ -66,7 +66,7 @@ def trace_end():
> print_drop_table()
>
> # called from perf, when it finds a correspoinding event
> -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
> +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, location, protocol):
> slocation = str(location)
> try:
> diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
> index 9aa0a32..4d21ef2 100644
> --- a/tools/perf/scripts/python/netdev-times.py
> +++ b/tools/perf/scripts/python/netdev-times.py
> @@ -224,75 +224,75 @@ def trace_end():
> (len(rx_skb_list), of_count_rx_skb_list)
>
> # called from perf, when it finds a correspoinding event
> -def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> -def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> -def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
> - irq, irq_name):
> + callchain, irq, irq_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> irq, irq_name)
> all_event_list.append(event_info)
>
> -def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
> +def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
> all_event_list.append(event_info)
>
> -def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
> +def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> napi, dev_name)
> all_event_list.append(event_info)
>
> -def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
> +def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
> skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
> +def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
> skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
> +def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
> +def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen, rc, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, rc ,dev_name)
> all_event_list.append(event_info)
>
> -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
> +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, protocol, location):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, protocol, location)
> all_event_list.append(event_info)
>
> -def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
> +def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr)
> all_event_list.append(event_info)
>
> -def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
> +def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen)
> diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
> index 74d55ec..de66cb3 100644
> --- a/tools/perf/scripts/python/sched-migration.py
> +++ b/tools/perf/scripts/python/sched-migration.py
> @@ -369,93 +369,92 @@ def trace_end():
>
> def sched__sched_stat_runtime(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, runtime, vruntime):
> + common_callchain, comm, pid, runtime, vruntime):
> pass
>
> def sched__sched_stat_iowait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_stat_sleep(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_stat_wait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_process_fork(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - parent_comm, parent_pid, child_comm, child_pid):
> + common_callchain, parent_comm, parent_pid, child_comm, child_pid):
> pass
>
> def sched__sched_process_wait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_process_exit(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_process_free(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_migrate_task(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, orig_cpu,
> + common_callchain, comm, pid, prio, orig_cpu,
> dest_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
>
> def sched__sched_switch(event_name, context, common_cpu,
> - common_secs, common_nsecs, common_pid, common_comm,
> + common_secs, common_nsecs, common_pid, common_comm, common_callchain,
> prev_comm, prev_pid, prev_prio, prev_state,
> next_comm, next_pid, next_prio):
>
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
> next_comm, next_pid, next_prio)
>
> def sched__sched_wakeup_new(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, success,
> + common_callchain, comm, pid, prio, success,
> target_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.wake_up(headers, comm, pid, success, target_cpu, 1)
>
> def sched__sched_wakeup(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, success,
> + common_callchain, comm, pid, prio, success,
> target_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.wake_up(headers, comm, pid, success, target_cpu, 0)
>
> def sched__sched_wait_task(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - ret):
> + common_callchain, ret):
> pass
>
> def sched__sched_kthread_stop(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid):
> + common_callchain, comm, pid):
> pass
>
> -def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm):
> +def trace_unhandled(event_name, context, event_fields_dict):
> pass
> diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
> index 42c267e..df65a30 100644
> --- a/tools/perf/scripts/python/sctop.py
> +++ b/tools/perf/scripts/python/sctop.py
> @@ -44,7 +44,7 @@ def trace_begin():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
> if for_comm is not None:
> if common_comm != for_comm:
> return
> diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
> index c64d1c5..9b07b39 100644
> --- a/tools/perf/scripts/python/syscall-counts-by-pid.py
> +++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
> @@ -38,7 +38,7 @@ def trace_end():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
>
> if (for_comm and common_comm != for_comm) or \
> (for_pid and common_pid != for_pid ):
> diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
> index b435d3f..5899ce5 100644
> --- a/tools/perf/scripts/python/syscall-counts.py
> +++ b/tools/perf/scripts/python/syscall-counts.py
> @@ -35,7 +35,7 @@ def trace_end():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
> if for_comm is not None:
> if common_comm != for_comm:
> return
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 8454dc9..4f81dc7 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -32,6 +32,7 @@
> #include "../event.h"
> #include "../thread.h"
> #include "../trace-event.h"
> +#include "../machine.h"
>
> PyMODINIT_FUNC initperf_trace_context(void);
>
> @@ -236,12 +237,90 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
> return event;
> }
>
> +
> +static PyObject *python_process_callchain(struct perf_sample *sample,
> + struct perf_evsel *evsel,
> + struct addr_location *al)
> +{
> + PyObject *pylist;
> +
> + pylist = PyList_New(0);
> + if (!pylist)
> + Py_FatalError("couldn't create Python list");
> +
> + if (!symbol_conf.use_callchain || !sample->callchain)
> + goto exit;
> +
> + if (machine__resolve_callchain(al->machine, evsel, al->thread,
> + sample, NULL, NULL,
> + PERF_MAX_STACK_DEPTH) != 0) {
> + pr_err("Failed to resolve callchain. Skipping\n");
> + goto exit;
> + }
> + callchain_cursor_commit(&callchain_cursor);
> +
> +
> + while (1) {
> + PyObject *pyelem;
> + struct callchain_cursor_node *node;
> + node = callchain_cursor_current(&callchain_cursor);
> + if (!node)
> + break;
> +
> + pyelem = PyDict_New();
> + if (!pyelem)
> + Py_FatalError("couldn't create Python dictionary");
> +
> +
> + pydict_set_item_string_decref(pyelem, "ip",
> + PyLong_FromUnsignedLongLong(node->ip));
> +
> + if (node->sym) {
> + PyObject *pysym = PyDict_New();
> + if (!pysym)
> + Py_FatalError("couldn't create Python dictionary");
> + pydict_set_item_string_decref(pysym, "start",
> + PyLong_FromUnsignedLongLong(node->sym->start));
> + pydict_set_item_string_decref(pysym, "end",
> + PyLong_FromUnsignedLongLong(node->sym->end));
> + pydict_set_item_string_decref(pysym, "binding",
> + PyInt_FromLong(node->sym->binding));
> + pydict_set_item_string_decref(pysym, "name",
> + PyString_FromStringAndSize(node->sym->name,
> + node->sym->namelen));
> + pydict_set_item_string_decref(pyelem, "sym", pysym);
> + }
> +
> + if (node->map) {
> + struct map *map = node->map;
> + const char *dsoname = "[unknown]";
> + if (map && map->dso && (map->dso->name || map->dso->long_name)) {
> + if (symbol_conf.show_kernel_path && map->dso->long_name)
> + dsoname = map->dso->long_name;
> + else if (map->dso->name)
> + dsoname = map->dso->name;
> + }
> + pydict_set_item_string_decref(pyelem, "dso",
> + PyString_FromString(dsoname));
> + }
> +
> + callchain_cursor_advance(&callchain_cursor);
> + PyList_Append(pylist, pyelem);
> + Py_DECREF(pyelem);
> + }
> +
> +exit:
> + return pylist;
> +}
> +
> +
> static void python_process_tracepoint(struct perf_sample *sample,
> struct perf_evsel *evsel,
> struct thread *thread,
> struct addr_location *al)
> {
> - PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
> + PyObject *handler, *retval, *context, *t, *obj, *callchain;
> + PyObject *dict = NULL;
> static char handler_name[256];
> struct format_field *field;
> unsigned long long val;
> @@ -285,18 +364,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
> PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
> PyTuple_SetItem(t, n++, context);
>
> + /* ip unwinding */
> + callchain = python_process_callchain(sample, evsel, al);
> +
> if (handler) {
> PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
> PyTuple_SetItem(t, n++, PyInt_FromLong(s));
> PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
> PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
> PyTuple_SetItem(t, n++, PyString_FromString(comm));
> + PyTuple_SetItem(t, n++, callchain);
> } else {
> pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
> pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
> pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
> pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
> pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
> + pydict_set_item_string_decref(dict, "common_callchain", callchain);
> }
> for (field = event->format.fields; field; field = field->next) {
> if (field->flags & FIELD_IS_STRING) {
> @@ -329,6 +413,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> pydict_set_item_string_decref(dict, field->name, obj);
>
> }
> +
> if (!handler)
> PyTuple_SetItem(t, n++, dict);
>
> @@ -360,7 +445,7 @@ static void python_process_general_event(struct perf_sample *sample,
> struct thread *thread,
> struct addr_location *al)
> {
> - PyObject *handler, *retval, *t, *dict;
> + PyObject *handler, *retval, *t, *dict, *callchain;
> static char handler_name[64];
> unsigned n = 0;
>
> @@ -400,6 +485,10 @@ static void python_process_general_event(struct perf_sample *sample,
> PyString_FromString(al->sym->name));
> }
>
> + /* ip unwinding */
> + callchain = python_process_callchain(sample, evsel, al);
> + pydict_set_item_string_decref(dict, "callchain", callchain);
> +
> PyTuple_SetItem(t, n++, dict);
> if (_PyTuple_Resize(&t, n) == -1)
> Py_FatalError("error resizing Python tuple");
> @@ -596,6 +685,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "common_nsecs, ");
> fprintf(ofp, "common_pid, ");
> fprintf(ofp, "common_comm,\n\t");
> + fprintf(ofp, "common_callchain, ");
>
> not_first = 0;
> count = 0;
> @@ -638,7 +728,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "%%u");
> }
>
> - fprintf(ofp, "\\n\" %% \\\n\t\t(");
> + fprintf(ofp, "\" %% \\\n\t\t(");
>
> not_first = 0;
> count = 0;
> @@ -674,7 +764,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "%s", f->name);
> }
>
> - fprintf(ofp, "),\n\n");
> + fprintf(ofp, ")\n\n");
> +
> + fprintf(ofp, "\t\tfor node in common_callchain:");
> + fprintf(ofp, "\n\t\t\tif 'sym' in node:");
> + fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
> + fprintf(ofp, "\n\t\t\telse:");
> + fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
> + fprintf(ofp, "\t\tprint \"\\n\"\n\n");
> +
> }
>
> fprintf(ofp, "def trace_unhandled(event_name, context, "


2014-07-07 17:17:22

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 2/3] Add callchain to generic and tracepoint events.

On Wed, Jun 04, 2014 at 02:07:14PM +0200, Joseph Schuchart wrote:
> Add callchain to generic and tracepoint events.
> Since this alters the interface for the python scripts,
> also adjust the script generation and the provided scripts.

hi,
I might be out of track in here, since I wasn't CC-ed,
but I've got to this patchset as a dependency for perf
CTF perf script so I need it ;-) however..

I just tried to apply it and got some conflicts in patch 2/3.

Could you please rebase to the latest tip/perf/core and resend
the whole set? Also prefix your subjects with 'perf script:'

Arnaldo,
not sure if you are tracking these.. please let me know

thanks,
jirka

2014-07-09 07:40:48

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 1/3] perf script: Add missing calls to Py_DECREF for return values

[PATCH 1/3] perf script: Add missing calls to Py_DECREF for return values

Signed-off-by: Joseph Schuchart <[email protected]>
---
tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 1c41932..631aa85 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -50,10 +50,14 @@ static int zero_flag_atom;

static PyObject *main_module, *main_dict;

+static void handler_call_die(const char *handler_name) NORETURN;
static void handler_call_die(const char *handler_name)
{
PyErr_Print();
Py_FatalError("problem in Python trace event handler");
+ // Py_FatalError does not return
+ // but we have to make the compiler happy
+ abort();
}

/*
@@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -334,6 +340,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
} else {
handler = PyDict_GetItemString(main_dict, "trace_unhandled");
if (handler && PyCallable_Check(handler)) {
@@ -341,6 +348,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die("trace_unhandled");
+ Py_DECREF(retval);
}
Py_DECREF(dict);
}
@@ -400,6 +408,7 @@ static void python_process_general_event(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
exit:
Py_DECREF(dict);
Py_DECREF(t);
@@ -521,8 +530,7 @@ static int python_stop_script(void)
retval = PyObject_CallObject(handler, NULL);
if (retval == NULL)
handler_call_die("trace_end");
- else
- Py_DECREF(retval);
+ Py_DECREF(retval);
out:
Py_XDECREF(main_dict);
Py_XDECREF(main_module);
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 07:41:01

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

[PATCH 2/3] perf script: Add callchain to generic and tracepoint events. Since
this alters the interface for the python scripts, also adjust the script
generation and the provided scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
tools/perf/scripts/python/check-perf-trace.py | 4 +-
.../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
tools/perf/scripts/python/futex-contention.py | 4 +-
tools/perf/scripts/python/net_dropmonitor.py | 2 +-
tools/perf/scripts/python/netdev-times.py | 26 ++---
tools/perf/scripts/python/sched-migration.py | 41 ++++----
tools/perf/scripts/python/sctop.py | 2 +-
tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
tools/perf/scripts/python/syscall-counts.py | 2 +-
.../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
11 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e..38dfb72 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):

class EventHeaders:
def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+ common_pid, common_comm, common_callchain):
self.cpu = common_cpu
self.secs = common_secs
self.nsecs = common_nsecs
self.pid = common_pid
self.comm = common_comm
+ self.callchain = common_callchain

def ts(self):
return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a76..334599c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():

def irq__softirq_entry(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- vec):
+ common_callchain, vec):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)

@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,

def kmem__kmalloc(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- call_site, ptr, bytes_req, bytes_alloc,
+ common_callchain, call_site, ptr, bytes_req, bytes_alloc,
gfp_flags):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 266a836..cafeff3 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():

def raw_syscalls__sys_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
+ common_callchain, id, ret):
if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a3..0f5cf43 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
process_names = {} # long-lived pid-to-execname mapping

-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, uaddr, op, val, utime, uaddr2, val3):
cmd = op & FUTEX_CMD_MASK
if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
thread_thislock[tid] = uaddr
thread_blocktime[tid] = nsecs(s, ns)

-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, ret):
if thread_blocktime.has_key(tid):
elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b574059..0b6ce8c 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
print_drop_table()

# called from perf, when it finds a correspoinding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, location, protocol):
slocation = str(location)
try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32..4d21ef2 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
(len(rx_skb_list), of_count_rx_skb_list)

# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- irq, irq_name):
+ callchain, irq, irq_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
irq, irq_name)
all_event_list.append(event_info)

-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
all_event_list.append(event_info)

-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
napi, dev_name)
all_event_list.append(event_info)

-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, rc, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, rc ,dev_name)
all_event_list.append(event_info)

-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, protocol, location):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, protocol, location)
all_event_list.append(event_info)

-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr)
all_event_list.append(event_info)

-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec..de66cb3 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():

def sched__sched_stat_runtime(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, runtime, vruntime):
+ common_callchain, comm, pid, runtime, vruntime):
pass

def sched__sched_stat_iowait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_sleep(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_process_fork(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- parent_comm, parent_pid, child_comm, child_pid):
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
pass

def sched__sched_process_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_free(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_migrate_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, orig_cpu,
+ common_callchain, comm, pid, prio, orig_cpu,
dest_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)

def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
+ common_secs, common_nsecs, common_pid, common_comm, common_callchain,
prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio):

headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio)

def sched__sched_wakeup_new(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 1)

def sched__sched_wakeup(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 0)

def sched__sched_wait_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- ret):
+ common_callchain, ret):
pass

def sched__sched_kthread_stop(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid):
+ common_callchain, comm, pid):
pass

-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index c9f3058..61621b9 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index cf2054c..daf314c 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):

if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index 92b2938..e66a773 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 631aa85..dae78e4 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
+#include "../machine.h"

PyMODINIT_FUNC initperf_trace_context(void);

@@ -237,12 +238,90 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
return event;
}

+
+static PyObject *python_process_callchain(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al)
+{
+ PyObject *pylist;
+
+ pylist = PyList_New(0);
+ if (!pylist)
+ Py_FatalError("couldn't create Python list");
+
+ if (!symbol_conf.use_callchain || !sample->callchain)
+ goto exit;
+
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
+ sample, NULL, NULL,
+ PERF_MAX_STACK_DEPTH) != 0) {
+ pr_err("Failed to resolve callchain. Skipping\n");
+ goto exit;
+ }
+ callchain_cursor_commit(&callchain_cursor);
+
+
+ while (1) {
+ PyObject *pyelem;
+ struct callchain_cursor_node *node;
+ node = callchain_cursor_current(&callchain_cursor);
+ if (!node)
+ break;
+
+ pyelem = PyDict_New();
+ if (!pyelem)
+ Py_FatalError("couldn't create Python dictionary");
+
+
+ pydict_set_item_string_decref(pyelem, "ip",
+ PyLong_FromUnsignedLongLong(node->ip));
+
+ if (node->sym) {
+ PyObject *pysym = PyDict_New();
+ if (!pysym)
+ Py_FatalError("couldn't create Python dictionary");
+ pydict_set_item_string_decref(pysym, "start",
+ PyLong_FromUnsignedLongLong(node->sym->start));
+ pydict_set_item_string_decref(pysym, "end",
+ PyLong_FromUnsignedLongLong(node->sym->end));
+ pydict_set_item_string_decref(pysym, "binding",
+ PyInt_FromLong(node->sym->binding));
+ pydict_set_item_string_decref(pysym, "name",
+ PyString_FromStringAndSize(node->sym->name,
+ node->sym->namelen));
+ pydict_set_item_string_decref(pyelem, "sym", pysym);
+ }
+
+ if (node->map) {
+ struct map *map = node->map;
+ const char *dsoname = "[unknown]";
+ if (map && map->dso && (map->dso->name || map->dso->long_name)) {
+ if (symbol_conf.show_kernel_path && map->dso->long_name)
+ dsoname = map->dso->long_name;
+ else if (map->dso->name)
+ dsoname = map->dso->name;
+ }
+ pydict_set_item_string_decref(pyelem, "dso",
+ PyString_FromString(dsoname));
+ }
+
+ callchain_cursor_advance(&callchain_cursor);
+ PyList_Append(pylist, pyelem);
+ Py_DECREF(pyelem);
+ }
+
+exit:
+ return pylist;
+}
+
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
+ PyObject *handler, *retval, *context, *t, *obj, *callchain;
+ PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long long val;
@@ -286,18 +365,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
+ pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@@ -330,6 +414,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);

}
+
if (!handler)
PyTuple_SetItem(t, n++, dict);

@@ -361,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict;
+ PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;

@@ -401,6 +486,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@@ -597,6 +686,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
+ fprintf(ofp, "common_callchain, ");

not_first = 0;
count = 0;
@@ -640,7 +730,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}

- fprintf(ofp, "\\n\" %% \\\n\t\t(");
+ fprintf(ofp, "\" %% \\\n\t\t(");

not_first = 0;
count = 0;
@@ -676,7 +766,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}

- fprintf(ofp, "),\n\n");
+ fprintf(ofp, ")\n\n");
+
+ fprintf(ofp, "\t\tfor node in common_callchain:");
+ fprintf(ofp, "\n\t\t\tif 'sym' in node:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
+ fprintf(ofp, "\n\t\t\telse:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
+ fprintf(ofp, "\t\tprint \"\\n\"\n\n");
+
}

fprintf(ofp, "def trace_unhandled(event_name, context, "
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 07:40:46

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 3/3] perf script: Provide additional sample information on generic events

[PATCH 3/3] perf script: Provide additional sample information on
generic events to Python scripts, including pid, tid, and cpu for which the
event was recorded. At the moment, the pointer to the sample struct is
passed to scripts, which seems to be of little use. The patch puts this
information in dictionaries for easy access by Python scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index dae78e4..64923cd 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -446,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict, *callchain;
+ PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
static char handler_name[64];
unsigned n = 0;

@@ -462,6 +462,10 @@ static void python_process_general_event(struct perf_sample *sample,
if (!dict)
Py_FatalError("couldn't create Python dictionary");

+ dict_sample = PyDict_New();
+ if (!dict_sample)
+ Py_FatalError("couldn't create Python dictionary");
+
snprintf(handler_name, sizeof(handler_name), "%s", "process_event");

handler = PyDict_GetItemString(main_dict, handler_name);
@@ -471,8 +475,21 @@ static void python_process_general_event(struct perf_sample *sample,
pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)&evsel->attr, sizeof(evsel->attr)));
- pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
- (const char *)sample, sizeof(*sample)));
+
+ pydict_set_item_string_decref(dict_sample, "pid",
+ PyInt_FromLong(sample->pid));
+ pydict_set_item_string_decref(dict_sample, "tid",
+ PyInt_FromLong(sample->tid));
+ pydict_set_item_string_decref(dict_sample, "cpu",
+ PyInt_FromLong(sample->cpu));
+ pydict_set_item_string_decref(dict_sample, "ip",
+ PyLong_FromUnsignedLongLong(sample->ip));
+ pydict_set_item_string_decref(dict_sample, "time",
+ PyLong_FromUnsignedLongLong(sample->time));
+ pydict_set_item_string_decref(dict_sample, "period",
+ PyLong_FromUnsignedLongLong(sample->period));
+ pydict_set_item_string_decref(dict, "sample", dict_sample);
+
pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
(const char *)sample->raw_data, sample->raw_size));
pydict_set_item_string_decref(dict, "comm",
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 08:14:21

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 1/3] perf script: Add missing calls to Py_DECREF for return values

Hi Joseph,

On Wed, 09 Jul 2014 09:40:29 +0200, Joseph Schuchart wrote:
> [PATCH 1/3] perf script: Add missing calls to Py_DECREF for return values
>
> Signed-off-by: Joseph Schuchart <[email protected]>

Acked-by: Namhyung Kim <[email protected]>

Thanks,
Namhyung


> ---
> tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 1c41932..631aa85 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -50,10 +50,14 @@ static int zero_flag_atom;
>
> static PyObject *main_module, *main_dict;
>
> +static void handler_call_die(const char *handler_name) NORETURN;
> static void handler_call_die(const char *handler_name)
> {
> PyErr_Print();
> Py_FatalError("problem in Python trace event handler");
> + // Py_FatalError does not return
> + // but we have to make the compiler happy
> + abort();
> }
>
> /*
> @@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> }
>
> Py_DECREF(t);
> @@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> }
>
> Py_DECREF(t);
> @@ -334,6 +340,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> } else {
> handler = PyDict_GetItemString(main_dict, "trace_unhandled");
> if (handler && PyCallable_Check(handler)) {
> @@ -341,6 +348,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die("trace_unhandled");
> + Py_DECREF(retval);
> }
> Py_DECREF(dict);
> }
> @@ -400,6 +408,7 @@ static void python_process_general_event(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> exit:
> Py_DECREF(dict);
> Py_DECREF(t);
> @@ -521,8 +530,7 @@ static int python_stop_script(void)
> retval = PyObject_CallObject(handler, NULL);
> if (retval == NULL)
> handler_call_die("trace_end");
> - else
> - Py_DECREF(retval);
> + Py_DECREF(retval);
> out:
> Py_XDECREF(main_dict);
> Py_XDECREF(main_module);

2014-07-09 08:15:59

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

On Wed, 09 Jul 2014 09:40:34 +0200, Joseph Schuchart wrote:
> [PATCH 2/3] perf script: Add callchain to generic and tracepoint events. Since

This [PATCH x/x] part should go.


> this alters the interface for the python scripts, also adjust the script
> generation and the provided scripts.
>
> Signed-off-by: Joseph Schuchart <[email protected]>
> Acked-by: Thomas Ilsche <[email protected]>

Anyway,

Acked-by: Namhyung Kim <[email protected]>

Thanks,
Namhyung


> ---
> .../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
> tools/perf/scripts/python/check-perf-trace.py | 4 +-
> .../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
> tools/perf/scripts/python/futex-contention.py | 4 +-
> tools/perf/scripts/python/net_dropmonitor.py | 2 +-
> tools/perf/scripts/python/netdev-times.py | 26 ++---
> tools/perf/scripts/python/sched-migration.py | 41 ++++----
> tools/perf/scripts/python/sctop.py | 2 +-
> tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
> tools/perf/scripts/python/syscall-counts.py | 2 +-
> .../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
> 11 files changed, 146 insertions(+), 48 deletions(-)
>
> diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> index de7211e..38dfb72 100644
> --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> @@ -107,12 +107,13 @@ def taskState(state):
>
> class EventHeaders:
> def __init__(self, common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm):
> + common_pid, common_comm, common_callchain):
> self.cpu = common_cpu
> self.secs = common_secs
> self.nsecs = common_nsecs
> self.pid = common_pid
> self.comm = common_comm
> + self.callchain = common_callchain
>
> def ts(self):
> return (self.secs * (10 ** 9)) + self.nsecs
> diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
> index 4647a76..334599c 100644
> --- a/tools/perf/scripts/python/check-perf-trace.py
> +++ b/tools/perf/scripts/python/check-perf-trace.py
> @@ -27,7 +27,7 @@ def trace_end():
>
> def irq__softirq_entry(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - vec):
> + common_callchain, vec):
> print_header(event_name, common_cpu, common_secs, common_nsecs,
> common_pid, common_comm)
>
> @@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,
>
> def kmem__kmalloc(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - call_site, ptr, bytes_req, bytes_alloc,
> + common_callchain, call_site, ptr, bytes_req, bytes_alloc,
> gfp_flags):
> print_header(event_name, common_cpu, common_secs, common_nsecs,
> common_pid, common_comm)
> diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
> index 266a836..cafeff3 100644
> --- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
> +++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
> @@ -39,7 +39,7 @@ def trace_end():
>
> def raw_syscalls__sys_exit(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, ret):
> + common_callchain, id, ret):
> if (for_comm and common_comm != for_comm) or \
> (for_pid and common_pid != for_pid ):
> return
> diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
> index 11e70a3..0f5cf43 100644
> --- a/tools/perf/scripts/python/futex-contention.py
> +++ b/tools/perf/scripts/python/futex-contention.py
> @@ -21,7 +21,7 @@ thread_blocktime = {}
> lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
> process_names = {} # long-lived pid-to-execname mapping
>
> -def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
> +def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
> nr, uaddr, op, val, utime, uaddr2, val3):
> cmd = op & FUTEX_CMD_MASK
> if cmd != FUTEX_WAIT:
> @@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
> thread_thislock[tid] = uaddr
> thread_blocktime[tid] = nsecs(s, ns)
>
> -def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
> +def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
> nr, ret):
> if thread_blocktime.has_key(tid):
> elapsed = nsecs(s, ns) - thread_blocktime[tid]
> diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
> index b574059..0b6ce8c 100755
> --- a/tools/perf/scripts/python/net_dropmonitor.py
> +++ b/tools/perf/scripts/python/net_dropmonitor.py
> @@ -66,7 +66,7 @@ def trace_end():
> print_drop_table()
>
> # called from perf, when it finds a correspoinding event
> -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
> +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, location, protocol):
> slocation = str(location)
> try:
> diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
> index 9aa0a32..4d21ef2 100644
> --- a/tools/perf/scripts/python/netdev-times.py
> +++ b/tools/perf/scripts/python/netdev-times.py
> @@ -224,75 +224,75 @@ def trace_end():
> (len(rx_skb_list), of_count_rx_skb_list)
>
> # called from perf, when it finds a correspoinding event
> -def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> -def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> -def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
> +def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
> if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
> return
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
> all_event_list.append(event_info)
>
> def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
> - irq, irq_name):
> + callchain, irq, irq_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> irq, irq_name)
> all_event_list.append(event_info)
>
> -def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
> +def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
> all_event_list.append(event_info)
>
> -def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
> +def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> napi, dev_name)
> all_event_list.append(event_info)
>
> -def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
> +def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
> skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
> +def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
> skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
> +def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, dev_name)
> all_event_list.append(event_info)
>
> -def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
> +def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen, rc, dev_name):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen, rc ,dev_name)
> all_event_list.append(event_info)
>
> -def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
> +def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, protocol, location):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, protocol, location)
> all_event_list.append(event_info)
>
> -def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
> +def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr)
> all_event_list.append(event_info)
>
> -def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
> +def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
> skbaddr, skblen):
> event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
> skbaddr, skblen)
> diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
> index 74d55ec..de66cb3 100644
> --- a/tools/perf/scripts/python/sched-migration.py
> +++ b/tools/perf/scripts/python/sched-migration.py
> @@ -369,93 +369,92 @@ def trace_end():
>
> def sched__sched_stat_runtime(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, runtime, vruntime):
> + common_callchain, comm, pid, runtime, vruntime):
> pass
>
> def sched__sched_stat_iowait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_stat_sleep(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_stat_wait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, delay):
> + common_callchain, comm, pid, delay):
> pass
>
> def sched__sched_process_fork(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - parent_comm, parent_pid, child_comm, child_pid):
> + common_callchain, parent_comm, parent_pid, child_comm, child_pid):
> pass
>
> def sched__sched_process_wait(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_process_exit(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_process_free(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_migrate_task(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, orig_cpu,
> + common_callchain, comm, pid, prio, orig_cpu,
> dest_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
>
> def sched__sched_switch(event_name, context, common_cpu,
> - common_secs, common_nsecs, common_pid, common_comm,
> + common_secs, common_nsecs, common_pid, common_comm, common_callchain,
> prev_comm, prev_pid, prev_prio, prev_state,
> next_comm, next_pid, next_prio):
>
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
> next_comm, next_pid, next_prio)
>
> def sched__sched_wakeup_new(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, success,
> + common_callchain, comm, pid, prio, success,
> target_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.wake_up(headers, comm, pid, success, target_cpu, 1)
>
> def sched__sched_wakeup(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio, success,
> + common_callchain, comm, pid, prio, success,
> target_cpu):
> headers = EventHeaders(common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm)
> + common_pid, common_comm, common_callchain)
> parser.wake_up(headers, comm, pid, success, target_cpu, 0)
>
> def sched__sched_wait_task(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid, prio):
> + common_callchain, comm, pid, prio):
> pass
>
> def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - ret):
> + common_callchain, ret):
> pass
>
> def sched__sched_kthread_stop(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - comm, pid):
> + common_callchain, comm, pid):
> pass
>
> -def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
> - common_pid, common_comm):
> +def trace_unhandled(event_name, context, event_fields_dict):
> pass
> diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
> index c9f3058..61621b9 100644
> --- a/tools/perf/scripts/python/sctop.py
> +++ b/tools/perf/scripts/python/sctop.py
> @@ -44,7 +44,7 @@ def trace_begin():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
> if for_comm is not None:
> if common_comm != for_comm:
> return
> diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
> index cf2054c..daf314c 100644
> --- a/tools/perf/scripts/python/syscall-counts-by-pid.py
> +++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
> @@ -38,7 +38,7 @@ def trace_end():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
>
> if (for_comm and common_comm != for_comm) or \
> (for_pid and common_pid != for_pid ):
> diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
> index 92b2938..e66a773 100644
> --- a/tools/perf/scripts/python/syscall-counts.py
> +++ b/tools/perf/scripts/python/syscall-counts.py
> @@ -35,7 +35,7 @@ def trace_end():
>
> def raw_syscalls__sys_enter(event_name, context, common_cpu,
> common_secs, common_nsecs, common_pid, common_comm,
> - id, args):
> + common_callchain, id, args):
> if for_comm is not None:
> if common_comm != for_comm:
> return
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index 631aa85..dae78e4 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -32,6 +32,7 @@
> #include "../event.h"
> #include "../thread.h"
> #include "../trace-event.h"
> +#include "../machine.h"
>
> PyMODINIT_FUNC initperf_trace_context(void);
>
> @@ -237,12 +238,90 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
> return event;
> }
>
> +
> +static PyObject *python_process_callchain(struct perf_sample *sample,
> + struct perf_evsel *evsel,
> + struct addr_location *al)
> +{
> + PyObject *pylist;
> +
> + pylist = PyList_New(0);
> + if (!pylist)
> + Py_FatalError("couldn't create Python list");
> +
> + if (!symbol_conf.use_callchain || !sample->callchain)
> + goto exit;
> +
> + if (machine__resolve_callchain(al->machine, evsel, al->thread,
> + sample, NULL, NULL,
> + PERF_MAX_STACK_DEPTH) != 0) {
> + pr_err("Failed to resolve callchain. Skipping\n");
> + goto exit;
> + }
> + callchain_cursor_commit(&callchain_cursor);
> +
> +
> + while (1) {
> + PyObject *pyelem;
> + struct callchain_cursor_node *node;
> + node = callchain_cursor_current(&callchain_cursor);
> + if (!node)
> + break;
> +
> + pyelem = PyDict_New();
> + if (!pyelem)
> + Py_FatalError("couldn't create Python dictionary");
> +
> +
> + pydict_set_item_string_decref(pyelem, "ip",
> + PyLong_FromUnsignedLongLong(node->ip));
> +
> + if (node->sym) {
> + PyObject *pysym = PyDict_New();
> + if (!pysym)
> + Py_FatalError("couldn't create Python dictionary");
> + pydict_set_item_string_decref(pysym, "start",
> + PyLong_FromUnsignedLongLong(node->sym->start));
> + pydict_set_item_string_decref(pysym, "end",
> + PyLong_FromUnsignedLongLong(node->sym->end));
> + pydict_set_item_string_decref(pysym, "binding",
> + PyInt_FromLong(node->sym->binding));
> + pydict_set_item_string_decref(pysym, "name",
> + PyString_FromStringAndSize(node->sym->name,
> + node->sym->namelen));
> + pydict_set_item_string_decref(pyelem, "sym", pysym);
> + }
> +
> + if (node->map) {
> + struct map *map = node->map;
> + const char *dsoname = "[unknown]";
> + if (map && map->dso && (map->dso->name || map->dso->long_name)) {
> + if (symbol_conf.show_kernel_path && map->dso->long_name)
> + dsoname = map->dso->long_name;
> + else if (map->dso->name)
> + dsoname = map->dso->name;
> + }
> + pydict_set_item_string_decref(pyelem, "dso",
> + PyString_FromString(dsoname));
> + }
> +
> + callchain_cursor_advance(&callchain_cursor);
> + PyList_Append(pylist, pyelem);
> + Py_DECREF(pyelem);
> + }
> +
> +exit:
> + return pylist;
> +}
> +
> +
> static void python_process_tracepoint(struct perf_sample *sample,
> struct perf_evsel *evsel,
> struct thread *thread,
> struct addr_location *al)
> {
> - PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
> + PyObject *handler, *retval, *context, *t, *obj, *callchain;
> + PyObject *dict = NULL;
> static char handler_name[256];
> struct format_field *field;
> unsigned long long val;
> @@ -286,18 +365,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
> PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
> PyTuple_SetItem(t, n++, context);
>
> + /* ip unwinding */
> + callchain = python_process_callchain(sample, evsel, al);
> +
> if (handler) {
> PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
> PyTuple_SetItem(t, n++, PyInt_FromLong(s));
> PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
> PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
> PyTuple_SetItem(t, n++, PyString_FromString(comm));
> + PyTuple_SetItem(t, n++, callchain);
> } else {
> pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
> pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
> pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
> pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
> pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
> + pydict_set_item_string_decref(dict, "common_callchain", callchain);
> }
> for (field = event->format.fields; field; field = field->next) {
> if (field->flags & FIELD_IS_STRING) {
> @@ -330,6 +414,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> pydict_set_item_string_decref(dict, field->name, obj);
>
> }
> +
> if (!handler)
> PyTuple_SetItem(t, n++, dict);
>
> @@ -361,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
> struct thread *thread,
> struct addr_location *al)
> {
> - PyObject *handler, *retval, *t, *dict;
> + PyObject *handler, *retval, *t, *dict, *callchain;
> static char handler_name[64];
> unsigned n = 0;
>
> @@ -401,6 +486,10 @@ static void python_process_general_event(struct perf_sample *sample,
> PyString_FromString(al->sym->name));
> }
>
> + /* ip unwinding */
> + callchain = python_process_callchain(sample, evsel, al);
> + pydict_set_item_string_decref(dict, "callchain", callchain);
> +
> PyTuple_SetItem(t, n++, dict);
> if (_PyTuple_Resize(&t, n) == -1)
> Py_FatalError("error resizing Python tuple");
> @@ -597,6 +686,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "common_nsecs, ");
> fprintf(ofp, "common_pid, ");
> fprintf(ofp, "common_comm,\n\t");
> + fprintf(ofp, "common_callchain, ");
>
> not_first = 0;
> count = 0;
> @@ -640,7 +730,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "%%u");
> }
>
> - fprintf(ofp, "\\n\" %% \\\n\t\t(");
> + fprintf(ofp, "\" %% \\\n\t\t(");
>
> not_first = 0;
> count = 0;
> @@ -676,7 +766,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
> fprintf(ofp, "%s", f->name);
> }
>
> - fprintf(ofp, "),\n\n");
> + fprintf(ofp, ")\n\n");
> +
> + fprintf(ofp, "\t\tfor node in common_callchain:");
> + fprintf(ofp, "\n\t\t\tif 'sym' in node:");
> + fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
> + fprintf(ofp, "\n\t\t\telse:");
> + fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
> + fprintf(ofp, "\t\tprint \"\\n\"\n\n");
> +
> }
>
> fprintf(ofp, "def trace_unhandled(event_name, context, "

2014-07-09 08:16:12

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 3/3] perf script: Provide additional sample information on generic events

On Wed, 09 Jul 2014 09:40:36 +0200, Joseph Schuchart wrote:
> [PATCH 3/3] perf script: Provide additional sample information on
> generic events to Python scripts, including pid, tid, and cpu for which the
> event was recorded. At the moment, the pointer to the sample struct is
> passed to scripts, which seems to be of little use. The patch puts this
> information in dictionaries for easy access by Python scripts.
>
> Signed-off-by: Joseph Schuchart <[email protected]>
> Acked-by: Thomas Ilsche <[email protected]>

Acked-by: Namhyung Kim <[email protected]>

Thanks,
Namhyung


> ---
> .../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++---
> 1 file changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index dae78e4..64923cd 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -446,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
> struct thread *thread,
> struct addr_location *al)
> {
> - PyObject *handler, *retval, *t, *dict, *callchain;
> + PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
> static char handler_name[64];
> unsigned n = 0;
>
> @@ -462,6 +462,10 @@ static void python_process_general_event(struct perf_sample *sample,
> if (!dict)
> Py_FatalError("couldn't create Python dictionary");
>
> + dict_sample = PyDict_New();
> + if (!dict_sample)
> + Py_FatalError("couldn't create Python dictionary");
> +
> snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
>
> handler = PyDict_GetItemString(main_dict, handler_name);
> @@ -471,8 +475,21 @@ static void python_process_general_event(struct perf_sample *sample,
> pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
> pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
> (const char *)&evsel->attr, sizeof(evsel->attr)));
> - pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
> - (const char *)sample, sizeof(*sample)));
> +
> + pydict_set_item_string_decref(dict_sample, "pid",
> + PyInt_FromLong(sample->pid));
> + pydict_set_item_string_decref(dict_sample, "tid",
> + PyInt_FromLong(sample->tid));
> + pydict_set_item_string_decref(dict_sample, "cpu",
> + PyInt_FromLong(sample->cpu));
> + pydict_set_item_string_decref(dict_sample, "ip",
> + PyLong_FromUnsignedLongLong(sample->ip));
> + pydict_set_item_string_decref(dict_sample, "time",
> + PyLong_FromUnsignedLongLong(sample->time));
> + pydict_set_item_string_decref(dict_sample, "period",
> + PyLong_FromUnsignedLongLong(sample->period));
> + pydict_set_item_string_decref(dict, "sample", dict_sample);
> +
> pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
> (const char *)sample->raw_data, sample->raw_size));
> pydict_set_item_string_decref(dict, "comm",

2014-07-09 11:27:46

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

On Wed, Jul 09, 2014 at 09:40:34AM +0200, Joseph Schuchart wrote:
> [PATCH 2/3] perf script: Add callchain to generic and tracepoint events. Since
> this alters the interface for the python scripts, also adjust the script
> generation and the provided scripts.

still having issues to apply 2nd patch on tip/perf/core (8b5b584)

Applying: perf script: Add missing calls to Py_DECREF for return values
Applying: perf script: Add callchain to generic and tracepoint events
error: patch failed: tools/perf/util/scripting-engines/trace-event-python.c:237
error: tools/perf/util/scripting-engines/trace-event-python.c: patch does not apply
Patch failed at 0002 perf script: Add callchain to generic and tracepoint events
The copy of the patch that failed is found in:
/home/jolsa/kernel.org/linux-perf/.git/rebase-apply/patch
When you have resolved this problem, run "git am --resolved".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".


thanks,
jirka

2014-07-09 11:43:35

by Joseph Schuchart

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Jirka,

I tried to apply the patches to the latest version of the perf/core branch before sending. Can you please send me some more information about the conflict?

Thanks
Joseph



On 09.07.2014 13:27, Jiri Olsa wrote:
> On Wed, Jul 09, 2014 at 09:40:34AM +0200, Joseph Schuchart wrote:
>> [PATCH 2/3] perf script: Add callchain to generic and tracepoint events. Since
>> this alters the interface for the python scripts, also adjust the script
>> generation and the provided scripts.
>
> still having issues to apply 2nd patch on tip/perf/core (8b5b584)
>
> Applying: perf script: Add missing calls to Py_DECREF for return values
> Applying: perf script: Add callchain to generic and tracepoint events
> error: patch failed: tools/perf/util/scripting-engines/trace-event-python.c:237
> error: tools/perf/util/scripting-engines/trace-event-python.c: patch does not apply
> Patch failed at 0002 perf script: Add callchain to generic and tracepoint events
> The copy of the patch that failed is found in:
> /home/jolsa/kernel.org/linux-perf/.git/rebase-apply/patch
> When you have resolved this problem, run "git am --resolved".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
>
>
> thanks,
> jirka
>

--
Dipl. Inf. Joseph Schuchart
Computer Scientist

Technische Universit?t Dresden
Center for Information Services and High Performance Computing (ZIH)
01062 Dresden, Germany

Phone: +49 351 463-36494
Fax: +49 351 463-3773
E-Mail: [email protected]


Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 11:49:25

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

On Wed, Jul 09, 2014 at 01:43:18PM +0200, Joseph Schuchart wrote:
> Jirka,
>
> I tried to apply the patches to the latest version of the perf/core branch before sending. Can you please send me some more information about the conflict?

is your HEAD 8b5b584 ?

[jolsa@krava perf]$ git show --oneline tip/perf/core
8b5b584 Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core

jirka

2014-07-09 14:16:48

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 1/3] perf script: Add missing calls to Py_DECREF


perf script: Add missing calls to Py_DECREF for return values

Signed-off-by: Joseph Schuchart <[email protected]>
---
tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index e55b65a..b6c1a69 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -50,10 +50,14 @@ static int zero_flag_atom;

static PyObject *main_module, *main_dict;

+static void handler_call_die(const char *handler_name) NORETURN;
static void handler_call_die(const char *handler_name)
{
PyErr_Print();
Py_FatalError("problem in Python trace event handler");
+ // Py_FatalError does not return
+ // but we have to make the compiler happy
+ abort();
}

/*
@@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -361,6 +367,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
} else {
handler = PyDict_GetItemString(main_dict, "trace_unhandled");
if (handler && PyCallable_Check(handler)) {
@@ -368,6 +375,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die("trace_unhandled");
+ Py_DECREF(retval);
}
Py_DECREF(dict);
}
@@ -427,6 +435,7 @@ static void python_process_general_event(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
exit:
Py_DECREF(dict);
Py_DECREF(t);
@@ -548,8 +557,7 @@ static int python_stop_script(void)
retval = PyObject_CallObject(handler, NULL);
if (retval == NULL)
handler_call_die("trace_end");
- else
- Py_DECREF(retval);
+ Py_DECREF(retval);
out:
Py_XDECREF(main_dict);
Py_XDECREF(main_module);
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 14:16:56

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events


perf script: Add callchain to generic and tracepoint events. Since
this alters the interface for the python scripts, also adjust the script
generation and the provided scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
tools/perf/scripts/python/check-perf-trace.py | 4 +-
.../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
tools/perf/scripts/python/futex-contention.py | 4 +-
tools/perf/scripts/python/net_dropmonitor.py | 2 +-
tools/perf/scripts/python/netdev-times.py | 26 ++---
tools/perf/scripts/python/sched-migration.py | 41 ++++----
tools/perf/scripts/python/sctop.py | 2 +-
tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
tools/perf/scripts/python/syscall-counts.py | 2 +-
.../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
11 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e..38dfb72 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):

class EventHeaders:
def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+ common_pid, common_comm, common_callchain):
self.cpu = common_cpu
self.secs = common_secs
self.nsecs = common_nsecs
self.pid = common_pid
self.comm = common_comm
+ self.callchain = common_callchain

def ts(self):
return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a76..334599c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():

def irq__softirq_entry(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- vec):
+ common_callchain, vec):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)

@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,

def kmem__kmalloc(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- call_site, ptr, bytes_req, bytes_alloc,
+ common_callchain, call_site, ptr, bytes_req, bytes_alloc,
gfp_flags):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 266a836..cafeff3 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():

def raw_syscalls__sys_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
+ common_callchain, id, ret):
if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a3..0f5cf43 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
process_names = {} # long-lived pid-to-execname mapping

-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, uaddr, op, val, utime, uaddr2, val3):
cmd = op & FUTEX_CMD_MASK
if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
thread_thislock[tid] = uaddr
thread_blocktime[tid] = nsecs(s, ns)

-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, ret):
if thread_blocktime.has_key(tid):
elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b574059..0b6ce8c 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
print_drop_table()

# called from perf, when it finds a correspoinding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, location, protocol):
slocation = str(location)
try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32..4d21ef2 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
(len(rx_skb_list), of_count_rx_skb_list)

# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- irq, irq_name):
+ callchain, irq, irq_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
irq, irq_name)
all_event_list.append(event_info)

-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
all_event_list.append(event_info)

-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
napi, dev_name)
all_event_list.append(event_info)

-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, rc, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, rc ,dev_name)
all_event_list.append(event_info)

-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, protocol, location):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, protocol, location)
all_event_list.append(event_info)

-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr)
all_event_list.append(event_info)

-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec..de66cb3 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():

def sched__sched_stat_runtime(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, runtime, vruntime):
+ common_callchain, comm, pid, runtime, vruntime):
pass

def sched__sched_stat_iowait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_sleep(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_process_fork(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- parent_comm, parent_pid, child_comm, child_pid):
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
pass

def sched__sched_process_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_free(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_migrate_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, orig_cpu,
+ common_callchain, comm, pid, prio, orig_cpu,
dest_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)

def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
+ common_secs, common_nsecs, common_pid, common_comm, common_callchain,
prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio):

headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio)

def sched__sched_wakeup_new(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 1)

def sched__sched_wakeup(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 0)

def sched__sched_wait_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- ret):
+ common_callchain, ret):
pass

def sched__sched_kthread_stop(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid):
+ common_callchain, comm, pid):
pass

-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index c9f3058..61621b9 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index cf2054c..daf314c 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):

if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index 92b2938..e66a773 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 631aa85..dae78e4 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
+#include "../machine.h"

PyMODINIT_FUNC initperf_trace_context(void);

@@ -237,12 +238,90 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
return event;
}

+
+static PyObject *python_process_callchain(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al)
+{
+ PyObject *pylist;
+
+ pylist = PyList_New(0);
+ if (!pylist)
+ Py_FatalError("couldn't create Python list");
+
+ if (!symbol_conf.use_callchain || !sample->callchain)
+ goto exit;
+
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
+ sample, NULL, NULL,
+ PERF_MAX_STACK_DEPTH) != 0) {
+ pr_err("Failed to resolve callchain. Skipping\n");
+ goto exit;
+ }
+ callchain_cursor_commit(&callchain_cursor);
+
+
+ while (1) {
+ PyObject *pyelem;
+ struct callchain_cursor_node *node;
+ node = callchain_cursor_current(&callchain_cursor);
+ if (!node)
+ break;
+
+ pyelem = PyDict_New();
+ if (!pyelem)
+ Py_FatalError("couldn't create Python dictionary");
+
+
+ pydict_set_item_string_decref(pyelem, "ip",
+ PyLong_FromUnsignedLongLong(node->ip));
+
+ if (node->sym) {
+ PyObject *pysym = PyDict_New();
+ if (!pysym)
+ Py_FatalError("couldn't create Python dictionary");
+ pydict_set_item_string_decref(pysym, "start",
+ PyLong_FromUnsignedLongLong(node->sym->start));
+ pydict_set_item_string_decref(pysym, "end",
+ PyLong_FromUnsignedLongLong(node->sym->end));
+ pydict_set_item_string_decref(pysym, "binding",
+ PyInt_FromLong(node->sym->binding));
+ pydict_set_item_string_decref(pysym, "name",
+ PyString_FromStringAndSize(node->sym->name,
+ node->sym->namelen));
+ pydict_set_item_string_decref(pyelem, "sym", pysym);
+ }
+
+ if (node->map) {
+ struct map *map = node->map;
+ const char *dsoname = "[unknown]";
+ if (map && map->dso && (map->dso->name || map->dso->long_name)) {
+ if (symbol_conf.show_kernel_path && map->dso->long_name)
+ dsoname = map->dso->long_name;
+ else if (map->dso->name)
+ dsoname = map->dso->name;
+ }
+ pydict_set_item_string_decref(pyelem, "dso",
+ PyString_FromString(dsoname));
+ }
+
+ callchain_cursor_advance(&callchain_cursor);
+ PyList_Append(pylist, pyelem);
+ Py_DECREF(pyelem);
+ }
+
+exit:
+ return pylist;
+}
+
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
+ PyObject *handler, *retval, *context, *t, *obj, *callchain;
+ PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long long val;
@@ -286,18 +365,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
+ pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@@ -330,6 +414,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);

}
+
if (!handler)
PyTuple_SetItem(t, n++, dict);

@@ -361,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict;
+ PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;

@@ -401,6 +486,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@@ -597,6 +686,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
+ fprintf(ofp, "common_callchain, ");

not_first = 0;
count = 0;
@@ -640,7 +730,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}

- fprintf(ofp, "\\n\" %% \\\n\t\t(");
+ fprintf(ofp, "\" %% \\\n\t\t(");

not_first = 0;
count = 0;
@@ -676,7 +766,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}

- fprintf(ofp, "),\n\n");
+ fprintf(ofp, ")\n\n");
+
+ fprintf(ofp, "\t\tfor node in common_callchain:");
+ fprintf(ofp, "\n\t\t\tif 'sym' in node:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
+ fprintf(ofp, "\n\t\t\telse:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
+ fprintf(ofp, "\t\tprint \"\\n\"\n\n");
+
}

fprintf(ofp, "def trace_unhandled(event_name, context, "
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 14:16:54

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 3/3] perf script: Provide additional sample information on generic events


perf script: Provide additional sample information on
generic events to Python scripts, including pid, tid, and cpu for which the
event was recorded. At the moment, the pointer to the sample struct is
passed to scripts, which seems to be of little use. The patch puts this
information in dictionaries for easy access by Python scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index dae78e4..64923cd 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -446,7 +446,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict, *callchain;
+ PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
static char handler_name[64];
unsigned n = 0;

@@ -462,6 +462,10 @@ static void python_process_general_event(struct perf_sample *sample,
if (!dict)
Py_FatalError("couldn't create Python dictionary");

+ dict_sample = PyDict_New();
+ if (!dict_sample)
+ Py_FatalError("couldn't create Python dictionary");
+
snprintf(handler_name, sizeof(handler_name), "%s", "process_event");

handler = PyDict_GetItemString(main_dict, handler_name);
@@ -471,8 +475,21 @@ static void python_process_general_event(struct perf_sample *sample,
pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)&evsel->attr, sizeof(evsel->attr)));
- pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
- (const char *)sample, sizeof(*sample)));
+
+ pydict_set_item_string_decref(dict_sample, "pid",
+ PyInt_FromLong(sample->pid));
+ pydict_set_item_string_decref(dict_sample, "tid",
+ PyInt_FromLong(sample->tid));
+ pydict_set_item_string_decref(dict_sample, "cpu",
+ PyInt_FromLong(sample->cpu));
+ pydict_set_item_string_decref(dict_sample, "ip",
+ PyLong_FromUnsignedLongLong(sample->ip));
+ pydict_set_item_string_decref(dict_sample, "time",
+ PyLong_FromUnsignedLongLong(sample->time));
+ pydict_set_item_string_decref(dict_sample, "period",
+ PyLong_FromUnsignedLongLong(sample->period));
+ pydict_set_item_string_decref(dict, "sample", dict_sample);
+
pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
(const char *)sample->raw_data, sample->raw_size));
pydict_set_item_string_decref(dict, "comm",
--
1.8.1.2



Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 14:16:42

by Joseph Schuchart

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Ok, with the help of a colleague with some more expertise on git than I have, we finally figured out which branch you mean with tip/perf/core. Sorry for the confusion! The conflict was trivial to solve, I will send the rebased patches separately.

Joseph

On 09.07.2014 13:49, Jiri Olsa wrote:
> On Wed, Jul 09, 2014 at 01:43:18PM +0200, Joseph Schuchart wrote:
>> Jirka,
>>
>> I tried to apply the patches to the latest version of the perf/core branch before sending. Can you please send me some more information about the conflict?
>
> is your HEAD 8b5b584 ?
>
> [jolsa@krava perf]$ git show --oneline tip/perf/core
> 8b5b584 Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core
>
> jirka
>

--
Dipl. Inf. Joseph Schuchart
Computer Scientist

Technische Universit?t Dresden
Center for Information Services and High Performance Computing (ZIH)
01062 Dresden, Germany

Phone: +49 351 463-36494
Fax: +49 351 463-3773
E-Mail: [email protected]


Attachments:
smime.p7s (4.90 kB)
S/MIME Cryptographic Signature

2014-07-09 19:07:26

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 1/3] perf script: Add missing calls to Py_DECREF

Em Wed, Jul 09, 2014 at 04:16:31PM +0200, Joseph Schuchart escreveu:
>
> perf script: Add missing calls to Py_DECREF for return values

I'm applying this one, but please next time write a few lines explaining
what happens without the patch and thus what it fixes, i.e. why is a
Py_DECREF needed in this case?

- Arnaldo

> Signed-off-by: Joseph Schuchart <[email protected]>
> ---
> tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++--
> 1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
> index e55b65a..b6c1a69 100644
> --- a/tools/perf/util/scripting-engines/trace-event-python.c
> +++ b/tools/perf/util/scripting-engines/trace-event-python.c
> @@ -50,10 +50,14 @@ static int zero_flag_atom;
>
> static PyObject *main_module, *main_dict;
>
> +static void handler_call_die(const char *handler_name) NORETURN;
> static void handler_call_die(const char *handler_name)
> {
> PyErr_Print();
> Py_FatalError("problem in Python trace event handler");
> + // Py_FatalError does not return
> + // but we have to make the compiler happy
> + abort();
> }
>
> /*
> @@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> }
>
> Py_DECREF(t);
> @@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> }
>
> Py_DECREF(t);
> @@ -361,6 +367,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> } else {
> handler = PyDict_GetItemString(main_dict, "trace_unhandled");
> if (handler && PyCallable_Check(handler)) {
> @@ -368,6 +375,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die("trace_unhandled");
> + Py_DECREF(retval);
> }
> Py_DECREF(dict);
> }
> @@ -427,6 +435,7 @@ static void python_process_general_event(struct perf_sample *sample,
> retval = PyObject_CallObject(handler, t);
> if (retval == NULL)
> handler_call_die(handler_name);
> + Py_DECREF(retval);
> exit:
> Py_DECREF(dict);
> Py_DECREF(t);
> @@ -548,8 +557,7 @@ static int python_stop_script(void)
> retval = PyObject_CallObject(handler, NULL);
> if (retval == NULL)
> handler_call_die("trace_end");
> - else
> - Py_DECREF(retval);
> + Py_DECREF(retval);
> out:
> Py_XDECREF(main_dict);
> Py_XDECREF(main_module);
> --
> 1.8.1.2
>
>

2014-07-09 19:09:28

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Em Wed, Jul 09, 2014 at 04:16:33PM +0200, Joseph Schuchart escreveu:
>
> perf script: Add callchain to generic and tracepoint events. Since
> this alters the interface for the python scripts, also adjust the script
> generation and the provided scripts.
>
> Signed-off-by: Joseph Schuchart <[email protected]>
> Acked-by: Thomas Ilsche <[email protected]>

This one is not applying, I'm checking the reason for its malformation
as stated in:


[acme@ssdandy linux]$ patch -p1 < /wb/1.patch
patching file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
Hunk #1 FAILED at 107.
1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py.rej
patching file tools/perf/scripts/python/check-perf-trace.py
Hunk #1 succeeded at 27 with fuzz 1.
Hunk #2 succeeded at 37 with fuzz 2 (offset -1 lines).
patching file tools/perf/scripts/python/failed-syscalls-by-pid.py
Hunk #1 FAILED at 39.
1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/failed-syscalls-by-pid.py.rej
patching file tools/perf/scripts/python/futex-contention.py
patch: **** malformed patch at line 154: ain,

[acme@ssdandy linux]$

2014-07-09 19:12:29

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Em Wed, Jul 09, 2014 at 04:09:21PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Jul 09, 2014 at 04:16:33PM +0200, Joseph Schuchart escreveu:
> >
> > perf script: Add callchain to generic and tracepoint events. Since
> > this alters the interface for the python scripts, also adjust the script
> > generation and the provided scripts.
> >
> > Signed-off-by: Joseph Schuchart <[email protected]>
> > Acked-by: Thomas Ilsche <[email protected]>
>
> This one is not applying, I'm checking the reason for its malformation
> as stated in:
>
>
> [acme@ssdandy linux]$ patch -p1 < /wb/1.patch
> patching file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> Hunk #1 FAILED at 107.
> 1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py.rej
> patching file tools/perf/scripts/python/check-perf-trace.py
> Hunk #1 succeeded at 27 with fuzz 1.
> Hunk #2 succeeded at 37 with fuzz 2 (offset -1 lines).
> patching file tools/perf/scripts/python/failed-syscalls-by-pid.py
> Hunk #1 FAILED at 39.
> 1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/failed-syscalls-by-pid.py.rej
> patching file tools/perf/scripts/python/futex-contention.py
> patch: **** malformed patch at line 154: ain,

It is full of:

self.cpu =3D common_cpu
self.secs =3D common_secs
self.nsecs =3D common_nsecs
self.pid =3D common_pid
self.comm =3D common_comm
+ self.callchain =3D common_callchain
=20
def ts(self):


See those =20, =3D? Some encoding problem...

So you used:

User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0

Please read the Thunderbird specific part of this page:

https://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html

- Arnaldo

2014-07-09 19:29:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Em Wed, Jul 09, 2014 at 04:12:23PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Jul 09, 2014 at 04:09:21PM -0300, Arnaldo Carvalho de Melo escreveu:
> > Em Wed, Jul 09, 2014 at 04:16:33PM +0200, Joseph Schuchart escreveu:

> > This one is not applying, I'm checking the reason for its malformation
> > as stated in:

> > [acme@ssdandy linux]$ patch -p1 < /wb/1.patch
> > patching file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
> > Hunk #1 FAILED at 107.
> > 1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py.rej
> > patching file tools/perf/scripts/python/check-perf-trace.py
> > Hunk #1 succeeded at 27 with fuzz 1.
> > Hunk #2 succeeded at 37 with fuzz 2 (offset -1 lines).
> > patching file tools/perf/scripts/python/failed-syscalls-by-pid.py
> > Hunk #1 FAILED at 39.
> > 1 out of 1 hunk FAILED -- saving rejects to file tools/perf/scripts/python/failed-syscalls-by-pid.py.rej
> > patching file tools/perf/scripts/python/futex-contention.py
> > patch: **** malformed patch at line 154: ain,

> It is full of:

> self.cpu =3D common_cpu

Ok, I applied the first patch on this series, please see my perf/core
branch at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git

You can have it with:

git remote add acme git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
git checkout -b perf/core acme/perf/core

Then please create the patches and follow the instructions about
Thunderbird at:

https://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html

So that it doesn't mangles the patch and resend, ok?

- Arnaldo

2014-07-10 11:51:03

by Joseph Schuchart

[permalink] [raw]
Subject: Re: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events

Arnaldo,

On 09.07.2014 21:29, Arnaldo Carvalho de Melo wrote:
> Em Wed, Jul 09, 2014 at 04:12:23PM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Wed, Jul 09, 2014 at 04:09:21PM -0300, Arnaldo Carvalho de Melo escreveu:
>
>> It is full of:
>
>> self.cpu =3D common_cpu
>
> Ok, I applied the first patch on this series, please see my perf/core
> branch at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
>
> You can have it with:
>
> git remote add acme git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git
> git checkout -b perf/core acme/perf/core
>
> Then please create the patches and follow the instructions about
> Thunderbird at:
>
> https://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html
>
> So that it doesn't mangles the patch and resend, ok?

Thanks for figuring out what the problem was, the patches looked fine when I checked them in my outbox. I had Thunderbird set up according to the documentation you mentioned. However, after some testing I found out what went wrong on my side: we have the policy at work to sign all of our emails using s/mime so I have TB set up to do this by default. This seems to mangle the emails and there is no way to notice that in Thunderbird because it automatically removes the mangling when displaying signed mails. Lesson learned, again sorry for all the trouble! I will resend the patches based on the current perf/core and be more careful next time.

Thanks
Joseph

>
> - Arnaldo
>

2014-07-10 11:51:16

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 2/3] perf script: Add callchain to generic and tracepoint events


perf script: Add callchain to generic and tracepoint events.
This provides valuable information for tracing performance problems.
Since this change alters the interface for the python scripts,
also adjust the script generation and the provided scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
tools/perf/scripts/python/check-perf-trace.py | 4 +-
.../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
tools/perf/scripts/python/futex-contention.py | 4 +-
tools/perf/scripts/python/net_dropmonitor.py | 2 +-
tools/perf/scripts/python/netdev-times.py | 26 ++---
tools/perf/scripts/python/sched-migration.py | 41 ++++----
tools/perf/scripts/python/sctop.py | 2 +-
tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
tools/perf/scripts/python/syscall-counts.py | 2 +-
.../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
11 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e..38dfb72 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):

class EventHeaders:
def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+ common_pid, common_comm, common_callchain):
self.cpu = common_cpu
self.secs = common_secs
self.nsecs = common_nsecs
self.pid = common_pid
self.comm = common_comm
+ self.callchain = common_callchain

def ts(self):
return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a76..334599c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():

def irq__softirq_entry(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- vec):
+ common_callchain, vec):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)

@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,

def kmem__kmalloc(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- call_site, ptr, bytes_req, bytes_alloc,
+ common_callchain, call_site, ptr, bytes_req, bytes_alloc,
gfp_flags):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 266a836..cafeff3 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():

def raw_syscalls__sys_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
+ common_callchain, id, ret):
if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a3..0f5cf43 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
process_names = {} # long-lived pid-to-execname mapping

-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, uaddr, op, val, utime, uaddr2, val3):
cmd = op & FUTEX_CMD_MASK
if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
thread_thislock[tid] = uaddr
thread_blocktime[tid] = nsecs(s, ns)

-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, ret):
if thread_blocktime.has_key(tid):
elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b574059..0b6ce8c 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
print_drop_table()

# called from perf, when it finds a correspoinding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, location, protocol):
slocation = str(location)
try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32..4d21ef2 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
(len(rx_skb_list), of_count_rx_skb_list)

# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- irq, irq_name):
+ callchain, irq, irq_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
irq, irq_name)
all_event_list.append(event_info)

-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
all_event_list.append(event_info)

-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
napi, dev_name)
all_event_list.append(event_info)

-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, rc, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, rc ,dev_name)
all_event_list.append(event_info)

-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, protocol, location):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, protocol, location)
all_event_list.append(event_info)

-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr)
all_event_list.append(event_info)

-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec..de66cb3 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():

def sched__sched_stat_runtime(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, runtime, vruntime):
+ common_callchain, comm, pid, runtime, vruntime):
pass

def sched__sched_stat_iowait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_sleep(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_process_fork(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- parent_comm, parent_pid, child_comm, child_pid):
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
pass

def sched__sched_process_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_free(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_migrate_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, orig_cpu,
+ common_callchain, comm, pid, prio, orig_cpu,
dest_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)

def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
+ common_secs, common_nsecs, common_pid, common_comm, common_callchain,
prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio):

headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio)

def sched__sched_wakeup_new(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 1)

def sched__sched_wakeup(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 0)

def sched__sched_wait_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- ret):
+ common_callchain, ret):
pass

def sched__sched_kthread_stop(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid):
+ common_callchain, comm, pid):
pass

-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index c9f3058..61621b9 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index cf2054c..daf314c 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):

if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index 92b2938..e66a773 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index b6c1a69..cf65404 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
+#include "../machine.h"

PyMODINIT_FUNC initperf_trace_context(void);

@@ -278,12 +279,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
return obj;
}

+
+static PyObject *python_process_callchain(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al)
+{
+ PyObject *pylist;
+
+ pylist = PyList_New(0);
+ if (!pylist)
+ Py_FatalError("couldn't create Python list");
+
+ if (!symbol_conf.use_callchain || !sample->callchain)
+ goto exit;
+
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
+ sample, NULL, NULL,
+ PERF_MAX_STACK_DEPTH) != 0) {
+ pr_err("Failed to resolve callchain. Skipping\n");
+ goto exit;
+ }
+ callchain_cursor_commit(&callchain_cursor);
+
+
+ while (1) {
+ PyObject *pyelem;
+ struct callchain_cursor_node *node;
+ node = callchain_cursor_current(&callchain_cursor);
+ if (!node)
+ break;
+
+ pyelem = PyDict_New();
+ if (!pyelem)
+ Py_FatalError("couldn't create Python dictionary");
+
+
+ pydict_set_item_string_decref(pyelem, "ip",
+ PyLong_FromUnsignedLongLong(node->ip));
+
+ if (node->sym) {
+ PyObject *pysym = PyDict_New();
+ if (!pysym)
+ Py_FatalError("couldn't create Python dictionary");
+ pydict_set_item_string_decref(pysym, "start",
+ PyLong_FromUnsignedLongLong(node->sym->start));
+ pydict_set_item_string_decref(pysym, "end",
+ PyLong_FromUnsignedLongLong(node->sym->end));
+ pydict_set_item_string_decref(pysym, "binding",
+ PyInt_FromLong(node->sym->binding));
+ pydict_set_item_string_decref(pysym, "name",
+ PyString_FromStringAndSize(node->sym->name,
+ node->sym->namelen));
+ pydict_set_item_string_decref(pyelem, "sym", pysym);
+ }
+
+ if (node->map) {
+ struct map *map = node->map;
+ const char *dsoname = "[unknown]";
+ if (map && map->dso && (map->dso->name || map->dso->long_name)) {
+ if (symbol_conf.show_kernel_path && map->dso->long_name)
+ dsoname = map->dso->long_name;
+ else if (map->dso->name)
+ dsoname = map->dso->name;
+ }
+ pydict_set_item_string_decref(pyelem, "dso",
+ PyString_FromString(dsoname));
+ }
+
+ callchain_cursor_advance(&callchain_cursor);
+ PyList_Append(pylist, pyelem);
+ Py_DECREF(pyelem);
+ }
+
+exit:
+ return pylist;
+}
+
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
+ PyObject *handler, *retval, *context, *t, *obj, *callchain;
+ PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -326,18 +405,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
+ pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@@ -357,6 +441,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);

}
+
if (!handler)
PyTuple_SetItem(t, n++, dict);

@@ -388,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict;
+ PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;

@@ -428,6 +513,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@@ -624,6 +713,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
+ fprintf(ofp, "common_callchain, ");

not_first = 0;
count = 0;
@@ -667,7 +757,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}

- fprintf(ofp, "\\n\" %% \\\n\t\t(");
+ fprintf(ofp, "\" %% \\\n\t\t(");

not_first = 0;
count = 0;
@@ -703,7 +793,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}

- fprintf(ofp, "),\n\n");
+ fprintf(ofp, ")\n\n");
+
+ fprintf(ofp, "\t\tfor node in common_callchain:");
+ fprintf(ofp, "\n\t\t\tif 'sym' in node:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
+ fprintf(ofp, "\n\t\t\telse:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
+ fprintf(ofp, "\t\tprint \"\\n\"\n\n");
+
}

fprintf(ofp, "def trace_unhandled(event_name, context, "
--
1.8.1.2

2014-07-10 11:51:21

by Joseph Schuchart

[permalink] [raw]
Subject: [PATCH 3/3] perf script: Provide additional sample information on generic events


perf script: Provide additional sample information on
generic events to Python scripts, including pid, tid, and cpu for which the
event was recorded. At the moment, the pointer to the sample struct is
passed to scripts, which seems to be of little use. The patch puts this
information in dictionaries for easy access by Python scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
---
.../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cf65404..b366b48 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -473,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict, *callchain;
+ PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
static char handler_name[64];
unsigned n = 0;

@@ -489,6 +489,10 @@ static void python_process_general_event(struct perf_sample *sample,
if (!dict)
Py_FatalError("couldn't create Python dictionary");

+ dict_sample = PyDict_New();
+ if (!dict_sample)
+ Py_FatalError("couldn't create Python dictionary");
+
snprintf(handler_name, sizeof(handler_name), "%s", "process_event");

handler = PyDict_GetItemString(main_dict, handler_name);
@@ -498,8 +502,21 @@ static void python_process_general_event(struct perf_sample *sample,
pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)&evsel->attr, sizeof(evsel->attr)));
- pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
- (const char *)sample, sizeof(*sample)));
+
+ pydict_set_item_string_decref(dict_sample, "pid",
+ PyInt_FromLong(sample->pid));
+ pydict_set_item_string_decref(dict_sample, "tid",
+ PyInt_FromLong(sample->tid));
+ pydict_set_item_string_decref(dict_sample, "cpu",
+ PyInt_FromLong(sample->cpu));
+ pydict_set_item_string_decref(dict_sample, "ip",
+ PyLong_FromUnsignedLongLong(sample->ip));
+ pydict_set_item_string_decref(dict_sample, "time",
+ PyLong_FromUnsignedLongLong(sample->time));
+ pydict_set_item_string_decref(dict_sample, "period",
+ PyLong_FromUnsignedLongLong(sample->period));
+ pydict_set_item_string_decref(dict, "sample", dict_sample);
+
pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
(const char *)sample->raw_data, sample->raw_size));
pydict_set_item_string_decref(dict, "comm",
--
1.8.1.2

Subject: [tip:perf/core] perf script: Add missing calls to Py_DECREF for return values

Commit-ID: 05f832e3a267d6e45d092595bdf9339d127ea137
Gitweb: http://git.kernel.org/tip/05f832e3a267d6e45d092595bdf9339d127ea137
Author: Joseph Schuchart <[email protected]>
AuthorDate: Wed, 9 Jul 2014 16:16:31 +0200
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 16 Jul 2014 17:57:33 -0300

perf script: Add missing calls to Py_DECREF for return values

Signed-off-by: Joseph Schuchart <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Ilsche <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/scripting-engines/trace-event-python.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index e55b65a..b6c1a69 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -50,10 +50,14 @@ static int zero_flag_atom;

static PyObject *main_module, *main_dict;

+static void handler_call_die(const char *handler_name) NORETURN;
static void handler_call_die(const char *handler_name)
{
PyErr_Print();
Py_FatalError("problem in Python trace event handler");
+ // Py_FatalError does not return
+ // but we have to make the compiler happy
+ abort();
}

/*
@@ -97,6 +101,7 @@ static void define_value(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -143,6 +148,7 @@ static void define_field(enum print_arg_type field_type,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
}

Py_DECREF(t);
@@ -361,6 +367,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
} else {
handler = PyDict_GetItemString(main_dict, "trace_unhandled");
if (handler && PyCallable_Check(handler)) {
@@ -368,6 +375,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die("trace_unhandled");
+ Py_DECREF(retval);
}
Py_DECREF(dict);
}
@@ -427,6 +435,7 @@ static void python_process_general_event(struct perf_sample *sample,
retval = PyObject_CallObject(handler, t);
if (retval == NULL)
handler_call_die(handler_name);
+ Py_DECREF(retval);
exit:
Py_DECREF(dict);
Py_DECREF(t);
@@ -548,8 +557,7 @@ static int python_stop_script(void)
retval = PyObject_CallObject(handler, NULL);
if (retval == NULL)
handler_call_die("trace_end");
- else
- Py_DECREF(retval);
+ Py_DECREF(retval);
out:
Py_XDECREF(main_dict);
Py_XDECREF(main_module);

Subject: [tip:perf/core] perf script: Add callchain to generic and tracepoint events

Commit-ID: 0f5f5bcd112292f14b75750dde7461463bb1c7bb
Gitweb: http://git.kernel.org/tip/0f5f5bcd112292f14b75750dde7461463bb1c7bb
Author: Joseph Schuchart <[email protected]>
AuthorDate: Thu, 10 Jul 2014 13:50:51 +0200
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 16 Jul 2014 17:57:33 -0300

perf script: Add callchain to generic and tracepoint events

This provides valuable information for tracing performance problems.

Since this change alters the interface for the python scripts, also
adjust the script generation and the provided scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Ilsche <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
.../python/Perf-Trace-Util/lib/Perf/Trace/Core.py | 3 +-
tools/perf/scripts/python/check-perf-trace.py | 4 +-
.../perf/scripts/python/failed-syscalls-by-pid.py | 2 +-
tools/perf/scripts/python/futex-contention.py | 4 +-
tools/perf/scripts/python/net_dropmonitor.py | 2 +-
tools/perf/scripts/python/netdev-times.py | 26 ++---
tools/perf/scripts/python/sched-migration.py | 41 ++++----
tools/perf/scripts/python/sctop.py | 2 +-
tools/perf/scripts/python/syscall-counts-by-pid.py | 2 +-
tools/perf/scripts/python/syscall-counts.py | 2 +-
.../util/scripting-engines/trace-event-python.c | 106 ++++++++++++++++++++-
11 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
index de7211e..38dfb72 100644
--- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -107,12 +107,13 @@ def taskState(state):

class EventHeaders:
def __init__(self, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+ common_pid, common_comm, common_callchain):
self.cpu = common_cpu
self.secs = common_secs
self.nsecs = common_nsecs
self.pid = common_pid
self.comm = common_comm
+ self.callchain = common_callchain

def ts(self):
return (self.secs * (10 ** 9)) + self.nsecs
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
index 4647a76..334599c 100644
--- a/tools/perf/scripts/python/check-perf-trace.py
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -27,7 +27,7 @@ def trace_end():

def irq__softirq_entry(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- vec):
+ common_callchain, vec):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)

@@ -38,7 +38,7 @@ def irq__softirq_entry(event_name, context, common_cpu,

def kmem__kmalloc(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- call_site, ptr, bytes_req, bytes_alloc,
+ common_callchain, call_site, ptr, bytes_req, bytes_alloc,
gfp_flags):
print_header(event_name, common_cpu, common_secs, common_nsecs,
common_pid, common_comm)
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
index 266a836..cafeff3 100644
--- a/tools/perf/scripts/python/failed-syscalls-by-pid.py
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -39,7 +39,7 @@ def trace_end():

def raw_syscalls__sys_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, ret):
+ common_callchain, id, ret):
if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
return
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
index 11e70a3..0f5cf43 100644
--- a/tools/perf/scripts/python/futex-contention.py
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -21,7 +21,7 @@ thread_blocktime = {}
lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
process_names = {} # long-lived pid-to-execname mapping

-def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, uaddr, op, val, utime, uaddr2, val3):
cmd = op & FUTEX_CMD_MASK
if cmd != FUTEX_WAIT:
@@ -31,7 +31,7 @@ def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
thread_thislock[tid] = uaddr
thread_blocktime[tid] = nsecs(s, ns)

-def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, callchain,
nr, ret):
if thread_blocktime.has_key(tid):
elapsed = nsecs(s, ns) - thread_blocktime[tid]
diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py
index b574059..0b6ce8c 100755
--- a/tools/perf/scripts/python/net_dropmonitor.py
+++ b/tools/perf/scripts/python/net_dropmonitor.py
@@ -66,7 +66,7 @@ def trace_end():
print_drop_table()

# called from perf, when it finds a correspoinding event
-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, location, protocol):
slocation = str(location)
try:
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 9aa0a32..4d21ef2 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -224,75 +224,75 @@ def trace_end():
(len(rx_skb_list), of_count_rx_skb_list)

# called from perf, when it finds a correspoinding event
-def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

-def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
+def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, callchain, vec):
if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
return
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
all_event_list.append(event_info)

def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
- irq, irq_name):
+ callchain, irq, irq_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
irq, irq_name)
all_event_list.append(event_info)

-def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
+def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, irq, ret):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
all_event_list.append(event_info)

-def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
+def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
napi, dev_name)
all_event_list.append(event_info)

-def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
+def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, dev_name)
all_event_list.append(event_info)

-def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
+def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen, rc, dev_name):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen, rc ,dev_name)
all_event_list.append(event_info)

-def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
+def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, protocol, location):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, protocol, location)
all_event_list.append(event_info)

-def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
+def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr)
all_event_list.append(event_info)

-def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
+def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm, callchain,
skbaddr, skblen):
event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
skbaddr, skblen)
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
index 74d55ec..de66cb3 100644
--- a/tools/perf/scripts/python/sched-migration.py
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -369,93 +369,92 @@ def trace_end():

def sched__sched_stat_runtime(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, runtime, vruntime):
+ common_callchain, comm, pid, runtime, vruntime):
pass

def sched__sched_stat_iowait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_sleep(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_stat_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, delay):
+ common_callchain, comm, pid, delay):
pass

def sched__sched_process_fork(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- parent_comm, parent_pid, child_comm, child_pid):
+ common_callchain, parent_comm, parent_pid, child_comm, child_pid):
pass

def sched__sched_process_wait(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_exit(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_process_free(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_migrate_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, orig_cpu,
+ common_callchain, comm, pid, prio, orig_cpu,
dest_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)

def sched__sched_switch(event_name, context, common_cpu,
- common_secs, common_nsecs, common_pid, common_comm,
+ common_secs, common_nsecs, common_pid, common_comm, common_callchain,
prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio):

headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
next_comm, next_pid, next_prio)

def sched__sched_wakeup_new(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 1)

def sched__sched_wakeup(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio, success,
+ common_callchain, comm, pid, prio, success,
target_cpu):
headers = EventHeaders(common_cpu, common_secs, common_nsecs,
- common_pid, common_comm)
+ common_pid, common_comm, common_callchain)
parser.wake_up(headers, comm, pid, success, target_cpu, 0)

def sched__sched_wait_task(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid, prio):
+ common_callchain, comm, pid, prio):
pass

def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- ret):
+ common_callchain, ret):
pass

def sched__sched_kthread_stop(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- comm, pid):
+ common_callchain, comm, pid):
pass

-def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
- common_pid, common_comm):
+def trace_unhandled(event_name, context, event_fields_dict):
pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
index c9f3058..61621b9 100644
--- a/tools/perf/scripts/python/sctop.py
+++ b/tools/perf/scripts/python/sctop.py
@@ -44,7 +44,7 @@ def trace_begin():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
index cf2054c..daf314c 100644
--- a/tools/perf/scripts/python/syscall-counts-by-pid.py
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -38,7 +38,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):

if (for_comm and common_comm != for_comm) or \
(for_pid and common_pid != for_pid ):
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
index 92b2938..e66a773 100644
--- a/tools/perf/scripts/python/syscall-counts.py
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -35,7 +35,7 @@ def trace_end():

def raw_syscalls__sys_enter(event_name, context, common_cpu,
common_secs, common_nsecs, common_pid, common_comm,
- id, args):
+ common_callchain, id, args):
if for_comm is not None:
if common_comm != for_comm:
return
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index b6c1a69..cf65404 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
+#include "../machine.h"

PyMODINIT_FUNC initperf_trace_context(void);

@@ -278,12 +279,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
return obj;
}

+
+static PyObject *python_process_callchain(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al)
+{
+ PyObject *pylist;
+
+ pylist = PyList_New(0);
+ if (!pylist)
+ Py_FatalError("couldn't create Python list");
+
+ if (!symbol_conf.use_callchain || !sample->callchain)
+ goto exit;
+
+ if (machine__resolve_callchain(al->machine, evsel, al->thread,
+ sample, NULL, NULL,
+ PERF_MAX_STACK_DEPTH) != 0) {
+ pr_err("Failed to resolve callchain. Skipping\n");
+ goto exit;
+ }
+ callchain_cursor_commit(&callchain_cursor);
+
+
+ while (1) {
+ PyObject *pyelem;
+ struct callchain_cursor_node *node;
+ node = callchain_cursor_current(&callchain_cursor);
+ if (!node)
+ break;
+
+ pyelem = PyDict_New();
+ if (!pyelem)
+ Py_FatalError("couldn't create Python dictionary");
+
+
+ pydict_set_item_string_decref(pyelem, "ip",
+ PyLong_FromUnsignedLongLong(node->ip));
+
+ if (node->sym) {
+ PyObject *pysym = PyDict_New();
+ if (!pysym)
+ Py_FatalError("couldn't create Python dictionary");
+ pydict_set_item_string_decref(pysym, "start",
+ PyLong_FromUnsignedLongLong(node->sym->start));
+ pydict_set_item_string_decref(pysym, "end",
+ PyLong_FromUnsignedLongLong(node->sym->end));
+ pydict_set_item_string_decref(pysym, "binding",
+ PyInt_FromLong(node->sym->binding));
+ pydict_set_item_string_decref(pysym, "name",
+ PyString_FromStringAndSize(node->sym->name,
+ node->sym->namelen));
+ pydict_set_item_string_decref(pyelem, "sym", pysym);
+ }
+
+ if (node->map) {
+ struct map *map = node->map;
+ const char *dsoname = "[unknown]";
+ if (map && map->dso && (map->dso->name || map->dso->long_name)) {
+ if (symbol_conf.show_kernel_path && map->dso->long_name)
+ dsoname = map->dso->long_name;
+ else if (map->dso->name)
+ dsoname = map->dso->name;
+ }
+ pydict_set_item_string_decref(pyelem, "dso",
+ PyString_FromString(dsoname));
+ }
+
+ callchain_cursor_advance(&callchain_cursor);
+ PyList_Append(pylist, pyelem);
+ Py_DECREF(pyelem);
+ }
+
+exit:
+ return pylist;
+}
+
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
+ PyObject *handler, *retval, *context, *t, *obj, *callchain;
+ PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -326,18 +405,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
+ PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
+ pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@@ -357,6 +441,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);

}
+
if (!handler)
PyTuple_SetItem(t, n++, dict);

@@ -388,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict;
+ PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;

@@ -428,6 +513,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}

+ /* ip unwinding */
+ callchain = python_process_callchain(sample, evsel, al);
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@@ -624,6 +713,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
+ fprintf(ofp, "common_callchain, ");

not_first = 0;
count = 0;
@@ -667,7 +757,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}

- fprintf(ofp, "\\n\" %% \\\n\t\t(");
+ fprintf(ofp, "\" %% \\\n\t\t(");

not_first = 0;
count = 0;
@@ -703,7 +793,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}

- fprintf(ofp, "),\n\n");
+ fprintf(ofp, ")\n\n");
+
+ fprintf(ofp, "\t\tfor node in common_callchain:");
+ fprintf(ofp, "\n\t\t\tif 'sym' in node:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
+ fprintf(ofp, "\n\t\t\telse:");
+ fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
+ fprintf(ofp, "\t\tprint \"\\n\"\n\n");
+
}

fprintf(ofp, "def trace_unhandled(event_name, context, "

Subject: [tip:perf/core] perf script: Provide additional sample information on generic events

Commit-ID: 57608cfd8827a74237d264a197722e2c99f72da4
Gitweb: http://git.kernel.org/tip/57608cfd8827a74237d264a197722e2c99f72da4
Author: Joseph Schuchart <[email protected]>
AuthorDate: Thu, 10 Jul 2014 13:50:56 +0200
Committer: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 16 Jul 2014 17:57:33 -0300

perf script: Provide additional sample information on generic events

To python scripts, including pid, tid, and cpu for which the event was
recorded.

At the moment, the pointer to the sample struct is passed to scripts,
which seems to be of little use.

The patch puts this information in dictionaries for easy access by
Python scripts.

Signed-off-by: Joseph Schuchart <[email protected]>
Acked-by: Thomas Ilsche <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Ilsche <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
.../util/scripting-engines/trace-event-python.c | 23 +++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index cf65404..b366b48 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -473,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
- PyObject *handler, *retval, *t, *dict, *callchain;
+ PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample;
static char handler_name[64];
unsigned n = 0;

@@ -489,6 +489,10 @@ static void python_process_general_event(struct perf_sample *sample,
if (!dict)
Py_FatalError("couldn't create Python dictionary");

+ dict_sample = PyDict_New();
+ if (!dict_sample)
+ Py_FatalError("couldn't create Python dictionary");
+
snprintf(handler_name, sizeof(handler_name), "%s", "process_event");

handler = PyDict_GetItemString(main_dict, handler_name);
@@ -498,8 +502,21 @@ static void python_process_general_event(struct perf_sample *sample,
pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)&evsel->attr, sizeof(evsel->attr)));
- pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
- (const char *)sample, sizeof(*sample)));
+
+ pydict_set_item_string_decref(dict_sample, "pid",
+ PyInt_FromLong(sample->pid));
+ pydict_set_item_string_decref(dict_sample, "tid",
+ PyInt_FromLong(sample->tid));
+ pydict_set_item_string_decref(dict_sample, "cpu",
+ PyInt_FromLong(sample->cpu));
+ pydict_set_item_string_decref(dict_sample, "ip",
+ PyLong_FromUnsignedLongLong(sample->ip));
+ pydict_set_item_string_decref(dict_sample, "time",
+ PyLong_FromUnsignedLongLong(sample->time));
+ pydict_set_item_string_decref(dict_sample, "period",
+ PyLong_FromUnsignedLongLong(sample->period));
+ pydict_set_item_string_decref(dict, "sample", dict_sample);
+
pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
(const char *)sample->raw_data, sample->raw_size));
pydict_set_item_string_decref(dict, "comm",