8e0b5a39d8a739720e621521f8b65710b1bb2486
[pandora-kernel.git] / tools / perf / util / python.c
1 #include <Python.h>
2 #include <structmember.h>
3 #include <inttypes.h>
4 #include <poll.h>
5 #include "evlist.h"
6 #include "evsel.h"
7 #include "event.h"
8 #include "cpumap.h"
9 #include "thread_map.h"
10
11 /* Define PyVarObject_HEAD_INIT for python 2.5 */
12 #ifndef PyVarObject_HEAD_INIT
13 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
14 #endif
15
16 struct throttle_event {
17         struct perf_event_header header;
18         u64                      time;
19         u64                      id;
20         u64                      stream_id;
21 };
22
23 PyMODINIT_FUNC initperf(void);
24
25 #define member_def(type, member, ptype, help) \
26         { #member, ptype, \
27           offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
28           0, help }
29
30 #define sample_member_def(name, member, ptype, help) \
31         { #name, ptype, \
32           offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
33           0, help }
34
35 struct pyrf_event {
36         PyObject_HEAD
37         struct perf_sample sample;
38         union perf_event   event;
39 };
40
41 #define sample_members \
42         sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"),                     \
43         sample_member_def(sample_pid, pid, T_INT, "event pid"),                  \
44         sample_member_def(sample_tid, tid, T_INT, "event tid"),                  \
45         sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),            \
46         sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),                 \
47         sample_member_def(sample_id, id, T_ULONGLONG, "event id"),                       \
48         sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
49         sample_member_def(sample_period, period, T_ULONGLONG, "event period"),           \
50         sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
51
52 static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
53
54 static PyMemberDef pyrf_mmap_event__members[] = {
55         sample_members
56         member_def(perf_event_header, type, T_UINT, "event type"),
57         member_def(mmap_event, pid, T_UINT, "event pid"),
58         member_def(mmap_event, tid, T_UINT, "event tid"),
59         member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
60         member_def(mmap_event, len, T_ULONGLONG, "map length"),
61         member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
62         member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
63         { .name = NULL, },
64 };
65
66 static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
67 {
68         PyObject *ret;
69         char *s;
70
71         if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
72                          "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
73                          "filename: %s }",
74                      pevent->event.mmap.pid, pevent->event.mmap.tid,
75                      pevent->event.mmap.start, pevent->event.mmap.len,
76                      pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
77                 ret = PyErr_NoMemory();
78         } else {
79                 ret = PyString_FromString(s);
80                 free(s);
81         }
82         return ret;
83 }
84
85 static PyTypeObject pyrf_mmap_event__type = {
86         PyVarObject_HEAD_INIT(NULL, 0)
87         .tp_name        = "perf.mmap_event",
88         .tp_basicsize   = sizeof(struct pyrf_event),
89         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
90         .tp_doc         = pyrf_mmap_event__doc,
91         .tp_members     = pyrf_mmap_event__members,
92         .tp_repr        = (reprfunc)pyrf_mmap_event__repr,
93 };
94
95 static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
96
97 static PyMemberDef pyrf_task_event__members[] = {
98         sample_members
99         member_def(perf_event_header, type, T_UINT, "event type"),
100         member_def(fork_event, pid, T_UINT, "event pid"),
101         member_def(fork_event, ppid, T_UINT, "event ppid"),
102         member_def(fork_event, tid, T_UINT, "event tid"),
103         member_def(fork_event, ptid, T_UINT, "event ptid"),
104         member_def(fork_event, time, T_ULONGLONG, "timestamp"),
105         { .name = NULL, },
106 };
107
108 static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
109 {
110         return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
111                                    "ptid: %u, time: %" PRIu64 "}",
112                                    pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
113                                    pevent->event.fork.pid,
114                                    pevent->event.fork.ppid,
115                                    pevent->event.fork.tid,
116                                    pevent->event.fork.ptid,
117                                    pevent->event.fork.time);
118 }
119
120 static PyTypeObject pyrf_task_event__type = {
121         PyVarObject_HEAD_INIT(NULL, 0)
122         .tp_name        = "perf.task_event",
123         .tp_basicsize   = sizeof(struct pyrf_event),
124         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
125         .tp_doc         = pyrf_task_event__doc,
126         .tp_members     = pyrf_task_event__members,
127         .tp_repr        = (reprfunc)pyrf_task_event__repr,
128 };
129
130 static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
131
132 static PyMemberDef pyrf_comm_event__members[] = {
133         sample_members
134         member_def(perf_event_header, type, T_UINT, "event type"),
135         member_def(comm_event, pid, T_UINT, "event pid"),
136         member_def(comm_event, tid, T_UINT, "event tid"),
137         member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
138         { .name = NULL, },
139 };
140
141 static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
142 {
143         return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
144                                    pevent->event.comm.pid,
145                                    pevent->event.comm.tid,
146                                    pevent->event.comm.comm);
147 }
148
149 static PyTypeObject pyrf_comm_event__type = {
150         PyVarObject_HEAD_INIT(NULL, 0)
151         .tp_name        = "perf.comm_event",
152         .tp_basicsize   = sizeof(struct pyrf_event),
153         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
154         .tp_doc         = pyrf_comm_event__doc,
155         .tp_members     = pyrf_comm_event__members,
156         .tp_repr        = (reprfunc)pyrf_comm_event__repr,
157 };
158
159 static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
160
161 static PyMemberDef pyrf_throttle_event__members[] = {
162         sample_members
163         member_def(perf_event_header, type, T_UINT, "event type"),
164         member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
165         member_def(throttle_event, id, T_ULONGLONG, "event id"),
166         member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
167         { .name = NULL, },
168 };
169
170 static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
171 {
172         struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
173
174         return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
175                                    ", stream_id: %" PRIu64 " }",
176                                    pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
177                                    te->time, te->id, te->stream_id);
178 }
179
180 static PyTypeObject pyrf_throttle_event__type = {
181         PyVarObject_HEAD_INIT(NULL, 0)
182         .tp_name        = "perf.throttle_event",
183         .tp_basicsize   = sizeof(struct pyrf_event),
184         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
185         .tp_doc         = pyrf_throttle_event__doc,
186         .tp_members     = pyrf_throttle_event__members,
187         .tp_repr        = (reprfunc)pyrf_throttle_event__repr,
188 };
189
190 static int pyrf_event__setup_types(void)
191 {
192         int err;
193         pyrf_mmap_event__type.tp_new =
194         pyrf_task_event__type.tp_new =
195         pyrf_comm_event__type.tp_new =
196         pyrf_throttle_event__type.tp_new = PyType_GenericNew;
197         err = PyType_Ready(&pyrf_mmap_event__type);
198         if (err < 0)
199                 goto out;
200         err = PyType_Ready(&pyrf_task_event__type);
201         if (err < 0)
202                 goto out;
203         err = PyType_Ready(&pyrf_comm_event__type);
204         if (err < 0)
205                 goto out;
206         err = PyType_Ready(&pyrf_throttle_event__type);
207         if (err < 0)
208                 goto out;
209 out:
210         return err;
211 }
212
213 static PyTypeObject *pyrf_event__type[] = {
214         [PERF_RECORD_MMAP]       = &pyrf_mmap_event__type,
215         [PERF_RECORD_LOST]       = &pyrf_mmap_event__type,
216         [PERF_RECORD_COMM]       = &pyrf_comm_event__type,
217         [PERF_RECORD_EXIT]       = &pyrf_task_event__type,
218         [PERF_RECORD_THROTTLE]   = &pyrf_throttle_event__type,
219         [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
220         [PERF_RECORD_FORK]       = &pyrf_task_event__type,
221         [PERF_RECORD_READ]       = &pyrf_mmap_event__type,
222         [PERF_RECORD_SAMPLE]     = &pyrf_mmap_event__type,
223 };
224
225 static PyObject *pyrf_event__new(union perf_event *event)
226 {
227         struct pyrf_event *pevent;
228         PyTypeObject *ptype;
229
230         if (event->header.type < PERF_RECORD_MMAP ||
231             event->header.type > PERF_RECORD_SAMPLE)
232                 return NULL;
233
234         ptype = pyrf_event__type[event->header.type];
235         pevent = PyObject_New(struct pyrf_event, ptype);
236         if (pevent != NULL)
237                 memcpy(&pevent->event, event, event->header.size);
238         return (PyObject *)pevent;
239 }
240
241 struct pyrf_cpu_map {
242         PyObject_HEAD
243
244         struct cpu_map *cpus;
245 };
246
247 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
248                               PyObject *args, PyObject *kwargs)
249 {
250         static char *kwlist[] = { "cpustr", NULL };
251         char *cpustr = NULL;
252
253         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
254                                          kwlist, &cpustr))
255                 return -1;
256
257         pcpus->cpus = cpu_map__new(cpustr);
258         if (pcpus->cpus == NULL)
259                 return -1;
260         return 0;
261 }
262
263 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
264 {
265         cpu_map__delete(pcpus->cpus);
266         pcpus->ob_type->tp_free((PyObject*)pcpus);
267 }
268
269 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
270 {
271         struct pyrf_cpu_map *pcpus = (void *)obj;
272
273         return pcpus->cpus->nr;
274 }
275
276 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
277 {
278         struct pyrf_cpu_map *pcpus = (void *)obj;
279
280         if (i >= pcpus->cpus->nr)
281                 return NULL;
282
283         return Py_BuildValue("i", pcpus->cpus->map[i]);
284 }
285
286 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
287         .sq_length = pyrf_cpu_map__length,
288         .sq_item   = pyrf_cpu_map__item,
289 };
290
291 static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
292
293 static PyTypeObject pyrf_cpu_map__type = {
294         PyVarObject_HEAD_INIT(NULL, 0)
295         .tp_name        = "perf.cpu_map",
296         .tp_basicsize   = sizeof(struct pyrf_cpu_map),
297         .tp_dealloc     = (destructor)pyrf_cpu_map__delete,
298         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
299         .tp_doc         = pyrf_cpu_map__doc,
300         .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
301         .tp_init        = (initproc)pyrf_cpu_map__init,
302 };
303
304 static int pyrf_cpu_map__setup_types(void)
305 {
306         pyrf_cpu_map__type.tp_new = PyType_GenericNew;
307         return PyType_Ready(&pyrf_cpu_map__type);
308 }
309
310 struct pyrf_thread_map {
311         PyObject_HEAD
312
313         struct thread_map *threads;
314 };
315
316 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
317                                  PyObject *args, PyObject *kwargs)
318 {
319         static char *kwlist[] = { "pid", "tid", NULL };
320         int pid = -1, tid = -1;
321
322         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
323                                          kwlist, &pid, &tid))
324                 return -1;
325
326         pthreads->threads = thread_map__new(pid, tid);
327         if (pthreads->threads == NULL)
328                 return -1;
329         return 0;
330 }
331
332 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
333 {
334         thread_map__delete(pthreads->threads);
335         pthreads->ob_type->tp_free((PyObject*)pthreads);
336 }
337
338 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
339 {
340         struct pyrf_thread_map *pthreads = (void *)obj;
341
342         return pthreads->threads->nr;
343 }
344
345 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
346 {
347         struct pyrf_thread_map *pthreads = (void *)obj;
348
349         if (i >= pthreads->threads->nr)
350                 return NULL;
351
352         return Py_BuildValue("i", pthreads->threads->map[i]);
353 }
354
355 static PySequenceMethods pyrf_thread_map__sequence_methods = {
356         .sq_length = pyrf_thread_map__length,
357         .sq_item   = pyrf_thread_map__item,
358 };
359
360 static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
361
362 static PyTypeObject pyrf_thread_map__type = {
363         PyVarObject_HEAD_INIT(NULL, 0)
364         .tp_name        = "perf.thread_map",
365         .tp_basicsize   = sizeof(struct pyrf_thread_map),
366         .tp_dealloc     = (destructor)pyrf_thread_map__delete,
367         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
368         .tp_doc         = pyrf_thread_map__doc,
369         .tp_as_sequence = &pyrf_thread_map__sequence_methods,
370         .tp_init        = (initproc)pyrf_thread_map__init,
371 };
372
373 static int pyrf_thread_map__setup_types(void)
374 {
375         pyrf_thread_map__type.tp_new = PyType_GenericNew;
376         return PyType_Ready(&pyrf_thread_map__type);
377 }
378
379 struct pyrf_evsel {
380         PyObject_HEAD
381
382         struct perf_evsel evsel;
383 };
384
385 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
386                             PyObject *args, PyObject *kwargs)
387 {
388         struct perf_event_attr attr = {
389                 .type = PERF_TYPE_HARDWARE,
390                 .config = PERF_COUNT_HW_CPU_CYCLES,
391                 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
392         };
393         static char *kwlist[] = {
394                 "type",
395                 "config",
396                 "sample_freq",
397                 "sample_period",
398                 "sample_type",
399                 "read_format",
400                 "disabled",
401                 "inherit",
402                 "pinned",
403                 "exclusive",
404                 "exclude_user",
405                 "exclude_kernel",
406                 "exclude_hv",
407                 "exclude_idle",
408                 "mmap",
409                 "comm",
410                 "freq",
411                 "inherit_stat",
412                 "enable_on_exec",
413                 "task",
414                 "watermark",
415                 "precise_ip",
416                 "mmap_data",
417                 "sample_id_all",
418                 "wakeup_events",
419                 "bp_type",
420                 "bp_addr",
421                 "bp_len",
422                  NULL
423         };
424         u64 sample_period = 0;
425         u32 disabled = 0,
426             inherit = 0,
427             pinned = 0,
428             exclusive = 0,
429             exclude_user = 0,
430             exclude_kernel = 0,
431             exclude_hv = 0,
432             exclude_idle = 0,
433             mmap = 0,
434             comm = 0,
435             freq = 1,
436             inherit_stat = 0,
437             enable_on_exec = 0,
438             task = 0,
439             watermark = 0,
440             precise_ip = 0,
441             mmap_data = 0,
442             sample_id_all = 1;
443         int idx = 0;
444
445         if (!PyArg_ParseTupleAndKeywords(args, kwargs,
446                                          "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
447                                          &attr.type, &attr.config, &attr.sample_freq,
448                                          &sample_period, &attr.sample_type,
449                                          &attr.read_format, &disabled, &inherit,
450                                          &pinned, &exclusive, &exclude_user,
451                                          &exclude_kernel, &exclude_hv, &exclude_idle,
452                                          &mmap, &comm, &freq, &inherit_stat,
453                                          &enable_on_exec, &task, &watermark,
454                                          &precise_ip, &mmap_data, &sample_id_all,
455                                          &attr.wakeup_events, &attr.bp_type,
456                                          &attr.bp_addr, &attr.bp_len, &idx))
457                 return -1;
458
459         /* union... */
460         if (sample_period != 0) {
461                 if (attr.sample_freq != 0)
462                         return -1; /* FIXME: throw right exception */
463                 attr.sample_period = sample_period;
464         }
465
466         /* Bitfields */
467         attr.disabled       = disabled;
468         attr.inherit        = inherit;
469         attr.pinned         = pinned;
470         attr.exclusive      = exclusive;
471         attr.exclude_user   = exclude_user;
472         attr.exclude_kernel = exclude_kernel;
473         attr.exclude_hv     = exclude_hv;
474         attr.exclude_idle   = exclude_idle;
475         attr.mmap           = mmap;
476         attr.comm           = comm;
477         attr.freq           = freq;
478         attr.inherit_stat   = inherit_stat;
479         attr.enable_on_exec = enable_on_exec;
480         attr.task           = task;
481         attr.watermark      = watermark;
482         attr.precise_ip     = precise_ip;
483         attr.mmap_data      = mmap_data;
484         attr.sample_id_all  = sample_id_all;
485
486         perf_evsel__init(&pevsel->evsel, &attr, idx);
487         return 0;
488 }
489
490 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
491 {
492         perf_evsel__exit(&pevsel->evsel);
493         pevsel->ob_type->tp_free((PyObject*)pevsel);
494 }
495
496 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
497                                   PyObject *args, PyObject *kwargs)
498 {
499         struct perf_evsel *evsel = &pevsel->evsel;
500         struct cpu_map *cpus = NULL;
501         struct thread_map *threads = NULL;
502         PyObject *pcpus = NULL, *pthreads = NULL;
503         int group = 0, inherit = 0;
504         static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
505
506         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
507                                          &pcpus, &pthreads, &group, &inherit))
508                 return NULL;
509
510         if (pthreads != NULL)
511                 threads = ((struct pyrf_thread_map *)pthreads)->threads;
512
513         if (pcpus != NULL)
514                 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
515
516         evsel->attr.inherit = inherit;
517         if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
518                 PyErr_SetFromErrno(PyExc_OSError);
519                 return NULL;
520         }
521
522         Py_INCREF(Py_None);
523         return Py_None;
524 }
525
526 static PyMethodDef pyrf_evsel__methods[] = {
527         {
528                 .ml_name  = "open",
529                 .ml_meth  = (PyCFunction)pyrf_evsel__open,
530                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
531                 .ml_doc   = PyDoc_STR("open the event selector file descriptor table.")
532         },
533         { .ml_name = NULL, }
534 };
535
536 static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
537
538 static PyTypeObject pyrf_evsel__type = {
539         PyVarObject_HEAD_INIT(NULL, 0)
540         .tp_name        = "perf.evsel",
541         .tp_basicsize   = sizeof(struct pyrf_evsel),
542         .tp_dealloc     = (destructor)pyrf_evsel__delete,
543         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
544         .tp_doc         = pyrf_evsel__doc,
545         .tp_methods     = pyrf_evsel__methods,
546         .tp_init        = (initproc)pyrf_evsel__init,
547 };
548
549 static int pyrf_evsel__setup_types(void)
550 {
551         pyrf_evsel__type.tp_new = PyType_GenericNew;
552         return PyType_Ready(&pyrf_evsel__type);
553 }
554
555 struct pyrf_evlist {
556         PyObject_HEAD
557
558         struct perf_evlist evlist;
559 };
560
561 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
562                              PyObject *args, PyObject *kwargs __used)
563 {
564         PyObject *pcpus = NULL, *pthreads = NULL;
565         struct cpu_map *cpus;
566         struct thread_map *threads;
567
568         if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
569                 return -1;
570
571         threads = ((struct pyrf_thread_map *)pthreads)->threads;
572         cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
573         perf_evlist__init(&pevlist->evlist, cpus, threads);
574         return 0;
575 }
576
577 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
578 {
579         perf_evlist__exit(&pevlist->evlist);
580         pevlist->ob_type->tp_free((PyObject*)pevlist);
581 }
582
583 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
584                                    PyObject *args, PyObject *kwargs)
585 {
586         struct perf_evlist *evlist = &pevlist->evlist;
587         static char *kwlist[] = { "pages", "overwrite", NULL };
588         int pages = 128, overwrite = false;
589
590         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
591                                          &pages, &overwrite))
592                 return NULL;
593
594         if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
595                 PyErr_SetFromErrno(PyExc_OSError);
596                 return NULL;
597         }
598
599         Py_INCREF(Py_None);
600         return Py_None;
601 }
602
603 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
604                                    PyObject *args, PyObject *kwargs)
605 {
606         struct perf_evlist *evlist = &pevlist->evlist;
607         static char *kwlist[] = { "timeout", NULL };
608         int timeout = -1, n;
609
610         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
611                 return NULL;
612
613         n = poll(evlist->pollfd, evlist->nr_fds, timeout);
614         if (n < 0) {
615                 PyErr_SetFromErrno(PyExc_OSError);
616                 return NULL;
617         }
618
619         return Py_BuildValue("i", n);
620 }
621
622 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
623                                          PyObject *args __used, PyObject *kwargs __used)
624 {
625         struct perf_evlist *evlist = &pevlist->evlist;
626         PyObject *list = PyList_New(0);
627         int i;
628
629         for (i = 0; i < evlist->nr_fds; ++i) {
630                 PyObject *file;
631                 FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
632
633                 if (fp == NULL)
634                         goto free_list;
635
636                 file = PyFile_FromFile(fp, "perf", "r", NULL);
637                 if (file == NULL)
638                         goto free_list;
639
640                 if (PyList_Append(list, file) != 0) {
641                         Py_DECREF(file);
642                         goto free_list;
643                 }
644                         
645                 Py_DECREF(file);
646         }
647
648         return list;
649 free_list:
650         return PyErr_NoMemory();
651 }
652
653
654 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
655                                   PyObject *args, PyObject *kwargs __used)
656 {
657         struct perf_evlist *evlist = &pevlist->evlist;
658         PyObject *pevsel;
659         struct perf_evsel *evsel;
660
661         if (!PyArg_ParseTuple(args, "O", &pevsel))
662                 return NULL;
663
664         Py_INCREF(pevsel);
665         evsel = &((struct pyrf_evsel *)pevsel)->evsel;
666         evsel->idx = evlist->nr_entries;
667         perf_evlist__add(evlist, evsel);
668
669         return Py_BuildValue("i", evlist->nr_entries);
670 }
671
672 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
673                                           PyObject *args, PyObject *kwargs)
674 {
675         struct perf_evlist *evlist = &pevlist->evlist;
676         union perf_event *event;
677         int sample_id_all = 1, cpu;
678         static char *kwlist[] = { "cpu", "sample_id_all", NULL };
679         int err;
680
681         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
682                                          &cpu, &sample_id_all))
683                 return NULL;
684
685         event = perf_evlist__mmap_read(evlist, cpu);
686         if (event != NULL) {
687                 struct perf_evsel *first;
688                 PyObject *pyevent = pyrf_event__new(event);
689                 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
690
691                 if (pyevent == NULL)
692                         return PyErr_NoMemory();
693
694                 first = list_entry(evlist->entries.next, struct perf_evsel, node);
695                 err = perf_event__parse_sample(event, first->attr.sample_type,
696                                                perf_evsel__sample_size(first),
697                                                sample_id_all, &pevent->sample);
698                 if (err)
699                         return PyErr_Format(PyExc_OSError,
700                                             "perf: can't parse sample, err=%d", err);
701                 return pyevent;
702         }
703
704         Py_INCREF(Py_None);
705         return Py_None;
706 }
707
708 static PyMethodDef pyrf_evlist__methods[] = {
709         {
710                 .ml_name  = "mmap",
711                 .ml_meth  = (PyCFunction)pyrf_evlist__mmap,
712                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
713                 .ml_doc   = PyDoc_STR("mmap the file descriptor table.")
714         },
715         {
716                 .ml_name  = "poll",
717                 .ml_meth  = (PyCFunction)pyrf_evlist__poll,
718                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
719                 .ml_doc   = PyDoc_STR("poll the file descriptor table.")
720         },
721         {
722                 .ml_name  = "get_pollfd",
723                 .ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
724                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
725                 .ml_doc   = PyDoc_STR("get the poll file descriptor table.")
726         },
727         {
728                 .ml_name  = "add",
729                 .ml_meth  = (PyCFunction)pyrf_evlist__add,
730                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
731                 .ml_doc   = PyDoc_STR("adds an event selector to the list.")
732         },
733         {
734                 .ml_name  = "read_on_cpu",
735                 .ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
736                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
737                 .ml_doc   = PyDoc_STR("reads an event.")
738         },
739         { .ml_name = NULL, }
740 };
741
742 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
743 {
744         struct pyrf_evlist *pevlist = (void *)obj;
745
746         return pevlist->evlist.nr_entries;
747 }
748
749 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
750 {
751         struct pyrf_evlist *pevlist = (void *)obj;
752         struct perf_evsel *pos;
753
754         if (i >= pevlist->evlist.nr_entries)
755                 return NULL;
756
757         list_for_each_entry(pos, &pevlist->evlist.entries, node)
758                 if (i-- == 0)
759                         break;
760
761         return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
762 }
763
764 static PySequenceMethods pyrf_evlist__sequence_methods = {
765         .sq_length = pyrf_evlist__length,
766         .sq_item   = pyrf_evlist__item,
767 };
768
769 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
770
771 static PyTypeObject pyrf_evlist__type = {
772         PyVarObject_HEAD_INIT(NULL, 0)
773         .tp_name        = "perf.evlist",
774         .tp_basicsize   = sizeof(struct pyrf_evlist),
775         .tp_dealloc     = (destructor)pyrf_evlist__delete,
776         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
777         .tp_as_sequence = &pyrf_evlist__sequence_methods,
778         .tp_doc         = pyrf_evlist__doc,
779         .tp_methods     = pyrf_evlist__methods,
780         .tp_init        = (initproc)pyrf_evlist__init,
781 };
782
783 static int pyrf_evlist__setup_types(void)
784 {
785         pyrf_evlist__type.tp_new = PyType_GenericNew;
786         return PyType_Ready(&pyrf_evlist__type);
787 }
788
789 static struct {
790         const char *name;
791         int         value;
792 } perf__constants[] = {
793         { "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
794         { "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
795         { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
796         { "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
797         { "TYPE_RAW",        PERF_TYPE_RAW },
798         { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
799
800         { "COUNT_HW_CPU_CYCLES",          PERF_COUNT_HW_CPU_CYCLES },
801         { "COUNT_HW_INSTRUCTIONS",        PERF_COUNT_HW_INSTRUCTIONS },
802         { "COUNT_HW_CACHE_REFERENCES",    PERF_COUNT_HW_CACHE_REFERENCES },
803         { "COUNT_HW_CACHE_MISSES",        PERF_COUNT_HW_CACHE_MISSES },
804         { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
805         { "COUNT_HW_BRANCH_MISSES",       PERF_COUNT_HW_BRANCH_MISSES },
806         { "COUNT_HW_BUS_CYCLES",          PERF_COUNT_HW_BUS_CYCLES },
807         { "COUNT_HW_CACHE_L1D",           PERF_COUNT_HW_CACHE_L1D },
808         { "COUNT_HW_CACHE_L1I",           PERF_COUNT_HW_CACHE_L1I },
809         { "COUNT_HW_CACHE_LL",            PERF_COUNT_HW_CACHE_LL },
810         { "COUNT_HW_CACHE_DTLB",          PERF_COUNT_HW_CACHE_DTLB },
811         { "COUNT_HW_CACHE_ITLB",          PERF_COUNT_HW_CACHE_ITLB },
812         { "COUNT_HW_CACHE_BPU",           PERF_COUNT_HW_CACHE_BPU },
813         { "COUNT_HW_CACHE_OP_READ",       PERF_COUNT_HW_CACHE_OP_READ },
814         { "COUNT_HW_CACHE_OP_WRITE",      PERF_COUNT_HW_CACHE_OP_WRITE },
815         { "COUNT_HW_CACHE_OP_PREFETCH",   PERF_COUNT_HW_CACHE_OP_PREFETCH },
816         { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
817         { "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
818
819         { "COUNT_HW_STALLED_CYCLES_FRONTEND",     PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
820         { "COUNT_HW_STALLED_CYCLES_BACKEND",      PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
821
822         { "COUNT_SW_CPU_CLOCK",        PERF_COUNT_SW_CPU_CLOCK },
823         { "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
824         { "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
825         { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
826         { "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
827         { "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
828         { "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
829         { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
830         { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
831
832         { "SAMPLE_IP",        PERF_SAMPLE_IP },
833         { "SAMPLE_TID",       PERF_SAMPLE_TID },
834         { "SAMPLE_TIME",      PERF_SAMPLE_TIME },
835         { "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
836         { "SAMPLE_READ",      PERF_SAMPLE_READ },
837         { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
838         { "SAMPLE_ID",        PERF_SAMPLE_ID },
839         { "SAMPLE_CPU",       PERF_SAMPLE_CPU },
840         { "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
841         { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
842         { "SAMPLE_RAW",       PERF_SAMPLE_RAW },
843
844         { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
845         { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
846         { "FORMAT_ID",                 PERF_FORMAT_ID },
847         { "FORMAT_GROUP",              PERF_FORMAT_GROUP },
848
849         { "RECORD_MMAP",       PERF_RECORD_MMAP },
850         { "RECORD_LOST",       PERF_RECORD_LOST },
851         { "RECORD_COMM",       PERF_RECORD_COMM },
852         { "RECORD_EXIT",       PERF_RECORD_EXIT },
853         { "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
854         { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
855         { "RECORD_FORK",       PERF_RECORD_FORK },
856         { "RECORD_READ",       PERF_RECORD_READ },
857         { "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
858         { .name = NULL, },
859 };
860
861 static PyMethodDef perf__methods[] = {
862         { .ml_name = NULL, }
863 };
864
865 PyMODINIT_FUNC initperf(void)
866 {
867         PyObject *obj;
868         int i;
869         PyObject *dict, *module = Py_InitModule("perf", perf__methods);
870
871         if (module == NULL ||
872             pyrf_event__setup_types() < 0 ||
873             pyrf_evlist__setup_types() < 0 ||
874             pyrf_evsel__setup_types() < 0 ||
875             pyrf_thread_map__setup_types() < 0 ||
876             pyrf_cpu_map__setup_types() < 0)
877                 return;
878
879         Py_INCREF(&pyrf_evlist__type);
880         PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
881
882         Py_INCREF(&pyrf_evsel__type);
883         PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
884
885         Py_INCREF(&pyrf_thread_map__type);
886         PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
887
888         Py_INCREF(&pyrf_cpu_map__type);
889         PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
890
891         dict = PyModule_GetDict(module);
892         if (dict == NULL)
893                 goto error;
894
895         for (i = 0; perf__constants[i].name != NULL; i++) {
896                 obj = PyInt_FromLong(perf__constants[i].value);
897                 if (obj == NULL)
898                         goto error;
899                 PyDict_SetItemString(dict, perf__constants[i].name, obj);
900                 Py_DECREF(obj);
901         }
902
903 error:
904         if (PyErr_Occurred())
905                 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
906 }