Merge branch 'for-linus' of git://www.jni.nu/cris
[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, 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, 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", NULL, NULL, };
422         u64 sample_period = 0;
423         u32 disabled = 0,
424             inherit = 0,
425             pinned = 0,
426             exclusive = 0,
427             exclude_user = 0,
428             exclude_kernel = 0,
429             exclude_hv = 0,
430             exclude_idle = 0,
431             mmap = 0,
432             comm = 0,
433             freq = 1,
434             inherit_stat = 0,
435             enable_on_exec = 0,
436             task = 0,
437             watermark = 0,
438             precise_ip = 0,
439             mmap_data = 0,
440             sample_id_all = 1;
441         int idx = 0;
442
443         if (!PyArg_ParseTupleAndKeywords(args, kwargs,
444                                          "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
445                                          &attr.type, &attr.config, &attr.sample_freq,
446                                          &sample_period, &attr.sample_type,
447                                          &attr.read_format, &disabled, &inherit,
448                                          &pinned, &exclusive, &exclude_user,
449                                          &exclude_kernel, &exclude_hv, &exclude_idle,
450                                          &mmap, &comm, &freq, &inherit_stat,
451                                          &enable_on_exec, &task, &watermark,
452                                          &precise_ip, &mmap_data, &sample_id_all,
453                                          &attr.wakeup_events, &attr.bp_type,
454                                          &attr.bp_addr, &attr.bp_len, &idx))
455                 return -1;
456
457         /* union... */
458         if (sample_period != 0) {
459                 if (attr.sample_freq != 0)
460                         return -1; /* FIXME: throw right exception */
461                 attr.sample_period = sample_period;
462         }
463
464         /* Bitfields */
465         attr.disabled       = disabled;
466         attr.inherit        = inherit;
467         attr.pinned         = pinned;
468         attr.exclusive      = exclusive;
469         attr.exclude_user   = exclude_user;
470         attr.exclude_kernel = exclude_kernel;
471         attr.exclude_hv     = exclude_hv;
472         attr.exclude_idle   = exclude_idle;
473         attr.mmap           = mmap;
474         attr.comm           = comm;
475         attr.freq           = freq;
476         attr.inherit_stat   = inherit_stat;
477         attr.enable_on_exec = enable_on_exec;
478         attr.task           = task;
479         attr.watermark      = watermark;
480         attr.precise_ip     = precise_ip;
481         attr.mmap_data      = mmap_data;
482         attr.sample_id_all  = sample_id_all;
483
484         perf_evsel__init(&pevsel->evsel, &attr, idx);
485         return 0;
486 }
487
488 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
489 {
490         perf_evsel__exit(&pevsel->evsel);
491         pevsel->ob_type->tp_free((PyObject*)pevsel);
492 }
493
494 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
495                                   PyObject *args, PyObject *kwargs)
496 {
497         struct perf_evsel *evsel = &pevsel->evsel;
498         struct cpu_map *cpus = NULL;
499         struct thread_map *threads = NULL;
500         PyObject *pcpus = NULL, *pthreads = NULL;
501         int group = 0, overwrite = 0;
502         static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
503
504         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
505                                          &pcpus, &pthreads, &group, &overwrite))
506                 return NULL;
507
508         if (pthreads != NULL)
509                 threads = ((struct pyrf_thread_map *)pthreads)->threads;
510
511         if (pcpus != NULL)
512                 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
513
514         if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
515                 PyErr_SetFromErrno(PyExc_OSError);
516                 return NULL;
517         }
518
519         Py_INCREF(Py_None);
520         return Py_None;
521 }
522
523 static PyMethodDef pyrf_evsel__methods[] = {
524         {
525                 .ml_name  = "open",
526                 .ml_meth  = (PyCFunction)pyrf_evsel__open,
527                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
528                 .ml_doc   = PyDoc_STR("open the event selector file descriptor table.")
529         },
530         { .ml_name = NULL, }
531 };
532
533 static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
534
535 static PyTypeObject pyrf_evsel__type = {
536         PyVarObject_HEAD_INIT(NULL, 0)
537         .tp_name        = "perf.evsel",
538         .tp_basicsize   = sizeof(struct pyrf_evsel),
539         .tp_dealloc     = (destructor)pyrf_evsel__delete,
540         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
541         .tp_doc         = pyrf_evsel__doc,
542         .tp_methods     = pyrf_evsel__methods,
543         .tp_init        = (initproc)pyrf_evsel__init,
544 };
545
546 static int pyrf_evsel__setup_types(void)
547 {
548         pyrf_evsel__type.tp_new = PyType_GenericNew;
549         return PyType_Ready(&pyrf_evsel__type);
550 }
551
552 struct pyrf_evlist {
553         PyObject_HEAD
554
555         struct perf_evlist evlist;
556 };
557
558 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
559                              PyObject *args, PyObject *kwargs __used)
560 {
561         PyObject *pcpus = NULL, *pthreads = NULL;
562         struct cpu_map *cpus;
563         struct thread_map *threads;
564
565         if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
566                 return -1;
567
568         threads = ((struct pyrf_thread_map *)pthreads)->threads;
569         cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
570         perf_evlist__init(&pevlist->evlist, cpus, threads);
571         return 0;
572 }
573
574 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
575 {
576         perf_evlist__exit(&pevlist->evlist);
577         pevlist->ob_type->tp_free((PyObject*)pevlist);
578 }
579
580 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
581                                    PyObject *args, PyObject *kwargs)
582 {
583         struct perf_evlist *evlist = &pevlist->evlist;
584         static char *kwlist[] = {"pages", "overwrite",
585                                   NULL, NULL};
586         int pages = 128, overwrite = false;
587
588         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
589                                          &pages, &overwrite))
590                 return NULL;
591
592         if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
593                 PyErr_SetFromErrno(PyExc_OSError);
594                 return NULL;
595         }
596
597         Py_INCREF(Py_None);
598         return Py_None;
599 }
600
601 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
602                                    PyObject *args, PyObject *kwargs)
603 {
604         struct perf_evlist *evlist = &pevlist->evlist;
605         static char *kwlist[] = {"timeout", NULL, NULL};
606         int timeout = -1, n;
607
608         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
609                 return NULL;
610
611         n = poll(evlist->pollfd, evlist->nr_fds, timeout);
612         if (n < 0) {
613                 PyErr_SetFromErrno(PyExc_OSError);
614                 return NULL;
615         }
616
617         return Py_BuildValue("i", n);
618 }
619
620 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
621                                          PyObject *args __used, PyObject *kwargs __used)
622 {
623         struct perf_evlist *evlist = &pevlist->evlist;
624         PyObject *list = PyList_New(0);
625         int i;
626
627         for (i = 0; i < evlist->nr_fds; ++i) {
628                 PyObject *file;
629                 FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
630
631                 if (fp == NULL)
632                         goto free_list;
633
634                 file = PyFile_FromFile(fp, "perf", "r", NULL);
635                 if (file == NULL)
636                         goto free_list;
637
638                 if (PyList_Append(list, file) != 0) {
639                         Py_DECREF(file);
640                         goto free_list;
641                 }
642                         
643                 Py_DECREF(file);
644         }
645
646         return list;
647 free_list:
648         return PyErr_NoMemory();
649 }
650
651
652 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
653                                   PyObject *args, PyObject *kwargs __used)
654 {
655         struct perf_evlist *evlist = &pevlist->evlist;
656         PyObject *pevsel;
657         struct perf_evsel *evsel;
658
659         if (!PyArg_ParseTuple(args, "O", &pevsel))
660                 return NULL;
661
662         Py_INCREF(pevsel);
663         evsel = &((struct pyrf_evsel *)pevsel)->evsel;
664         evsel->idx = evlist->nr_entries;
665         perf_evlist__add(evlist, evsel);
666
667         return Py_BuildValue("i", evlist->nr_entries);
668 }
669
670 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
671                                           PyObject *args, PyObject *kwargs)
672 {
673         struct perf_evlist *evlist = &pevlist->evlist;
674         union perf_event *event;
675         int sample_id_all = 1, cpu;
676         static char *kwlist[] = {"sample_id_all", NULL, NULL};
677
678         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
679                                          &cpu, &sample_id_all))
680                 return NULL;
681
682         event = perf_evlist__read_on_cpu(evlist, cpu);
683         if (event != NULL) {
684                 struct perf_evsel *first;
685                 PyObject *pyevent = pyrf_event__new(event);
686                 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
687
688                 if (pyevent == NULL)
689                         return PyErr_NoMemory();
690
691                 first = list_entry(evlist->entries.next, struct perf_evsel, node);
692                 perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
693                                          &pevent->sample);
694                 return pyevent;
695         }
696
697         Py_INCREF(Py_None);
698         return Py_None;
699 }
700
701 static PyMethodDef pyrf_evlist__methods[] = {
702         {
703                 .ml_name  = "mmap",
704                 .ml_meth  = (PyCFunction)pyrf_evlist__mmap,
705                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
706                 .ml_doc   = PyDoc_STR("mmap the file descriptor table.")
707         },
708         {
709                 .ml_name  = "poll",
710                 .ml_meth  = (PyCFunction)pyrf_evlist__poll,
711                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
712                 .ml_doc   = PyDoc_STR("poll the file descriptor table.")
713         },
714         {
715                 .ml_name  = "get_pollfd",
716                 .ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
717                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
718                 .ml_doc   = PyDoc_STR("get the poll file descriptor table.")
719         },
720         {
721                 .ml_name  = "add",
722                 .ml_meth  = (PyCFunction)pyrf_evlist__add,
723                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
724                 .ml_doc   = PyDoc_STR("adds an event selector to the list.")
725         },
726         {
727                 .ml_name  = "read_on_cpu",
728                 .ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
729                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
730                 .ml_doc   = PyDoc_STR("reads an event.")
731         },
732         { .ml_name = NULL, }
733 };
734
735 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
736 {
737         struct pyrf_evlist *pevlist = (void *)obj;
738
739         return pevlist->evlist.nr_entries;
740 }
741
742 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
743 {
744         struct pyrf_evlist *pevlist = (void *)obj;
745         struct perf_evsel *pos;
746
747         if (i >= pevlist->evlist.nr_entries)
748                 return NULL;
749
750         list_for_each_entry(pos, &pevlist->evlist.entries, node)
751                 if (i-- == 0)
752                         break;
753
754         return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
755 }
756
757 static PySequenceMethods pyrf_evlist__sequence_methods = {
758         .sq_length = pyrf_evlist__length,
759         .sq_item   = pyrf_evlist__item,
760 };
761
762 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
763
764 static PyTypeObject pyrf_evlist__type = {
765         PyVarObject_HEAD_INIT(NULL, 0)
766         .tp_name        = "perf.evlist",
767         .tp_basicsize   = sizeof(struct pyrf_evlist),
768         .tp_dealloc     = (destructor)pyrf_evlist__delete,
769         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
770         .tp_as_sequence = &pyrf_evlist__sequence_methods,
771         .tp_doc         = pyrf_evlist__doc,
772         .tp_methods     = pyrf_evlist__methods,
773         .tp_init        = (initproc)pyrf_evlist__init,
774 };
775
776 static int pyrf_evlist__setup_types(void)
777 {
778         pyrf_evlist__type.tp_new = PyType_GenericNew;
779         return PyType_Ready(&pyrf_evlist__type);
780 }
781
782 static struct {
783         const char *name;
784         int         value;
785 } perf__constants[] = {
786         { "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
787         { "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
788         { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
789         { "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
790         { "TYPE_RAW",        PERF_TYPE_RAW },
791         { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
792
793         { "COUNT_HW_CPU_CYCLES",          PERF_COUNT_HW_CPU_CYCLES },
794         { "COUNT_HW_INSTRUCTIONS",        PERF_COUNT_HW_INSTRUCTIONS },
795         { "COUNT_HW_CACHE_REFERENCES",    PERF_COUNT_HW_CACHE_REFERENCES },
796         { "COUNT_HW_CACHE_MISSES",        PERF_COUNT_HW_CACHE_MISSES },
797         { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
798         { "COUNT_HW_BRANCH_MISSES",       PERF_COUNT_HW_BRANCH_MISSES },
799         { "COUNT_HW_BUS_CYCLES",          PERF_COUNT_HW_BUS_CYCLES },
800         { "COUNT_HW_CACHE_L1D",           PERF_COUNT_HW_CACHE_L1D },
801         { "COUNT_HW_CACHE_L1I",           PERF_COUNT_HW_CACHE_L1I },
802         { "COUNT_HW_CACHE_LL",            PERF_COUNT_HW_CACHE_LL },
803         { "COUNT_HW_CACHE_DTLB",          PERF_COUNT_HW_CACHE_DTLB },
804         { "COUNT_HW_CACHE_ITLB",          PERF_COUNT_HW_CACHE_ITLB },
805         { "COUNT_HW_CACHE_BPU",           PERF_COUNT_HW_CACHE_BPU },
806         { "COUNT_HW_CACHE_OP_READ",       PERF_COUNT_HW_CACHE_OP_READ },
807         { "COUNT_HW_CACHE_OP_WRITE",      PERF_COUNT_HW_CACHE_OP_WRITE },
808         { "COUNT_HW_CACHE_OP_PREFETCH",   PERF_COUNT_HW_CACHE_OP_PREFETCH },
809         { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
810         { "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
811
812         { "COUNT_SW_CPU_CLOCK",        PERF_COUNT_SW_CPU_CLOCK },
813         { "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
814         { "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
815         { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
816         { "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
817         { "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
818         { "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
819         { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
820         { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
821
822         { "SAMPLE_IP",        PERF_SAMPLE_IP },
823         { "SAMPLE_TID",       PERF_SAMPLE_TID },
824         { "SAMPLE_TIME",      PERF_SAMPLE_TIME },
825         { "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
826         { "SAMPLE_READ",      PERF_SAMPLE_READ },
827         { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
828         { "SAMPLE_ID",        PERF_SAMPLE_ID },
829         { "SAMPLE_CPU",       PERF_SAMPLE_CPU },
830         { "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
831         { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
832         { "SAMPLE_RAW",       PERF_SAMPLE_RAW },
833
834         { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
835         { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
836         { "FORMAT_ID",                 PERF_FORMAT_ID },
837         { "FORMAT_GROUP",              PERF_FORMAT_GROUP },
838
839         { "RECORD_MMAP",       PERF_RECORD_MMAP },
840         { "RECORD_LOST",       PERF_RECORD_LOST },
841         { "RECORD_COMM",       PERF_RECORD_COMM },
842         { "RECORD_EXIT",       PERF_RECORD_EXIT },
843         { "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
844         { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
845         { "RECORD_FORK",       PERF_RECORD_FORK },
846         { "RECORD_READ",       PERF_RECORD_READ },
847         { "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
848         { .name = NULL, },
849 };
850
851 static PyMethodDef perf__methods[] = {
852         { .ml_name = NULL, }
853 };
854
855 PyMODINIT_FUNC initperf(void)
856 {
857         PyObject *obj;
858         int i;
859         PyObject *dict, *module = Py_InitModule("perf", perf__methods);
860
861         if (module == NULL ||
862             pyrf_event__setup_types() < 0 ||
863             pyrf_evlist__setup_types() < 0 ||
864             pyrf_evsel__setup_types() < 0 ||
865             pyrf_thread_map__setup_types() < 0 ||
866             pyrf_cpu_map__setup_types() < 0)
867                 return;
868
869         Py_INCREF(&pyrf_evlist__type);
870         PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
871
872         Py_INCREF(&pyrf_evsel__type);
873         PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
874
875         Py_INCREF(&pyrf_thread_map__type);
876         PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
877
878         Py_INCREF(&pyrf_cpu_map__type);
879         PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
880
881         dict = PyModule_GetDict(module);
882         if (dict == NULL)
883                 goto error;
884
885         for (i = 0; perf__constants[i].name != NULL; i++) {
886                 obj = PyInt_FromLong(perf__constants[i].value);
887                 if (obj == NULL)
888                         goto error;
889                 PyDict_SetItemString(dict, perf__constants[i].name, obj);
890                 Py_DECREF(obj);
891         }
892
893 error:
894         if (PyErr_Occurred())
895                 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
896 }