]>
Commit | Line | Data |
---|---|---|
877108e4 ACM |
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 | ||
cfff2d90 FW |
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 | ||
877108e4 ACM |
16 | struct throttle_event { |
17 | struct perf_event_header header; | |
18 | u64 time; | |
19 | u64 id; | |
20 | u64 stream_id; | |
21 | }; | |
22 | ||
f6bbc1da ACM |
23 | PyMODINIT_FUNC initperf(void); |
24 | ||
877108e4 ACM |
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 | ||
877108e4 | 41 | #define sample_members \ |
f6bbc1da | 42 | sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \ |
877108e4 ACM |
43 | sample_member_def(sample_pid, pid, T_INT, "event pid"), \ |
44 | sample_member_def(sample_tid, tid, T_INT, "event tid"), \ | |
f6bbc1da ACM |
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"), \ | |
877108e4 ACM |
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"), | |
f6bbc1da ACM |
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"), | |
877108e4 | 62 | member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"), |
f6bbc1da | 63 | { .name = NULL, }, |
877108e4 ACM |
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"), | |
f6bbc1da ACM |
104 | member_def(fork_event, time, T_ULONGLONG, "timestamp"), |
105 | { .name = NULL, }, | |
877108e4 ACM |
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"), | |
f6bbc1da | 138 | { .name = NULL, }, |
877108e4 ACM |
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"), | |
f6bbc1da ACM |
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, }, | |
877108e4 ACM |
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 | ||
3e9f45a7 ACM |
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 | ||
877108e4 ACM |
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 = | |
3e9f45a7 ACM |
293 | pyrf_lost_event__type.tp_new = |
294 | pyrf_read_event__type.tp_new = | |
295 | pyrf_sample_event__type.tp_new = | |
877108e4 ACM |
296 | pyrf_throttle_event__type.tp_new = PyType_GenericNew; |
297 | err = PyType_Ready(&pyrf_mmap_event__type); | |
3e9f45a7 ACM |
298 | if (err < 0) |
299 | goto out; | |
300 | err = PyType_Ready(&pyrf_lost_event__type); | |
877108e4 ACM |
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; | |
3e9f45a7 ACM |
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; | |
877108e4 ACM |
318 | out: |
319 | return err; | |
320 | } | |
321 | ||
322 | static PyTypeObject *pyrf_event__type[] = { | |
323 | [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, | |
3e9f45a7 | 324 | [PERF_RECORD_LOST] = &pyrf_lost_event__type, |
877108e4 ACM |
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, | |
3e9f45a7 ACM |
330 | [PERF_RECORD_READ] = &pyrf_read_event__type, |
331 | [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, | |
877108e4 ACM |
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 | { | |
64348153 | 359 | static char *kwlist[] = { "cpustr", NULL }; |
877108e4 ACM |
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 | { | |
64348153 | 428 | static char *kwlist[] = { "pid", "tid", NULL }; |
877108e4 ACM |
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", | |
64348153 FW |
530 | "bp_len", |
531 | NULL | |
532 | }; | |
877108e4 ACM |
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; | |
5d2cd909 | 612 | int group = 0, inherit = 0; |
64348153 | 613 | static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL }; |
877108e4 ACM |
614 | |
615 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, | |
5d2cd909 | 616 | &pcpus, &pthreads, &group, &inherit)) |
877108e4 ACM |
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 | ||
5d2cd909 ACM |
625 | evsel->attr.inherit = inherit; |
626 | if (perf_evsel__open(evsel, cpus, threads, group) < 0) { | |
877108e4 ACM |
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 | }, | |
f6bbc1da | 642 | { .ml_name = NULL, } |
877108e4 ACM |
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, | |
f6bbc1da | 671 | PyObject *args, PyObject *kwargs __used) |
877108e4 | 672 | { |
7e2ed097 ACM |
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); | |
877108e4 ACM |
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; | |
64348153 | 696 | static char *kwlist[] = { "pages", "overwrite", NULL }; |
877108e4 ACM |
697 | int pages = 128, overwrite = false; |
698 | ||
7e2ed097 ACM |
699 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, |
700 | &pages, &overwrite)) | |
877108e4 ACM |
701 | return NULL; |
702 | ||
7e2ed097 | 703 | if (perf_evlist__mmap(evlist, pages, overwrite) < 0) { |
877108e4 ACM |
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; | |
64348153 | 716 | static char *kwlist[] = { "timeout", NULL }; |
877108e4 ACM |
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, | |
f6bbc1da | 732 | PyObject *args __used, PyObject *kwargs __used) |
877108e4 ACM |
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, | |
f6bbc1da | 764 | PyObject *args, PyObject *kwargs __used) |
877108e4 ACM |
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; | |
64348153 | 787 | static char *kwlist[] = { "cpu", "sample_id_all", NULL }; |
5538beca | 788 | int err; |
877108e4 ACM |
789 | |
790 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, | |
791 | &cpu, &sample_id_all)) | |
792 | return NULL; | |
793 | ||
aece948f | 794 | event = perf_evlist__mmap_read(evlist, cpu); |
877108e4 ACM |
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); | |
5538beca | 804 | err = perf_event__parse_sample(event, first->attr.sample_type, |
c2a70653 | 805 | perf_evsel__sample_size(first), |
2b022a82 | 806 | sample_id_all, &pevent->sample, false); |
5c6970af ACM |
807 | if (err) |
808 | return PyErr_Format(PyExc_OSError, | |
809 | "perf: can't parse sample, err=%d", err); | |
877108e4 ACM |
810 | return pyevent; |
811 | } | |
5c6970af | 812 | |
877108e4 ACM |
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 | }, | |
f6bbc1da | 848 | { .ml_name = NULL, } |
877108e4 ACM |
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 | ||
129c04cb IM |
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 | ||
877108e4 ACM |
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 }, | |
f6bbc1da | 967 | { .name = NULL, }, |
877108e4 ACM |
968 | }; |
969 | ||
970 | static PyMethodDef perf__methods[] = { | |
f6bbc1da | 971 | { .ml_name = NULL, } |
877108e4 ACM |
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 | } |