From e5cadb93d0839d268a7c4199e0fdef0f94722117 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 23 Jun 2016 11:26:15 -0300 Subject: perf evlist: Rename for_each() macros to for_each_entry() To match the semantics for list.h in the kernel, that are used to implement those macros. Cc: Adrian Hunter Cc: David Ahern Cc: Jiri Olsa Cc: Milian Wolff Cc: Namhyung Kim Cc: Taeung Song Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-qbcjlgj0ffxquxscahbpddi3@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 98f127abfa42..65c6c73d28fe 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -957,7 +957,7 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) if (i >= pevlist->evlist.nr_entries) return NULL; - evlist__for_each(&pevlist->evlist, pos) { + evlist__for_each_entry(&pevlist->evlist, pos) { if (i-- == 0) break; } -- cgit v1.2.3-70-g09d2 From ad4e3c04587c01c2e2b00c0e6a414dbededa6c55 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:07:55 +0200 Subject: perf python: Init perf_event_attr::size in perf.evsel constructor Currently 0 is passed as perf_event_attr::size, which could block usage of new features. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-4-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 65c6c73d28fe..d0c1267741ee 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -653,6 +653,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel, attr.precise_ip = precise_ip; attr.mmap_data = mmap_data; attr.sample_id_all = sample_id_all; + attr.size = sizeof(attr); perf_evsel__init(&pevsel->evsel, &attr, idx); return 0; -- cgit v1.2.3-70-g09d2 From e8968e654191390a1300f0847250353a1c9da30d Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:07:56 +0200 Subject: perf python: Fix pyrf_evlist__read_on_cpu event consuming We can't consume the event before parsing it. Under heavy load we could get caught by kernel writer overwriting the event we're trying to parse. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-5-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d0c1267741ee..c68ef0319114 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -865,12 +865,14 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, PyObject *pyevent = pyrf_event__new(event); struct pyrf_event *pevent = (struct pyrf_event *)pyevent; - perf_evlist__mmap_consume(evlist, cpu); - if (pyevent == NULL) return PyErr_NoMemory(); err = perf_evlist__parse_sample(evlist, event, &pevent->sample); + + /* Consume the even only after we parsed it out. */ + perf_evlist__mmap_consume(evlist, cpu); + if (err) return PyErr_Format(PyExc_OSError, "perf: can't parse sample, err=%d", err); -- cgit v1.2.3-70-g09d2 From 85e37de3a993b9e407398f792b996acad27f4cdc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:07:57 +0200 Subject: perf python: Put perf.event objects into dictionary Make perf.event object parts of the perf module dictionary so we can address them by name. The following objects/names are added: mmap_event lost_event comm_event task_event throttle_event task_event read_event sample_event switch_event We can now use it in python script like: ... event = evlist.read_on_cpu(cpu) ... if not isinstance(event, perf.sample_event): Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-6-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index c68ef0319114..fc277e486d17 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -1103,6 +1103,33 @@ PyMODINIT_FUNC initperf(void) Py_INCREF(&pyrf_evsel__type); PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); + Py_INCREF(&pyrf_mmap_event__type); + PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type); + + Py_INCREF(&pyrf_lost_event__type); + PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type); + + Py_INCREF(&pyrf_comm_event__type); + PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type); + + Py_INCREF(&pyrf_task_event__type); + PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); + + Py_INCREF(&pyrf_throttle_event__type); + PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type); + + Py_INCREF(&pyrf_task_event__type); + PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); + + Py_INCREF(&pyrf_read_event__type); + PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type); + + Py_INCREF(&pyrf_sample_event__type); + PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type); + + Py_INCREF(&pyrf_context_switch_event__type); + PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type); + Py_INCREF(&pyrf_thread_map__type); PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); -- cgit v1.2.3-70-g09d2 From 1075fbb22f095c857930190e30fd3ae422d424b6 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:07:58 +0200 Subject: perf python: Add perf.tracepoint method To get id of the tracepoint from subsystem and name strings. The interface is: id = perf.tracepoint(sys, name) In case of error -1 is returned. It will be used to get python tracepoint event's config value for tracepoint event. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-7-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index fc277e486d17..45fdd4a68721 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "evlist.h" #include "evsel.h" #include "event.h" @@ -1076,7 +1077,32 @@ static struct { { .name = NULL, }, }; +static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, + PyObject *args, PyObject *kwargs) +{ + struct event_format *tp_format; + static char *kwlist[] = { "sys", "name", NULL }; + char *sys = NULL; + char *name = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist, + &sys, &name)) + return NULL; + + tp_format = trace_event__tp_format(sys, name); + if (IS_ERR(tp_format)) + return PyInt_FromLong(-1); + + return PyInt_FromLong(tp_format->id); +} + static PyMethodDef perf__methods[] = { + { + .ml_name = "tracepoint", + .ml_meth = (PyCFunction) pyrf__tracepoint, + .ml_flags = METH_VARARGS | METH_KEYWORDS, + .ml_doc = PyDoc_STR("Get tracepoint config.") + }, { .ml_name = NULL, } }; -- cgit v1.2.3-70-g09d2 From 377f698db12150a1cf79987dca1d3990fa14a1f8 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:07:59 +0200 Subject: perf python: Add struct evsel into struct pyrf_event To be able to find out event configuration info during sample parsing. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-8-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 45fdd4a68721..dc7adaa3a02c 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -48,6 +48,7 @@ PyMODINIT_FUNC initperf(void); struct pyrf_event { PyObject_HEAD + struct perf_evsel *evsel; struct perf_sample sample; union perf_event event; }; @@ -865,11 +866,18 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, if (event != NULL) { PyObject *pyevent = pyrf_event__new(event); struct pyrf_event *pevent = (struct pyrf_event *)pyevent; + struct perf_evsel *evsel; if (pyevent == NULL) return PyErr_NoMemory(); - err = perf_evlist__parse_sample(evlist, event, &pevent->sample); + evsel = perf_evlist__event2evsel(evlist, event); + if (!evsel) + return Py_None; + + pevent->evsel = evsel; + + err = perf_evsel__parse_sample(evsel, event, &pevent->sample); /* Consume the even only after we parsed it out. */ perf_evlist__mmap_consume(evlist, cpu); -- cgit v1.2.3-70-g09d2 From bae57e3825a3dded15f61cd20c6757d60ad6c712 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sun, 10 Jul 2016 13:08:00 +0200 Subject: perf python: Add support to resolve tracepoint fields Adding tp_getattro callback for sample event. It resolves tracepoint fields in runtime. It's now possible to access tracepoint fields in normal fashion like hardcoded ones (see the example in the next patch). Reported-and-Tested-by: Jiri Pirko Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1468148882-10362-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index dc7adaa3a02c..d32f97033718 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -290,6 +290,97 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) return ret; } +static bool is_tracepoint(struct pyrf_event *pevent) +{ + return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT; +} + +static int is_printable_array(char *p, unsigned int len) +{ + unsigned int i; + + for (i = 0; i < len; i++) { + if (!isprint(p[i]) && !isspace(p[i])) + return 0; + } + + return 1; +} + +static PyObject* +tracepoint_field(struct pyrf_event *pe, struct format_field *field) +{ + struct pevent *pevent = field->event->pevent; + void *data = pe->sample.raw_data; + PyObject *ret = NULL; + unsigned long long val; + unsigned int offset, len; + + if (field->flags & FIELD_IS_ARRAY) { + offset = field->offset; + len = field->size; + if (field->flags & FIELD_IS_DYNAMIC) { + val = pevent_read_number(pevent, data + offset, len); + offset = val; + len = offset >> 16; + offset &= 0xffff; + } + if (field->flags & FIELD_IS_STRING && + is_printable_array(data + offset, len)) { + ret = PyString_FromString((char *)data + offset); + } else { + ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); + field->flags &= ~FIELD_IS_STRING; + } + } else { + val = pevent_read_number(pevent, data + field->offset, + field->size); + if (field->flags & FIELD_IS_POINTER) + ret = PyLong_FromUnsignedLong((unsigned long) val); + else if (field->flags & FIELD_IS_SIGNED) + ret = PyLong_FromLong((long) val); + else + ret = PyLong_FromUnsignedLong((unsigned long) val); + } + + return ret; +} + +static PyObject* +get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) +{ + const char *str = PyString_AsString(PyObject_Str(attr_name)); + struct perf_evsel *evsel = pevent->evsel; + struct format_field *field; + + if (!evsel->tp_format) { + struct event_format *tp_format; + + tp_format = trace_event__tp_format_id(evsel->attr.config); + if (!tp_format) + return NULL; + + evsel->tp_format = tp_format; + } + + field = pevent_find_any_field(evsel->tp_format, str); + if (!field) + return NULL; + + return tracepoint_field(pevent, field); +} + +static PyObject* +pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name) +{ + PyObject *obj = NULL; + + if (is_tracepoint(pevent)) + obj = get_tracepoint_field(pevent, attr_name); + + return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name); +} + static PyTypeObject pyrf_sample_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.sample_event", @@ -298,6 +389,7 @@ static PyTypeObject pyrf_sample_event__type = { .tp_doc = pyrf_sample_event__doc, .tp_members = pyrf_sample_event__members, .tp_repr = (reprfunc)pyrf_sample_event__repr, + .tp_getattro = (getattrofunc) pyrf_sample_event__getattro, }; static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); -- cgit v1.2.3-70-g09d2 From accaed2659530b4047678070cb23fd1d9a1c1a59 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Sat, 16 Jul 2016 18:11:19 +0200 Subject: perf tools: Make is_printable_array global It's used from 2 objects in perf, so it's better to keep just one copy. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Jiri Pirko Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1468685480-18951-3-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/python.c | 12 ------------ tools/perf/util/scripting-engines/trace-event-python.c | 16 ---------------- tools/perf/util/util.c | 16 ++++++++++++++++ tools/perf/util/util.h | 1 + 4 files changed, 17 insertions(+), 28 deletions(-) (limited to 'tools/perf/util/python.c') diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index d32f97033718..a5fbc012e3df 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -295,18 +295,6 @@ static bool is_tracepoint(struct pyrf_event *pevent) return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT; } -static int is_printable_array(char *p, unsigned int len) -{ - unsigned int i; - - for (i = 0; i < len; i++) { - if (!isprint(p[i]) && !isspace(p[i])) - return 0; - } - - return 1; -} - static PyObject* tracepoint_field(struct pyrf_event *pe, struct format_field *field) { diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 7bd6da80533e..e0203b979474 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -386,22 +386,6 @@ exit: return pylist; } -static int is_printable_array(char *p, unsigned int len) -{ - unsigned int i; - - if (!p || !len || p[len - 1] != 0) - return 0; - - len--; - - for (i = 0; i < len; i++) { - if (!isprint(p[i]) && !isspace(p[i])) - return 0; - } - return 1; -} - static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index 5f44a21955cd..cee559d8c9e8 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -746,3 +746,19 @@ void print_binary(unsigned char *data, size_t len, } printer(BINARY_PRINT_DATA_END, -1, extra); } + +int is_printable_array(char *p, unsigned int len) +{ + unsigned int i; + + if (!p || !len || p[len - 1] != 0) + return 0; + + len--; + + for (i = 0; i < len; i++) { + if (!isprint(p[i]) && !isspace(p[i])) + return 0; + } + return 1; +} diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 843cbba8f9d3..e5f55477491d 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -364,4 +364,5 @@ void print_binary(unsigned char *data, size_t len, extern int sched_getcpu(void); #endif +int is_printable_array(char *p, unsigned int len); #endif /* GIT_COMPAT_UTIL_H */ -- cgit v1.2.3-70-g09d2