perf python: Add PERF_RECORD_{LOST,READ,SAMPLE} routine tables
[linux-2.6.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 char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
191
192 static PyMemberDef pyrf_lost_event__members[] = {
193         sample_members
194         member_def(lost_event, id, T_ULONGLONG, "event id"),
195         member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
196         { .name = NULL, },
197 };
198
199 static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
200 {
201         PyObject *ret;
202         char *s;
203
204         if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
205                          "lost: %#" PRIx64 " }",
206                      pevent->event.lost.id, pevent->event.lost.lost) < 0) {
207                 ret = PyErr_NoMemory();
208         } else {
209                 ret = PyString_FromString(s);
210                 free(s);
211         }
212         return ret;
213 }
214
215 static PyTypeObject pyrf_lost_event__type = {
216         PyVarObject_HEAD_INIT(NULL, 0)
217         .tp_name        = "perf.lost_event",
218         .tp_basicsize   = sizeof(struct pyrf_event),
219         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
220         .tp_doc         = pyrf_lost_event__doc,
221         .tp_members     = pyrf_lost_event__members,
222         .tp_repr        = (reprfunc)pyrf_lost_event__repr,
223 };
224
225 static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
226
227 static PyMemberDef pyrf_read_event__members[] = {
228         sample_members
229         member_def(read_event, pid, T_UINT, "event pid"),
230         member_def(read_event, tid, T_UINT, "event tid"),
231         { .name = NULL, },
232 };
233
234 static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
235 {
236         return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
237                                    pevent->event.read.pid,
238                                    pevent->event.read.tid);
239         /*
240          * FIXME: return the array of read values,
241          * making this method useful ;-)
242          */
243 }
244
245 static PyTypeObject pyrf_read_event__type = {
246         PyVarObject_HEAD_INIT(NULL, 0)
247         .tp_name        = "perf.read_event",
248         .tp_basicsize   = sizeof(struct pyrf_event),
249         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
250         .tp_doc         = pyrf_read_event__doc,
251         .tp_members     = pyrf_read_event__members,
252         .tp_repr        = (reprfunc)pyrf_read_event__repr,
253 };
254
255 static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
256
257 static PyMemberDef pyrf_sample_event__members[] = {
258         sample_members
259         member_def(perf_event_header, type, T_UINT, "event type"),
260         { .name = NULL, },
261 };
262
263 static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
264 {
265         PyObject *ret;
266         char *s;
267
268         if (asprintf(&s, "{ type: sample }") < 0) {
269                 ret = PyErr_NoMemory();
270         } else {
271                 ret = PyString_FromString(s);
272                 free(s);
273         }
274         return ret;
275 }
276
277 static PyTypeObject pyrf_sample_event__type = {
278         PyVarObject_HEAD_INIT(NULL, 0)
279         .tp_name        = "perf.sample_event",
280         .tp_basicsize   = sizeof(struct pyrf_event),
281         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
282         .tp_doc         = pyrf_sample_event__doc,
283         .tp_members     = pyrf_sample_event__members,
284         .tp_repr        = (reprfunc)pyrf_sample_event__repr,
285 };
286
287 static int pyrf_event__setup_types(void)
288 {
289         int err;
290         pyrf_mmap_event__type.tp_new =
291         pyrf_task_event__type.tp_new =
292         pyrf_comm_event__type.tp_new =
293         pyrf_lost_event__type.tp_new =
294         pyrf_read_event__type.tp_new =
295         pyrf_sample_event__type.tp_new =
296         pyrf_throttle_event__type.tp_new = PyType_GenericNew;
297         err = PyType_Ready(&pyrf_mmap_event__type);
298         if (err < 0)
299                 goto out;
300         err = PyType_Ready(&pyrf_lost_event__type);
301         if (err < 0)
302                 goto out;
303         err = PyType_Ready(&pyrf_task_event__type);
304         if (err < 0)
305                 goto out;
306         err = PyType_Ready(&pyrf_comm_event__type);
307         if (err < 0)
308                 goto out;
309         err = PyType_Ready(&pyrf_throttle_event__type);
310         if (err < 0)
311                 goto out;
312         err = PyType_Ready(&pyrf_read_event__type);
313         if (err < 0)
314                 goto out;
315         err = PyType_Ready(&pyrf_sample_event__type);
316         if (err < 0)
317                 goto out;
318 out:
319         return err;
320 }
321
322 static PyTypeObject *pyrf_event__type[] = {
323         [PERF_RECORD_MMAP]       = &pyrf_mmap_event__type,
324         [PERF_RECORD_LOST]       = &pyrf_lost_event__type,
325         [PERF_RECORD_COMM]       = &pyrf_comm_event__type,
326         [PERF_RECORD_EXIT]       = &pyrf_task_event__type,
327         [PERF_RECORD_THROTTLE]   = &pyrf_throttle_event__type,
328         [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
329         [PERF_RECORD_FORK]       = &pyrf_task_event__type,
330         [PERF_RECORD_READ]       = &pyrf_read_event__type,
331         [PERF_RECORD_SAMPLE]     = &pyrf_sample_event__type,
332 };
333
334 static PyObject *pyrf_event__new(union perf_event *event)
335 {
336         struct pyrf_event *pevent;
337         PyTypeObject *ptype;
338
339         if (event->header.type < PERF_RECORD_MMAP ||
340             event->header.type > PERF_RECORD_SAMPLE)
341                 return NULL;
342
343         ptype = pyrf_event__type[event->header.type];
344         pevent = PyObject_New(struct pyrf_event, ptype);
345         if (pevent != NULL)
346                 memcpy(&pevent->event, event, event->header.size);
347         return (PyObject *)pevent;
348 }
349
350 struct pyrf_cpu_map {
351         PyObject_HEAD
352
353         struct cpu_map *cpus;
354 };
355
356 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
357                               PyObject *args, PyObject *kwargs)
358 {
359         static char *kwlist[] = { "cpustr", NULL };
360         char *cpustr = NULL;
361
362         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
363                                          kwlist, &cpustr))
364                 return -1;
365
366         pcpus->cpus = cpu_map__new(cpustr);
367         if (pcpus->cpus == NULL)
368                 return -1;
369         return 0;
370 }
371
372 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
373 {
374         cpu_map__delete(pcpus->cpus);
375         pcpus->ob_type->tp_free((PyObject*)pcpus);
376 }
377
378 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
379 {
380         struct pyrf_cpu_map *pcpus = (void *)obj;
381
382         return pcpus->cpus->nr;
383 }
384
385 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
386 {
387         struct pyrf_cpu_map *pcpus = (void *)obj;
388
389         if (i >= pcpus->cpus->nr)
390                 return NULL;
391
392         return Py_BuildValue("i", pcpus->cpus->map[i]);
393 }
394
395 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
396         .sq_length = pyrf_cpu_map__length,
397         .sq_item   = pyrf_cpu_map__item,
398 };
399
400 static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
401
402 static PyTypeObject pyrf_cpu_map__type = {
403         PyVarObject_HEAD_INIT(NULL, 0)
404         .tp_name        = "perf.cpu_map",
405         .tp_basicsize   = sizeof(struct pyrf_cpu_map),
406         .tp_dealloc     = (destructor)pyrf_cpu_map__delete,
407         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
408         .tp_doc         = pyrf_cpu_map__doc,
409         .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
410         .tp_init        = (initproc)pyrf_cpu_map__init,
411 };
412
413 static int pyrf_cpu_map__setup_types(void)
414 {
415         pyrf_cpu_map__type.tp_new = PyType_GenericNew;
416         return PyType_Ready(&pyrf_cpu_map__type);
417 }
418
419 struct pyrf_thread_map {
420         PyObject_HEAD
421
422         struct thread_map *threads;
423 };
424
425 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
426                                  PyObject *args, PyObject *kwargs)
427 {
428         static char *kwlist[] = { "pid", "tid", NULL };
429         int pid = -1, tid = -1;
430
431         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
432                                          kwlist, &pid, &tid))
433                 return -1;
434
435         pthreads->threads = thread_map__new(pid, tid);
436         if (pthreads->threads == NULL)
437                 return -1;
438         return 0;
439 }
440
441 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
442 {
443         thread_map__delete(pthreads->threads);
444         pthreads->ob_type->tp_free((PyObject*)pthreads);
445 }
446
447 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
448 {
449         struct pyrf_thread_map *pthreads = (void *)obj;
450
451         return pthreads->threads->nr;
452 }
453
454 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
455 {
456         struct pyrf_thread_map *pthreads = (void *)obj;
457
458         if (i >= pthreads->threads->nr)
459                 return NULL;
460
461         return Py_BuildValue("i", pthreads->threads->map[i]);
462 }
463
464 static PySequenceMethods pyrf_thread_map__sequence_methods = {
465         .sq_length = pyrf_thread_map__length,
466         .sq_item   = pyrf_thread_map__item,
467 };
468
469 static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
470
471 static PyTypeObject pyrf_thread_map__type = {
472         PyVarObject_HEAD_INIT(NULL, 0)
473         .tp_name        = "perf.thread_map",
474         .tp_basicsize   = sizeof(struct pyrf_thread_map),
475         .tp_dealloc     = (destructor)pyrf_thread_map__delete,
476         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
477         .tp_doc         = pyrf_thread_map__doc,
478         .tp_as_sequence = &pyrf_thread_map__sequence_methods,
479         .tp_init        = (initproc)pyrf_thread_map__init,
480 };
481
482 static int pyrf_thread_map__setup_types(void)
483 {
484         pyrf_thread_map__type.tp_new = PyType_GenericNew;
485         return PyType_Ready(&pyrf_thread_map__type);
486 }
487
488 struct pyrf_evsel {
489         PyObject_HEAD
490
491         struct perf_evsel evsel;
492 };
493
494 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
495                             PyObject *args, PyObject *kwargs)
496 {
497         struct perf_event_attr attr = {
498                 .type = PERF_TYPE_HARDWARE,
499                 .config = PERF_COUNT_HW_CPU_CYCLES,
500                 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
501         };
502         static char *kwlist[] = {
503                 "type",
504                 "config",
505                 "sample_freq",
506                 "sample_period",
507                 "sample_type",
508                 "read_format",
509                 "disabled",
510                 "inherit",
511                 "pinned",
512                 "exclusive",
513                 "exclude_user",
514                 "exclude_kernel",
515                 "exclude_hv",
516                 "exclude_idle",
517                 "mmap",
518                 "comm",
519                 "freq",
520                 "inherit_stat",
521                 "enable_on_exec",
522                 "task",
523                 "watermark",
524                 "precise_ip",
525                 "mmap_data",
526                 "sample_id_all",
527                 "wakeup_events",
528                 "bp_type",
529                 "bp_addr",
530                 "bp_len",
531                  NULL
532         };
533         u64 sample_period = 0;
534         u32 disabled = 0,
535             inherit = 0,
536             pinned = 0,
537             exclusive = 0,
538             exclude_user = 0,
539             exclude_kernel = 0,
540             exclude_hv = 0,
541             exclude_idle = 0,
542             mmap = 0,
543             comm = 0,
544             freq = 1,
545             inherit_stat = 0,
546             enable_on_exec = 0,
547             task = 0,
548             watermark = 0,
549             precise_ip = 0,
550             mmap_data = 0,
551             sample_id_all = 1;
552         int idx = 0;
553
554         if (!PyArg_ParseTupleAndKeywords(args, kwargs,
555                                          "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
556                                          &attr.type, &attr.config, &attr.sample_freq,
557                                          &sample_period, &attr.sample_type,
558                                          &attr.read_format, &disabled, &inherit,
559                                          &pinned, &exclusive, &exclude_user,
560                                          &exclude_kernel, &exclude_hv, &exclude_idle,
561                                          &mmap, &comm, &freq, &inherit_stat,
562                                          &enable_on_exec, &task, &watermark,
563                                          &precise_ip, &mmap_data, &sample_id_all,
564                                          &attr.wakeup_events, &attr.bp_type,
565                                          &attr.bp_addr, &attr.bp_len, &idx))
566                 return -1;
567
568         /* union... */
569         if (sample_period != 0) {
570                 if (attr.sample_freq != 0)
571                         return -1; /* FIXME: throw right exception */
572                 attr.sample_period = sample_period;
573         }
574
575         /* Bitfields */
576         attr.disabled       = disabled;
577         attr.inherit        = inherit;
578         attr.pinned         = pinned;
579         attr.exclusive      = exclusive;
580         attr.exclude_user   = exclude_user;
581         attr.exclude_kernel = exclude_kernel;
582         attr.exclude_hv     = exclude_hv;
583         attr.exclude_idle   = exclude_idle;
584         attr.mmap           = mmap;
585         attr.comm           = comm;
586         attr.freq           = freq;
587         attr.inherit_stat   = inherit_stat;
588         attr.enable_on_exec = enable_on_exec;
589         attr.task           = task;
590         attr.watermark      = watermark;
591         attr.precise_ip     = precise_ip;
592         attr.mmap_data      = mmap_data;
593         attr.sample_id_all  = sample_id_all;
594
595         perf_evsel__init(&pevsel->evsel, &attr, idx);
596         return 0;
597 }
598
599 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
600 {
601         perf_evsel__exit(&pevsel->evsel);
602         pevsel->ob_type->tp_free((PyObject*)pevsel);
603 }
604
605 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
606                                   PyObject *args, PyObject *kwargs)
607 {
608         struct perf_evsel *evsel = &pevsel->evsel;
609         struct cpu_map *cpus = NULL;
610         struct thread_map *threads = NULL;
611         PyObject *pcpus = NULL, *pthreads = NULL;
612         int group = 0, inherit = 0;
613         static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
614
615         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
616                                          &pcpus, &pthreads, &group, &inherit))
617                 return NULL;
618
619         if (pthreads != NULL)
620                 threads = ((struct pyrf_thread_map *)pthreads)->threads;
621
622         if (pcpus != NULL)
623                 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
624
625         evsel->attr.inherit = inherit;
626         if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
627                 PyErr_SetFromErrno(PyExc_OSError);
628                 return NULL;
629         }
630
631         Py_INCREF(Py_None);
632         return Py_None;
633 }
634
635 static PyMethodDef pyrf_evsel__methods[] = {
636         {
637                 .ml_name  = "open",
638                 .ml_meth  = (PyCFunction)pyrf_evsel__open,
639                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
640                 .ml_doc   = PyDoc_STR("open the event selector file descriptor table.")
641         },
642         { .ml_name = NULL, }
643 };
644
645 static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
646
647 static PyTypeObject pyrf_evsel__type = {
648         PyVarObject_HEAD_INIT(NULL, 0)
649         .tp_name        = "perf.evsel",
650         .tp_basicsize   = sizeof(struct pyrf_evsel),
651         .tp_dealloc     = (destructor)pyrf_evsel__delete,
652         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
653         .tp_doc         = pyrf_evsel__doc,
654         .tp_methods     = pyrf_evsel__methods,
655         .tp_init        = (initproc)pyrf_evsel__init,
656 };
657
658 static int pyrf_evsel__setup_types(void)
659 {
660         pyrf_evsel__type.tp_new = PyType_GenericNew;
661         return PyType_Ready(&pyrf_evsel__type);
662 }
663
664 struct pyrf_evlist {
665         PyObject_HEAD
666
667         struct perf_evlist evlist;
668 };
669
670 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
671                              PyObject *args, PyObject *kwargs __used)
672 {
673         PyObject *pcpus = NULL, *pthreads = NULL;
674         struct cpu_map *cpus;
675         struct thread_map *threads;
676
677         if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
678                 return -1;
679
680         threads = ((struct pyrf_thread_map *)pthreads)->threads;
681         cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
682         perf_evlist__init(&pevlist->evlist, cpus, threads);
683         return 0;
684 }
685
686 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
687 {
688         perf_evlist__exit(&pevlist->evlist);
689         pevlist->ob_type->tp_free((PyObject*)pevlist);
690 }
691
692 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
693                                    PyObject *args, PyObject *kwargs)
694 {
695         struct perf_evlist *evlist = &pevlist->evlist;
696         static char *kwlist[] = { "pages", "overwrite", NULL };
697         int pages = 128, overwrite = false;
698
699         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
700                                          &pages, &overwrite))
701                 return NULL;
702
703         if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
704                 PyErr_SetFromErrno(PyExc_OSError);
705                 return NULL;
706         }
707
708         Py_INCREF(Py_None);
709         return Py_None;
710 }
711
712 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
713                                    PyObject *args, PyObject *kwargs)
714 {
715         struct perf_evlist *evlist = &pevlist->evlist;
716         static char *kwlist[] = { "timeout", NULL };
717         int timeout = -1, n;
718
719         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
720                 return NULL;
721
722         n = poll(evlist->pollfd, evlist->nr_fds, timeout);
723         if (n < 0) {
724                 PyErr_SetFromErrno(PyExc_OSError);
725                 return NULL;
726         }
727
728         return Py_BuildValue("i", n);
729 }
730
731 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
732                                          PyObject *args __used, PyObject *kwargs __used)
733 {
734         struct perf_evlist *evlist = &pevlist->evlist;
735         PyObject *list = PyList_New(0);
736         int i;
737
738         for (i = 0; i < evlist->nr_fds; ++i) {
739                 PyObject *file;
740                 FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
741
742                 if (fp == NULL)
743                         goto free_list;
744
745                 file = PyFile_FromFile(fp, "perf", "r", NULL);
746                 if (file == NULL)
747                         goto free_list;
748
749                 if (PyList_Append(list, file) != 0) {
750                         Py_DECREF(file);
751                         goto free_list;
752                 }
753                         
754                 Py_DECREF(file);
755         }
756
757         return list;
758 free_list:
759         return PyErr_NoMemory();
760 }
761
762
763 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
764                                   PyObject *args, PyObject *kwargs __used)
765 {
766         struct perf_evlist *evlist = &pevlist->evlist;
767         PyObject *pevsel;
768         struct perf_evsel *evsel;
769
770         if (!PyArg_ParseTuple(args, "O", &pevsel))
771                 return NULL;
772
773         Py_INCREF(pevsel);
774         evsel = &((struct pyrf_evsel *)pevsel)->evsel;
775         evsel->idx = evlist->nr_entries;
776         perf_evlist__add(evlist, evsel);
777
778         return Py_BuildValue("i", evlist->nr_entries);
779 }
780
781 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
782                                           PyObject *args, PyObject *kwargs)
783 {
784         struct perf_evlist *evlist = &pevlist->evlist;
785         union perf_event *event;
786         int sample_id_all = 1, cpu;
787         static char *kwlist[] = { "cpu", "sample_id_all", NULL };
788         int err;
789
790         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
791                                          &cpu, &sample_id_all))
792                 return NULL;
793
794         event = perf_evlist__mmap_read(evlist, cpu);
795         if (event != NULL) {
796                 struct perf_evsel *first;
797                 PyObject *pyevent = pyrf_event__new(event);
798                 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
799
800                 if (pyevent == NULL)
801                         return PyErr_NoMemory();
802
803                 first = list_entry(evlist->entries.next, struct perf_evsel, node);
804                 err = perf_event__parse_sample(event, first->attr.sample_type,
805                                                perf_evsel__sample_size(first),
806                                                sample_id_all, &pevent->sample);
807                 if (err)
808                         return PyErr_Format(PyExc_OSError,
809                                             "perf: can't parse sample, err=%d", err);
810                 return pyevent;
811         }
812
813         Py_INCREF(Py_None);
814         return Py_None;
815 }
816
817 static PyMethodDef pyrf_evlist__methods[] = {
818         {
819                 .ml_name  = "mmap",
820                 .ml_meth  = (PyCFunction)pyrf_evlist__mmap,
821                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
822                 .ml_doc   = PyDoc_STR("mmap the file descriptor table.")
823         },
824         {
825                 .ml_name  = "poll",
826                 .ml_meth  = (PyCFunction)pyrf_evlist__poll,
827                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
828                 .ml_doc   = PyDoc_STR("poll the file descriptor table.")
829         },
830         {
831                 .ml_name  = "get_pollfd",
832                 .ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
833                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
834                 .ml_doc   = PyDoc_STR("get the poll file descriptor table.")
835         },
836         {
837                 .ml_name  = "add",
838                 .ml_meth  = (PyCFunction)pyrf_evlist__add,
839                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
840                 .ml_doc   = PyDoc_STR("adds an event selector to the list.")
841         },
842         {
843                 .ml_name  = "read_on_cpu",
844                 .ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
845                 .ml_flags = METH_VARARGS | METH_KEYWORDS,
846                 .ml_doc   = PyDoc_STR("reads an event.")
847         },
848         { .ml_name = NULL, }
849 };
850
851 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
852 {
853         struct pyrf_evlist *pevlist = (void *)obj;
854
855         return pevlist->evlist.nr_entries;
856 }
857
858 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
859 {
860         struct pyrf_evlist *pevlist = (void *)obj;
861         struct perf_evsel *pos;
862
863         if (i >= pevlist->evlist.nr_entries)
864                 return NULL;
865
866         list_for_each_entry(pos, &pevlist->evlist.entries, node)
867                 if (i-- == 0)
868                         break;
869
870         return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
871 }
872
873 static PySequenceMethods pyrf_evlist__sequence_methods = {
874         .sq_length = pyrf_evlist__length,
875         .sq_item   = pyrf_evlist__item,
876 };
877
878 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
879
880 static PyTypeObject pyrf_evlist__type = {
881         PyVarObject_HEAD_INIT(NULL, 0)
882         .tp_name        = "perf.evlist",
883         .tp_basicsize   = sizeof(struct pyrf_evlist),
884         .tp_dealloc     = (destructor)pyrf_evlist__delete,
885         .tp_flags       = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
886         .tp_as_sequence = &pyrf_evlist__sequence_methods,
887         .tp_doc         = pyrf_evlist__doc,
888         .tp_methods     = pyrf_evlist__methods,
889         .tp_init        = (initproc)pyrf_evlist__init,
890 };
891
892 static int pyrf_evlist__setup_types(void)
893 {
894         pyrf_evlist__type.tp_new = PyType_GenericNew;
895         return PyType_Ready(&pyrf_evlist__type);
896 }
897
898 static struct {
899         const char *name;
900         int         value;
901 } perf__constants[] = {
902         { "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
903         { "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
904         { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
905         { "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
906         { "TYPE_RAW",        PERF_TYPE_RAW },
907         { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
908
909         { "COUNT_HW_CPU_CYCLES",          PERF_COUNT_HW_CPU_CYCLES },
910         { "COUNT_HW_INSTRUCTIONS",        PERF_COUNT_HW_INSTRUCTIONS },
911         { "COUNT_HW_CACHE_REFERENCES",    PERF_COUNT_HW_CACHE_REFERENCES },
912         { "COUNT_HW_CACHE_MISSES",        PERF_COUNT_HW_CACHE_MISSES },
913         { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
914         { "COUNT_HW_BRANCH_MISSES",       PERF_COUNT_HW_BRANCH_MISSES },
915         { "COUNT_HW_BUS_CYCLES",          PERF_COUNT_HW_BUS_CYCLES },
916         { "COUNT_HW_CACHE_L1D",           PERF_COUNT_HW_CACHE_L1D },
917         { "COUNT_HW_CACHE_L1I",           PERF_COUNT_HW_CACHE_L1I },
918         { "COUNT_HW_CACHE_LL",            PERF_COUNT_HW_CACHE_LL },
919         { "COUNT_HW_CACHE_DTLB",          PERF_COUNT_HW_CACHE_DTLB },
920         { "COUNT_HW_CACHE_ITLB",          PERF_COUNT_HW_CACHE_ITLB },
921         { "COUNT_HW_CACHE_BPU",           PERF_COUNT_HW_CACHE_BPU },
922         { "COUNT_HW_CACHE_OP_READ",       PERF_COUNT_HW_CACHE_OP_READ },
923         { "COUNT_HW_CACHE_OP_WRITE",      PERF_COUNT_HW_CACHE_OP_WRITE },
924         { "COUNT_HW_CACHE_OP_PREFETCH",   PERF_COUNT_HW_CACHE_OP_PREFETCH },
925         { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
926         { "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
927
928         { "COUNT_HW_STALLED_CYCLES_FRONTEND",     PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
929         { "COUNT_HW_STALLED_CYCLES_BACKEND",      PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
930
931         { "COUNT_SW_CPU_CLOCK",        PERF_COUNT_SW_CPU_CLOCK },
932         { "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
933         { "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
934         { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
935         { "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
936         { "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
937         { "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
938         { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
939         { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
940
941         { "SAMPLE_IP",        PERF_SAMPLE_IP },
942         { "SAMPLE_TID",       PERF_SAMPLE_TID },
943         { "SAMPLE_TIME",      PERF_SAMPLE_TIME },
944         { "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
945         { "SAMPLE_READ",      PERF_SAMPLE_READ },
946         { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
947         { "SAMPLE_ID",        PERF_SAMPLE_ID },
948         { "SAMPLE_CPU",       PERF_SAMPLE_CPU },
949         { "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
950         { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
951         { "SAMPLE_RAW",       PERF_SAMPLE_RAW },
952
953         { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
954         { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
955         { "FORMAT_ID",                 PERF_FORMAT_ID },
956         { "FORMAT_GROUP",              PERF_FORMAT_GROUP },
957
958         { "RECORD_MMAP",       PERF_RECORD_MMAP },
959         { "RECORD_LOST",       PERF_RECORD_LOST },
960         { "RECORD_COMM",       PERF_RECORD_COMM },
961         { "RECORD_EXIT",       PERF_RECORD_EXIT },
962         { "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
963         { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
964         { "RECORD_FORK",       PERF_RECORD_FORK },
965         { "RECORD_READ",       PERF_RECORD_READ },
966         { "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
967         { .name = NULL, },
968 };
969
970 static PyMethodDef perf__methods[] = {
971         { .ml_name = NULL, }
972 };
973
974 PyMODINIT_FUNC initperf(void)
975 {
976         PyObject *obj;
977         int i;
978         PyObject *dict, *module = Py_InitModule("perf", perf__methods);
979
980         if (module == NULL ||
981             pyrf_event__setup_types() < 0 ||
982             pyrf_evlist__setup_types() < 0 ||
983             pyrf_evsel__setup_types() < 0 ||
984             pyrf_thread_map__setup_types() < 0 ||
985             pyrf_cpu_map__setup_types() < 0)
986                 return;
987
988         Py_INCREF(&pyrf_evlist__type);
989         PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
990
991         Py_INCREF(&pyrf_evsel__type);
992         PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
993
994         Py_INCREF(&pyrf_thread_map__type);
995         PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
996
997         Py_INCREF(&pyrf_cpu_map__type);
998         PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
999
1000         dict = PyModule_GetDict(module);
1001         if (dict == NULL)
1002                 goto error;
1003
1004         for (i = 0; perf__constants[i].name != NULL; i++) {
1005                 obj = PyInt_FromLong(perf__constants[i].value);
1006                 if (obj == NULL)
1007                         goto error;
1008                 PyDict_SetItemString(dict, perf__constants[i].name, obj);
1009                 Py_DECREF(obj);
1010         }
1011
1012 error:
1013         if (PyErr_Occurred())
1014                 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1015 }