Commit-ID:  ae938802443732e77d01f8d5b52b900b9327ff30
Gitweb:     http://git.kernel.org/tip/ae938802443732e77d01f8d5b52b900b9327ff30
Author:     Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Tue, 6 Oct 2015 17:46:46 -0300
Committer:  Arnaldo Carvalho de Melo <[email protected]>
CommitDate: Wed, 7 Oct 2015 19:41:50 -0300

perf python: Support the PERF_RECORD_SWITCH event

To test it check tools/perf/python/twatch.py, after following the
instructions there to enable context_switch, output looks like:

  [root@zoo linux]# tools/perf/python/twatch.py
  cpu: 1, pid: 31463, tid: 31463 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31463, switch_out: 0 }
  cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31496, switch_out: 0 }
  cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31496, switch_out: 1 }
  cpu: 3, pid: 31463, tid: 31527 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31527, switch_out: 0 }
  cpu: 1, pid: 31463, tid: 31463 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31463, switch_out: 1 }
  cpu: 3, pid: 31463, tid: 31527 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31527, switch_out: 1 }
  cpu: 1, pid: 31463, tid: 31463 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31463, switch_out: 0 }
  ^CTraceback (most recent call last):
    File "tools/perf/python/twatch.py", line 67, in <module>
      main(context_switch = 1, thread = 31463)
    File "tools/perf/python/twatch.py", line 40, in main
      evlist.poll(timeout = -1)
  KeyboardInterrupt
  [root@zoo linux]#

Cc: Adrian Hunter <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Guy Streeter <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Stephane Eranian <[email protected]>
Cc: Wang Nan <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
 tools/perf/python/twatch.py | 23 +++++++++++++++---
 tools/perf/util/python.c    | 59 ++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index b9d5083..c235c22 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -15,14 +15,14 @@
 
 import perf
 
-def main():
+def main(context_switch = 0, thread = -1):
        cpus = perf.cpu_map()
-       threads = perf.thread_map()
+       threads = perf.thread_map(thread)
        evsel = perf.evsel(type   = perf.TYPE_SOFTWARE,
                           config = perf.COUNT_SW_DUMMY,
                           task = 1, comm = 1, mmap = 0, freq = 0,
                           wakeup_events = 1, watermark = 1,
-                          sample_id_all = 1,
+                          sample_id_all = 1, context_switch = context_switch,
                           sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | 
perf.SAMPLE_CPU)
 
        """What we want are just the PERF_RECORD_ lifetime events for threads,
@@ -48,4 +48,21 @@ def main():
                        print event
 
 if __name__ == '__main__':
+    """
+       To test the PERF_RECORD_SWITCH record, pick a pid and replace
+       in the following line.
+
+       Example output:
+
+cpu: 3, pid: 31463, tid: 31593 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31593, switch_out: 1 }
+cpu: 1, pid: 31463, tid: 31489 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31489, switch_out: 1 }
+cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31496, switch_out: 1 }
+cpu: 3, pid: 31463, tid: 31491 { type: context_switch, next_prev_pid: 31463, 
next_prev_tid: 31491, switch_out: 0 }
+
+       It is possible as well to use event.misc & 
perf.PERF_RECORD_MISC_SWITCH_OUT
+       to figure out if this is a context switch in or out of the monitored 
threads.
+
+       If bored, please add command line option parsing support for these 
options :-)
+    """
+    # main(context_switch = 1, thread = 31463)
     main()
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 6324fe6..98f127a 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -67,6 +67,7 @@ static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap 
event object.");
 static PyMemberDef pyrf_mmap_event__members[] = {
        sample_members
        member_def(perf_event_header, type, T_UINT, "event type"),
+       member_def(perf_event_header, misc, T_UINT, "event misc"),
        member_def(mmap_event, pid, T_UINT, "event pid"),
        member_def(mmap_event, tid, T_UINT, "event tid"),
        member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
@@ -297,6 +298,43 @@ static PyTypeObject pyrf_sample_event__type = {
        .tp_repr        = (reprfunc)pyrf_sample_event__repr,
 };
 
+static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch 
event object.");
+
+static PyMemberDef pyrf_context_switch_event__members[] = {
+       sample_members
+       member_def(perf_event_header, type, T_UINT, "event type"),
+       member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev 
pid"),
+       member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev 
tid"),
+       { .name = NULL, },
+};
+
+static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent)
+{
+       PyObject *ret;
+       char *s;
+
+       if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, 
next_prev_tid: %u, switch_out: %u }",
+                    pevent->event.context_switch.next_prev_pid,
+                    pevent->event.context_switch.next_prev_tid,
+                    !!(pevent->event.header.misc & 
PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
+               ret = PyErr_NoMemory();
+       } else {
+               ret = PyString_FromString(s);
+               free(s);
+       }
+       return ret;
+}
+
+static PyTypeObject pyrf_context_switch_event__type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       .tp_name        = "perf.context_switch_event",
+       .tp_basicsize   = sizeof(struct pyrf_event),
+       .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+       .tp_doc         = pyrf_context_switch_event__doc,
+       .tp_members     = pyrf_context_switch_event__members,
+       .tp_repr        = (reprfunc)pyrf_context_switch_event__repr,
+};
+
 static int pyrf_event__setup_types(void)
 {
        int err;
@@ -306,6 +344,7 @@ static int pyrf_event__setup_types(void)
        pyrf_lost_event__type.tp_new =
        pyrf_read_event__type.tp_new =
        pyrf_sample_event__type.tp_new =
+       pyrf_context_switch_event__type.tp_new =
        pyrf_throttle_event__type.tp_new = PyType_GenericNew;
        err = PyType_Ready(&pyrf_mmap_event__type);
        if (err < 0)
@@ -328,6 +367,9 @@ static int pyrf_event__setup_types(void)
        err = PyType_Ready(&pyrf_sample_event__type);
        if (err < 0)
                goto out;
+       err = PyType_Ready(&pyrf_context_switch_event__type);
+       if (err < 0)
+               goto out;
 out:
        return err;
 }
@@ -342,6 +384,8 @@ static PyTypeObject *pyrf_event__type[] = {
        [PERF_RECORD_FORK]       = &pyrf_task_event__type,
        [PERF_RECORD_READ]       = &pyrf_read_event__type,
        [PERF_RECORD_SAMPLE]     = &pyrf_sample_event__type,
+       [PERF_RECORD_SWITCH]     = &pyrf_context_switch_event__type,
+       [PERF_RECORD_SWITCH_CPU_WIDE]  = &pyrf_context_switch_event__type,
 };
 
 static PyObject *pyrf_event__new(union perf_event *event)
@@ -349,8 +393,10 @@ static PyObject *pyrf_event__new(union perf_event *event)
        struct pyrf_event *pevent;
        PyTypeObject *ptype;
 
-       if (event->header.type < PERF_RECORD_MMAP ||
-           event->header.type > PERF_RECORD_SAMPLE)
+       if ((event->header.type < PERF_RECORD_MMAP ||
+            event->header.type > PERF_RECORD_SAMPLE) &&
+           !(event->header.type == PERF_RECORD_SWITCH ||
+             event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
                return NULL;
 
        ptype = pyrf_event__type[event->header.type];
@@ -528,6 +574,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
                "exclude_hv",
                "exclude_idle",
                "mmap",
+               "context_switch",
                "comm",
                "freq",
                "inherit_stat",
@@ -553,6 +600,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
            exclude_hv = 0,
            exclude_idle = 0,
            mmap = 0,
+           context_switch = 0,
            comm = 0,
            freq = 1,
            inherit_stat = 0,
@@ -565,13 +613,13 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
        int idx = 0;
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs,
-                                        "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", 
kwlist,
+                                        "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", 
kwlist,
                                         &attr.type, &attr.config, 
&attr.sample_freq,
                                         &sample_period, &attr.sample_type,
                                         &attr.read_format, &disabled, &inherit,
                                         &pinned, &exclusive, &exclude_user,
                                         &exclude_kernel, &exclude_hv, 
&exclude_idle,
-                                        &mmap, &comm, &freq, &inherit_stat,
+                                        &mmap, &context_switch, &comm, &freq, 
&inherit_stat,
                                         &enable_on_exec, &task, &watermark,
                                         &precise_ip, &mmap_data, 
&sample_id_all,
                                         &attr.wakeup_events, &attr.bp_type,
@@ -595,6 +643,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
        attr.exclude_hv     = exclude_hv;
        attr.exclude_idle   = exclude_idle;
        attr.mmap           = mmap;
+       attr.context_switch = context_switch;
        attr.comm           = comm;
        attr.freq           = freq;
        attr.inherit_stat   = inherit_stat;
@@ -1019,6 +1068,8 @@ static struct {
        PERF_CONST(RECORD_LOST_SAMPLES),
        PERF_CONST(RECORD_SWITCH),
        PERF_CONST(RECORD_SWITCH_CPU_WIDE),
+
+       PERF_CONST(RECORD_MISC_SWITCH_OUT),
        { .name = NULL, },
 };
 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to