summaryrefslogtreecommitdiffstats
path: root/tools/perf/util/scripting-engines/trace-event-python.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c246
1 files changed, 184 insertions, 62 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00..c7187f0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
}
+static int get_argument_count(PyObject *handler)
+{
+ int arg_count = 0;
+
+ /*
+ * The attribute for the code object is func_code in Python 2,
+ * whereas it is __code__ in Python 3.0+.
+ */
+ PyObject *code_obj = PyObject_GetAttrString(handler,
+ "func_code");
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ code_obj = PyObject_GetAttrString(handler,
+ "__code__");
+ }
+ PyErr_Clear();
+ if (code_obj) {
+ PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+ "co_argcount");
+ if (arg_count_obj) {
+ arg_count = (int) PyInt_AsLong(arg_count_obj);
+ Py_DECREF(arg_count_obj);
+ }
+ Py_DECREF(code_obj);
+ }
+ return arg_count;
+}
+
static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
{
PyObject *retval;
@@ -391,13 +419,115 @@ exit:
return pylist;
}
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+ PyObject *t;
+
+ t = PyTuple_New(2);
+ if (!t)
+ Py_FatalError("couldn't create Python tuple");
+ PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+ PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+ return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel)
+{
+ u64 read_format = evsel->attr.read_format;
+ PyObject *values;
+ unsigned int i;
+
+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+ pydict_set_item_string_decref(dict_sample, "time_enabled",
+ PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+ }
+
+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+ pydict_set_item_string_decref(dict_sample, "time_running",
+ PyLong_FromUnsignedLongLong(sample->read.time_running));
+ }
+
+ if (read_format & PERF_FORMAT_GROUP)
+ values = PyList_New(sample->read.group.nr);
+ else
+ values = PyList_New(1);
+
+ if (!values)
+ Py_FatalError("couldn't create Python list");
+
+ if (read_format & PERF_FORMAT_GROUP) {
+ for (i = 0; i < sample->read.group.nr; i++) {
+ PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
+ PyList_SET_ITEM(values, i, t);
+ }
+ } else {
+ PyObject *t = get_sample_value_as_tuple(&sample->read.one);
+ PyList_SET_ITEM(values, 0, t);
+ }
+ pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct addr_location *al,
+ PyObject *callchain)
+{
+ PyObject *dict, *dict_sample;
+
+ dict = PyDict_New();
+ if (!dict)
+ Py_FatalError("couldn't create Python dictionary");
+
+ dict_sample = PyDict_New();
+ if (!dict_sample)
+ Py_FatalError("couldn't create Python dictionary");
+
+ 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, "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));
+ set_sample_read_in_dict(dict_sample, sample, evsel);
+ 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",
+ PyString_FromString(thread__comm_str(al->thread)));
+ if (al->map) {
+ pydict_set_item_string_decref(dict, "dso",
+ PyString_FromString(al->map->dso->name));
+ }
+ if (al->sym) {
+ pydict_set_item_string_decref(dict, "symbol",
+ PyString_FromString(al->sym->name));
+ }
+
+ pydict_set_item_string_decref(dict, "callchain", callchain);
+
+ return dict;
+}
+
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct addr_location *al)
{
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
- PyObject *dict = NULL;
+ PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -407,10 +537,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
- t = PyTuple_New(MAX_FIELDS);
- if (!t)
- Py_FatalError("couldn't create Python tuple");
+ const char *default_handler_name = "trace_unhandled";
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +554,19 @@ static void python_process_tracepoint(struct perf_sample *sample,
handler = get_handler(handler_name);
if (!handler) {
+ handler = get_handler(default_handler_name);
+ if (!handler)
+ return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+ t = PyTuple_New(MAX_FIELDS);
+ if (!t)
+ Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
@@ -444,8 +580,10 @@ static void python_process_tracepoint(struct perf_sample *sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+ /* Need an additional reference for the perf_sample dict */
+ Py_INCREF(callchain);
- if (handler) {
+ if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,26 +622,35 @@ static void python_process_tracepoint(struct perf_sample *sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
- if (handler)
+ if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
}
- if (!handler)
+ if (dict)
PyTuple_SetItem(t, n++, dict);
+ if (get_argument_count(handler) == (int) n + 1) {
+ all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+ callchain);
+ PyTuple_SetItem(t, n++, all_entries_dict);
+ } else {
+ Py_DECREF(callchain);
+ }
+
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
- if (handler) {
+ if (!dict) {
call_object(handler, t, handler_name);
} else {
- try_call_object("trace_unhandled", t);
+ call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
+ Py_XDECREF(all_entries_dict);
Py_DECREF(t);
}
@@ -795,10 +942,16 @@ static void python_process_general_event(struct perf_sample *sample,
struct perf_evsel *evsel,
struct addr_location *al)
{
- PyObject *handler, *t, *dict, *callchain, *dict_sample;
+ PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
+ snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+ handler = get_handler(handler_name);
+ if (!handler)
+ return;
+
/*
* Use the MAX_FIELDS to make the function expandable, though
* currently there is only one item for the tuple.
@@ -807,61 +960,16 @@ static void python_process_general_event(struct perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
- dict = PyDict_New();
- 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 = get_handler(handler_name);
- if (!handler)
- goto exit;
-
- 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, "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",
- PyString_FromString(thread__comm_str(al->thread)));
- if (al->map) {
- pydict_set_item_string_decref(dict, "dso",
- PyString_FromString(al->map->dso->name));
- }
- if (al->sym) {
- pydict_set_item_string_decref(dict, "symbol",
- PyString_FromString(al->sym->name));
- }
-
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
- pydict_set_item_string_decref(dict, "callchain", callchain);
+ dict = get_perf_sample_dict(sample, evsel, al, callchain);
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
}
@@ -1259,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}
+ if (not_first++)
+ fprintf(ofp, ", ");
+ if (++count % 5 == 0)
+ fprintf(ofp, "\n\t\t");
+ fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1328,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, ")\n\n");
+ fprintf(ofp, "\t\tprint 'Sample: {'+"
+ "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\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'])");
@@ -1338,15 +1455,20 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
}
fprintf(ofp, "def trace_unhandled(event_name, context, "
- "event_fields_dict):\n");
+ "event_fields_dict, perf_sample_dict):\n");
- fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
- "for k,v in sorted(event_fields_dict.items())])\n\n");
+ fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+ fprintf(ofp, "\t\tprint 'Sample: {'+"
+ "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
- "(event_name, cpu, secs, nsecs, pid, comm),\n");
+ "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+ fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+ "\treturn delimiter.join"
+ "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
fclose(ofp);
OpenPOWER on IntegriCloud