1 // SPDX-License-Identifier: GPL-2.0
2 #include <Python.h>
3 #include <structmember.h>
4 #include <inttypes.h>
5 #include <poll.h>
6 #include <linux/err.h>
7 #include <perf/cpumap.h>
8 #ifdef HAVE_LIBTRACEEVENT
9 #include <event-parse.h>
10 #endif
11 #include <perf/mmap.h>
12 #include "evlist.h"
13 #include "evsel.h"
14 #include "event.h"
15 #include "print_binary.h"
16 #include "strbuf.h"
17 #include "thread_map.h"
18 #include "trace-event.h"
19 #include "mmap.h"
20 #include "util/sample.h"
21 #include <internal/lib.h>
22
23 #define _PyUnicode_FromString(arg) \
24 PyUnicode_FromString(arg)
25 #define _PyUnicode_FromFormat(...) \
26 PyUnicode_FromFormat(__VA_ARGS__)
27 #define _PyLong_FromLong(arg) \
28 PyLong_FromLong(arg)
29
30 PyMODINIT_FUNC PyInit_perf(void);
31
32 #define member_def(type, member, ptype, help) \
33 { #member, ptype, \
34 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
35 0, help }
36
37 #define sample_member_def(name, member, ptype, help) \
38 { #name, ptype, \
39 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
40 0, help }
41
42 struct pyrf_event {
43 PyObject_HEAD
44 struct evsel *evsel;
45 struct perf_sample sample;
46 union perf_event event;
47 };
48
49 #define sample_members \
50 sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"), \
51 sample_member_def(sample_pid, pid, T_INT, "event pid"), \
52 sample_member_def(sample_tid, tid, T_INT, "event tid"), \
53 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
54 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \
55 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
56 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
57 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
58 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
59
60 static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
61
62 static PyMemberDef pyrf_mmap_event__members[] = {
63 sample_members
64 member_def(perf_event_header, type, T_UINT, "event type"),
65 member_def(perf_event_header, misc, T_UINT, "event misc"),
66 member_def(perf_record_mmap, pid, T_UINT, "event pid"),
67 member_def(perf_record_mmap, tid, T_UINT, "event tid"),
68 member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"),
69 member_def(perf_record_mmap, len, T_ULONGLONG, "map length"),
70 member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"),
71 member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"),
72 { .name = NULL, },
73 };
74
pyrf_mmap_event__repr(const struct pyrf_event * pevent)75 static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent)
76 {
77 PyObject *ret;
78 char *s;
79
80 if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", "
81 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", "
82 "filename: %s }",
83 pevent->event.mmap.pid, pevent->event.mmap.tid,
84 pevent->event.mmap.start, pevent->event.mmap.len,
85 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
86 ret = PyErr_NoMemory();
87 } else {
88 ret = PyUnicode_FromString(s);
89 free(s);
90 }
91 return ret;
92 }
93
94 static PyTypeObject pyrf_mmap_event__type = {
95 PyVarObject_HEAD_INIT(NULL, 0)
96 .tp_name = "perf.mmap_event",
97 .tp_basicsize = sizeof(struct pyrf_event),
98 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
99 .tp_doc = pyrf_mmap_event__doc,
100 .tp_members = pyrf_mmap_event__members,
101 .tp_repr = (reprfunc)pyrf_mmap_event__repr,
102 };
103
104 static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
105
106 static PyMemberDef pyrf_task_event__members[] = {
107 sample_members
108 member_def(perf_event_header, type, T_UINT, "event type"),
109 member_def(perf_record_fork, pid, T_UINT, "event pid"),
110 member_def(perf_record_fork, ppid, T_UINT, "event ppid"),
111 member_def(perf_record_fork, tid, T_UINT, "event tid"),
112 member_def(perf_record_fork, ptid, T_UINT, "event ptid"),
113 member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"),
114 { .name = NULL, },
115 };
116
pyrf_task_event__repr(const struct pyrf_event * pevent)117 static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent)
118 {
119 return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
120 "ptid: %u, time: %" PRI_lu64 "}",
121 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
122 pevent->event.fork.pid,
123 pevent->event.fork.ppid,
124 pevent->event.fork.tid,
125 pevent->event.fork.ptid,
126 pevent->event.fork.time);
127 }
128
129 static PyTypeObject pyrf_task_event__type = {
130 PyVarObject_HEAD_INIT(NULL, 0)
131 .tp_name = "perf.task_event",
132 .tp_basicsize = sizeof(struct pyrf_event),
133 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
134 .tp_doc = pyrf_task_event__doc,
135 .tp_members = pyrf_task_event__members,
136 .tp_repr = (reprfunc)pyrf_task_event__repr,
137 };
138
139 static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
140
141 static PyMemberDef pyrf_comm_event__members[] = {
142 sample_members
143 member_def(perf_event_header, type, T_UINT, "event type"),
144 member_def(perf_record_comm, pid, T_UINT, "event pid"),
145 member_def(perf_record_comm, tid, T_UINT, "event tid"),
146 member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"),
147 { .name = NULL, },
148 };
149
pyrf_comm_event__repr(const struct pyrf_event * pevent)150 static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent)
151 {
152 return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
153 pevent->event.comm.pid,
154 pevent->event.comm.tid,
155 pevent->event.comm.comm);
156 }
157
158 static PyTypeObject pyrf_comm_event__type = {
159 PyVarObject_HEAD_INIT(NULL, 0)
160 .tp_name = "perf.comm_event",
161 .tp_basicsize = sizeof(struct pyrf_event),
162 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
163 .tp_doc = pyrf_comm_event__doc,
164 .tp_members = pyrf_comm_event__members,
165 .tp_repr = (reprfunc)pyrf_comm_event__repr,
166 };
167
168 static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
169
170 static PyMemberDef pyrf_throttle_event__members[] = {
171 sample_members
172 member_def(perf_event_header, type, T_UINT, "event type"),
173 member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"),
174 member_def(perf_record_throttle, id, T_ULONGLONG, "event id"),
175 member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"),
176 { .name = NULL, },
177 };
178
pyrf_throttle_event__repr(const struct pyrf_event * pevent)179 static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent)
180 {
181 const struct perf_record_throttle *te = (const struct perf_record_throttle *)
182 (&pevent->event.header + 1);
183
184 return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64
185 ", stream_id: %" PRI_lu64 " }",
186 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
187 te->time, te->id, te->stream_id);
188 }
189
190 static PyTypeObject pyrf_throttle_event__type = {
191 PyVarObject_HEAD_INIT(NULL, 0)
192 .tp_name = "perf.throttle_event",
193 .tp_basicsize = sizeof(struct pyrf_event),
194 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
195 .tp_doc = pyrf_throttle_event__doc,
196 .tp_members = pyrf_throttle_event__members,
197 .tp_repr = (reprfunc)pyrf_throttle_event__repr,
198 };
199
200 static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
201
202 static PyMemberDef pyrf_lost_event__members[] = {
203 sample_members
204 member_def(perf_record_lost, id, T_ULONGLONG, "event id"),
205 member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"),
206 { .name = NULL, },
207 };
208
pyrf_lost_event__repr(const struct pyrf_event * pevent)209 static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent)
210 {
211 PyObject *ret;
212 char *s;
213
214 if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", "
215 "lost: %#" PRI_lx64 " }",
216 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
217 ret = PyErr_NoMemory();
218 } else {
219 ret = PyUnicode_FromString(s);
220 free(s);
221 }
222 return ret;
223 }
224
225 static PyTypeObject pyrf_lost_event__type = {
226 PyVarObject_HEAD_INIT(NULL, 0)
227 .tp_name = "perf.lost_event",
228 .tp_basicsize = sizeof(struct pyrf_event),
229 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
230 .tp_doc = pyrf_lost_event__doc,
231 .tp_members = pyrf_lost_event__members,
232 .tp_repr = (reprfunc)pyrf_lost_event__repr,
233 };
234
235 static const char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
236
237 static PyMemberDef pyrf_read_event__members[] = {
238 sample_members
239 member_def(perf_record_read, pid, T_UINT, "event pid"),
240 member_def(perf_record_read, tid, T_UINT, "event tid"),
241 { .name = NULL, },
242 };
243
pyrf_read_event__repr(const struct pyrf_event * pevent)244 static PyObject *pyrf_read_event__repr(const struct pyrf_event *pevent)
245 {
246 return PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
247 pevent->event.read.pid,
248 pevent->event.read.tid);
249 /*
250 * FIXME: return the array of read values,
251 * making this method useful ;-)
252 */
253 }
254
255 static PyTypeObject pyrf_read_event__type = {
256 PyVarObject_HEAD_INIT(NULL, 0)
257 .tp_name = "perf.read_event",
258 .tp_basicsize = sizeof(struct pyrf_event),
259 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
260 .tp_doc = pyrf_read_event__doc,
261 .tp_members = pyrf_read_event__members,
262 .tp_repr = (reprfunc)pyrf_read_event__repr,
263 };
264
265 static const char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
266
267 static PyMemberDef pyrf_sample_event__members[] = {
268 sample_members
269 member_def(perf_event_header, type, T_UINT, "event type"),
270 { .name = NULL, },
271 };
272
pyrf_sample_event__repr(const struct pyrf_event * pevent)273 static PyObject *pyrf_sample_event__repr(const struct pyrf_event *pevent)
274 {
275 PyObject *ret;
276 char *s;
277
278 if (asprintf(&s, "{ type: sample }") < 0) {
279 ret = PyErr_NoMemory();
280 } else {
281 ret = PyUnicode_FromString(s);
282 free(s);
283 }
284 return ret;
285 }
286
287 #ifdef HAVE_LIBTRACEEVENT
is_tracepoint(const struct pyrf_event * pevent)288 static bool is_tracepoint(const struct pyrf_event *pevent)
289 {
290 return pevent->evsel->core.attr.type == PERF_TYPE_TRACEPOINT;
291 }
292
293 static PyObject*
tracepoint_field(const struct pyrf_event * pe,struct tep_format_field * field)294 tracepoint_field(const struct pyrf_event *pe, struct tep_format_field *field)
295 {
296 struct tep_handle *pevent = field->event->tep;
297 void *data = pe->sample.raw_data;
298 PyObject *ret = NULL;
299 unsigned long long val;
300 unsigned int offset, len;
301
302 if (field->flags & TEP_FIELD_IS_ARRAY) {
303 offset = field->offset;
304 len = field->size;
305 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
306 val = tep_read_number(pevent, data + offset, len);
307 offset = val;
308 len = offset >> 16;
309 offset &= 0xffff;
310 if (tep_field_is_relative(field->flags))
311 offset += field->offset + field->size;
312 }
313 if (field->flags & TEP_FIELD_IS_STRING &&
314 is_printable_array(data + offset, len)) {
315 ret = PyUnicode_FromString((char *)data + offset);
316 } else {
317 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
318 field->flags &= ~TEP_FIELD_IS_STRING;
319 }
320 } else {
321 val = tep_read_number(pevent, data + field->offset,
322 field->size);
323 if (field->flags & TEP_FIELD_IS_POINTER)
324 ret = PyLong_FromUnsignedLong((unsigned long) val);
325 else if (field->flags & TEP_FIELD_IS_SIGNED)
326 ret = PyLong_FromLong((long) val);
327 else
328 ret = PyLong_FromUnsignedLong((unsigned long) val);
329 }
330
331 return ret;
332 }
333
334 static PyObject*
get_tracepoint_field(struct pyrf_event * pevent,PyObject * attr_name)335 get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
336 {
337 const char *str = _PyUnicode_AsString(PyObject_Str(attr_name));
338 struct evsel *evsel = pevent->evsel;
339 struct tep_format_field *field;
340
341 if (!evsel->tp_format) {
342 struct tep_event *tp_format;
343
344 tp_format = trace_event__tp_format_id(evsel->core.attr.config);
345 if (IS_ERR_OR_NULL(tp_format))
346 return NULL;
347
348 evsel->tp_format = tp_format;
349 }
350
351 field = tep_find_any_field(evsel->tp_format, str);
352 if (!field)
353 return NULL;
354
355 return tracepoint_field(pevent, field);
356 }
357 #endif /* HAVE_LIBTRACEEVENT */
358
359 static PyObject*
pyrf_sample_event__getattro(struct pyrf_event * pevent,PyObject * attr_name)360 pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
361 {
362 PyObject *obj = NULL;
363
364 #ifdef HAVE_LIBTRACEEVENT
365 if (is_tracepoint(pevent))
366 obj = get_tracepoint_field(pevent, attr_name);
367 #endif
368
369 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
370 }
371
372 static PyTypeObject pyrf_sample_event__type = {
373 PyVarObject_HEAD_INIT(NULL, 0)
374 .tp_name = "perf.sample_event",
375 .tp_basicsize = sizeof(struct pyrf_event),
376 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
377 .tp_doc = pyrf_sample_event__doc,
378 .tp_members = pyrf_sample_event__members,
379 .tp_repr = (reprfunc)pyrf_sample_event__repr,
380 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro,
381 };
382
383 static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
384
385 static PyMemberDef pyrf_context_switch_event__members[] = {
386 sample_members
387 member_def(perf_event_header, type, T_UINT, "event type"),
388 member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"),
389 member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"),
390 { .name = NULL, },
391 };
392
pyrf_context_switch_event__repr(const struct pyrf_event * pevent)393 static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent)
394 {
395 PyObject *ret;
396 char *s;
397
398 if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
399 pevent->event.context_switch.next_prev_pid,
400 pevent->event.context_switch.next_prev_tid,
401 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
402 ret = PyErr_NoMemory();
403 } else {
404 ret = PyUnicode_FromString(s);
405 free(s);
406 }
407 return ret;
408 }
409
410 static PyTypeObject pyrf_context_switch_event__type = {
411 PyVarObject_HEAD_INIT(NULL, 0)
412 .tp_name = "perf.context_switch_event",
413 .tp_basicsize = sizeof(struct pyrf_event),
414 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
415 .tp_doc = pyrf_context_switch_event__doc,
416 .tp_members = pyrf_context_switch_event__members,
417 .tp_repr = (reprfunc)pyrf_context_switch_event__repr,
418 };
419
pyrf_event__setup_types(void)420 static int pyrf_event__setup_types(void)
421 {
422 int err;
423 pyrf_mmap_event__type.tp_new =
424 pyrf_task_event__type.tp_new =
425 pyrf_comm_event__type.tp_new =
426 pyrf_lost_event__type.tp_new =
427 pyrf_read_event__type.tp_new =
428 pyrf_sample_event__type.tp_new =
429 pyrf_context_switch_event__type.tp_new =
430 pyrf_throttle_event__type.tp_new = PyType_GenericNew;
431 err = PyType_Ready(&pyrf_mmap_event__type);
432 if (err < 0)
433 goto out;
434 err = PyType_Ready(&pyrf_lost_event__type);
435 if (err < 0)
436 goto out;
437 err = PyType_Ready(&pyrf_task_event__type);
438 if (err < 0)
439 goto out;
440 err = PyType_Ready(&pyrf_comm_event__type);
441 if (err < 0)
442 goto out;
443 err = PyType_Ready(&pyrf_throttle_event__type);
444 if (err < 0)
445 goto out;
446 err = PyType_Ready(&pyrf_read_event__type);
447 if (err < 0)
448 goto out;
449 err = PyType_Ready(&pyrf_sample_event__type);
450 if (err < 0)
451 goto out;
452 err = PyType_Ready(&pyrf_context_switch_event__type);
453 if (err < 0)
454 goto out;
455 out:
456 return err;
457 }
458
459 static PyTypeObject *pyrf_event__type[] = {
460 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
461 [PERF_RECORD_LOST] = &pyrf_lost_event__type,
462 [PERF_RECORD_COMM] = &pyrf_comm_event__type,
463 [PERF_RECORD_EXIT] = &pyrf_task_event__type,
464 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
465 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
466 [PERF_RECORD_FORK] = &pyrf_task_event__type,
467 [PERF_RECORD_READ] = &pyrf_read_event__type,
468 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
469 [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type,
470 [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type,
471 };
472
pyrf_event__new(const union perf_event * event)473 static PyObject *pyrf_event__new(const union perf_event *event)
474 {
475 struct pyrf_event *pevent;
476 PyTypeObject *ptype;
477
478 if ((event->header.type < PERF_RECORD_MMAP ||
479 event->header.type > PERF_RECORD_SAMPLE) &&
480 !(event->header.type == PERF_RECORD_SWITCH ||
481 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE))
482 return NULL;
483
484 // FIXME this better be dynamic or we need to parse everything
485 // before calling perf_mmap__consume(), including tracepoint fields.
486 if (sizeof(pevent->event) < event->header.size)
487 return NULL;
488
489 ptype = pyrf_event__type[event->header.type];
490 pevent = PyObject_New(struct pyrf_event, ptype);
491 if (pevent != NULL)
492 memcpy(&pevent->event, event, event->header.size);
493 return (PyObject *)pevent;
494 }
495
496 struct pyrf_cpu_map {
497 PyObject_HEAD
498
499 struct perf_cpu_map *cpus;
500 };
501
pyrf_cpu_map__init(struct pyrf_cpu_map * pcpus,PyObject * args,PyObject * kwargs)502 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
503 PyObject *args, PyObject *kwargs)
504 {
505 static char *kwlist[] = { "cpustr", NULL };
506 char *cpustr = NULL;
507
508 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
509 kwlist, &cpustr))
510 return -1;
511
512 pcpus->cpus = perf_cpu_map__new(cpustr);
513 if (pcpus->cpus == NULL)
514 return -1;
515 return 0;
516 }
517
pyrf_cpu_map__delete(struct pyrf_cpu_map * pcpus)518 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
519 {
520 perf_cpu_map__put(pcpus->cpus);
521 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
522 }
523
pyrf_cpu_map__length(PyObject * obj)524 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
525 {
526 struct pyrf_cpu_map *pcpus = (void *)obj;
527
528 return perf_cpu_map__nr(pcpus->cpus);
529 }
530
pyrf_cpu_map__item(PyObject * obj,Py_ssize_t i)531 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
532 {
533 struct pyrf_cpu_map *pcpus = (void *)obj;
534
535 if (i >= perf_cpu_map__nr(pcpus->cpus))
536 return NULL;
537
538 return Py_BuildValue("i", perf_cpu_map__cpu(pcpus->cpus, i).cpu);
539 }
540
541 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
542 .sq_length = pyrf_cpu_map__length,
543 .sq_item = pyrf_cpu_map__item,
544 };
545
546 static const char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
547
548 static PyTypeObject pyrf_cpu_map__type = {
549 PyVarObject_HEAD_INIT(NULL, 0)
550 .tp_name = "perf.cpu_map",
551 .tp_basicsize = sizeof(struct pyrf_cpu_map),
552 .tp_dealloc = (destructor)pyrf_cpu_map__delete,
553 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
554 .tp_doc = pyrf_cpu_map__doc,
555 .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
556 .tp_init = (initproc)pyrf_cpu_map__init,
557 };
558
pyrf_cpu_map__setup_types(void)559 static int pyrf_cpu_map__setup_types(void)
560 {
561 pyrf_cpu_map__type.tp_new = PyType_GenericNew;
562 return PyType_Ready(&pyrf_cpu_map__type);
563 }
564
565 struct pyrf_thread_map {
566 PyObject_HEAD
567
568 struct perf_thread_map *threads;
569 };
570
pyrf_thread_map__init(struct pyrf_thread_map * pthreads,PyObject * args,PyObject * kwargs)571 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
572 PyObject *args, PyObject *kwargs)
573 {
574 static char *kwlist[] = { "pid", "tid", "uid", NULL };
575 int pid = -1, tid = -1, uid = UINT_MAX;
576
577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
578 kwlist, &pid, &tid, &uid))
579 return -1;
580
581 pthreads->threads = thread_map__new(pid, tid, uid);
582 if (pthreads->threads == NULL)
583 return -1;
584 return 0;
585 }
586
pyrf_thread_map__delete(struct pyrf_thread_map * pthreads)587 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
588 {
589 perf_thread_map__put(pthreads->threads);
590 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
591 }
592
pyrf_thread_map__length(PyObject * obj)593 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
594 {
595 struct pyrf_thread_map *pthreads = (void *)obj;
596
597 return perf_thread_map__nr(pthreads->threads);
598 }
599
pyrf_thread_map__item(PyObject * obj,Py_ssize_t i)600 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
601 {
602 struct pyrf_thread_map *pthreads = (void *)obj;
603
604 if (i >= perf_thread_map__nr(pthreads->threads))
605 return NULL;
606
607 return Py_BuildValue("i", perf_thread_map__pid(pthreads->threads, i));
608 }
609
610 static PySequenceMethods pyrf_thread_map__sequence_methods = {
611 .sq_length = pyrf_thread_map__length,
612 .sq_item = pyrf_thread_map__item,
613 };
614
615 static const char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
616
617 static PyTypeObject pyrf_thread_map__type = {
618 PyVarObject_HEAD_INIT(NULL, 0)
619 .tp_name = "perf.thread_map",
620 .tp_basicsize = sizeof(struct pyrf_thread_map),
621 .tp_dealloc = (destructor)pyrf_thread_map__delete,
622 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
623 .tp_doc = pyrf_thread_map__doc,
624 .tp_as_sequence = &pyrf_thread_map__sequence_methods,
625 .tp_init = (initproc)pyrf_thread_map__init,
626 };
627
pyrf_thread_map__setup_types(void)628 static int pyrf_thread_map__setup_types(void)
629 {
630 pyrf_thread_map__type.tp_new = PyType_GenericNew;
631 return PyType_Ready(&pyrf_thread_map__type);
632 }
633
634 struct pyrf_evsel {
635 PyObject_HEAD
636
637 struct evsel evsel;
638 };
639
pyrf_evsel__init(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)640 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
641 PyObject *args, PyObject *kwargs)
642 {
643 struct perf_event_attr attr = {
644 .type = PERF_TYPE_HARDWARE,
645 .config = PERF_COUNT_HW_CPU_CYCLES,
646 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
647 };
648 static char *kwlist[] = {
649 "type",
650 "config",
651 "sample_freq",
652 "sample_period",
653 "sample_type",
654 "read_format",
655 "disabled",
656 "inherit",
657 "pinned",
658 "exclusive",
659 "exclude_user",
660 "exclude_kernel",
661 "exclude_hv",
662 "exclude_idle",
663 "mmap",
664 "context_switch",
665 "comm",
666 "freq",
667 "inherit_stat",
668 "enable_on_exec",
669 "task",
670 "watermark",
671 "precise_ip",
672 "mmap_data",
673 "sample_id_all",
674 "wakeup_events",
675 "bp_type",
676 "bp_addr",
677 "bp_len",
678 NULL
679 };
680 u64 sample_period = 0;
681 u32 disabled = 0,
682 inherit = 0,
683 pinned = 0,
684 exclusive = 0,
685 exclude_user = 0,
686 exclude_kernel = 0,
687 exclude_hv = 0,
688 exclude_idle = 0,
689 mmap = 0,
690 context_switch = 0,
691 comm = 0,
692 freq = 1,
693 inherit_stat = 0,
694 enable_on_exec = 0,
695 task = 0,
696 watermark = 0,
697 precise_ip = 0,
698 mmap_data = 0,
699 sample_id_all = 1;
700 int idx = 0;
701
702 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
703 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
704 &attr.type, &attr.config, &attr.sample_freq,
705 &sample_period, &attr.sample_type,
706 &attr.read_format, &disabled, &inherit,
707 &pinned, &exclusive, &exclude_user,
708 &exclude_kernel, &exclude_hv, &exclude_idle,
709 &mmap, &context_switch, &comm, &freq, &inherit_stat,
710 &enable_on_exec, &task, &watermark,
711 &precise_ip, &mmap_data, &sample_id_all,
712 &attr.wakeup_events, &attr.bp_type,
713 &attr.bp_addr, &attr.bp_len, &idx))
714 return -1;
715
716 /* union... */
717 if (sample_period != 0) {
718 if (attr.sample_freq != 0)
719 return -1; /* FIXME: throw right exception */
720 attr.sample_period = sample_period;
721 }
722
723 /* Bitfields */
724 attr.disabled = disabled;
725 attr.inherit = inherit;
726 attr.pinned = pinned;
727 attr.exclusive = exclusive;
728 attr.exclude_user = exclude_user;
729 attr.exclude_kernel = exclude_kernel;
730 attr.exclude_hv = exclude_hv;
731 attr.exclude_idle = exclude_idle;
732 attr.mmap = mmap;
733 attr.context_switch = context_switch;
734 attr.comm = comm;
735 attr.freq = freq;
736 attr.inherit_stat = inherit_stat;
737 attr.enable_on_exec = enable_on_exec;
738 attr.task = task;
739 attr.watermark = watermark;
740 attr.precise_ip = precise_ip;
741 attr.mmap_data = mmap_data;
742 attr.sample_id_all = sample_id_all;
743 attr.size = sizeof(attr);
744
745 evsel__init(&pevsel->evsel, &attr, idx);
746 return 0;
747 }
748
pyrf_evsel__delete(struct pyrf_evsel * pevsel)749 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
750 {
751 evsel__exit(&pevsel->evsel);
752 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
753 }
754
pyrf_evsel__open(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)755 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
756 PyObject *args, PyObject *kwargs)
757 {
758 struct evsel *evsel = &pevsel->evsel;
759 struct perf_cpu_map *cpus = NULL;
760 struct perf_thread_map *threads = NULL;
761 PyObject *pcpus = NULL, *pthreads = NULL;
762 int group = 0, inherit = 0;
763 static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
764
765 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
766 &pcpus, &pthreads, &group, &inherit))
767 return NULL;
768
769 if (pthreads != NULL)
770 threads = ((struct pyrf_thread_map *)pthreads)->threads;
771
772 if (pcpus != NULL)
773 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
774
775 evsel->core.attr.inherit = inherit;
776 /*
777 * This will group just the fds for this single evsel, to group
778 * multiple events, use evlist.open().
779 */
780 if (evsel__open(evsel, cpus, threads) < 0) {
781 PyErr_SetFromErrno(PyExc_OSError);
782 return NULL;
783 }
784
785 Py_INCREF(Py_None);
786 return Py_None;
787 }
788
pyrf_evsel__str(PyObject * self)789 static PyObject *pyrf_evsel__str(PyObject *self)
790 {
791 struct pyrf_evsel *pevsel = (void *)self;
792 struct evsel *evsel = &pevsel->evsel;
793
794 if (!evsel->pmu)
795 return PyUnicode_FromFormat("evsel(%s)", evsel__name(evsel));
796
797 return PyUnicode_FromFormat("evsel(%s/%s/)", evsel->pmu->name, evsel__name(evsel));
798 }
799
800 static PyMethodDef pyrf_evsel__methods[] = {
801 {
802 .ml_name = "open",
803 .ml_meth = (PyCFunction)pyrf_evsel__open,
804 .ml_flags = METH_VARARGS | METH_KEYWORDS,
805 .ml_doc = PyDoc_STR("open the event selector file descriptor table.")
806 },
807 { .ml_name = NULL, }
808 };
809
810 static const char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
811
812 static PyTypeObject pyrf_evsel__type = {
813 PyVarObject_HEAD_INIT(NULL, 0)
814 .tp_name = "perf.evsel",
815 .tp_basicsize = sizeof(struct pyrf_evsel),
816 .tp_dealloc = (destructor)pyrf_evsel__delete,
817 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
818 .tp_doc = pyrf_evsel__doc,
819 .tp_methods = pyrf_evsel__methods,
820 .tp_init = (initproc)pyrf_evsel__init,
821 .tp_str = pyrf_evsel__str,
822 .tp_repr = pyrf_evsel__str,
823 };
824
pyrf_evsel__setup_types(void)825 static int pyrf_evsel__setup_types(void)
826 {
827 pyrf_evsel__type.tp_new = PyType_GenericNew;
828 return PyType_Ready(&pyrf_evsel__type);
829 }
830
831 struct pyrf_evlist {
832 PyObject_HEAD
833
834 struct evlist evlist;
835 };
836
pyrf_evlist__init(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __maybe_unused)837 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
838 PyObject *args, PyObject *kwargs __maybe_unused)
839 {
840 PyObject *pcpus = NULL, *pthreads = NULL;
841 struct perf_cpu_map *cpus;
842 struct perf_thread_map *threads;
843
844 if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
845 return -1;
846
847 threads = ((struct pyrf_thread_map *)pthreads)->threads;
848 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
849 evlist__init(&pevlist->evlist, cpus, threads);
850 return 0;
851 }
852
pyrf_evlist__delete(struct pyrf_evlist * pevlist)853 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
854 {
855 evlist__exit(&pevlist->evlist);
856 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
857 }
858
pyrf_evlist__mmap(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)859 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
860 PyObject *args, PyObject *kwargs)
861 {
862 struct evlist *evlist = &pevlist->evlist;
863 static char *kwlist[] = { "pages", "overwrite", NULL };
864 int pages = 128, overwrite = false;
865
866 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
867 &pages, &overwrite))
868 return NULL;
869
870 if (evlist__mmap(evlist, pages) < 0) {
871 PyErr_SetFromErrno(PyExc_OSError);
872 return NULL;
873 }
874
875 Py_INCREF(Py_None);
876 return Py_None;
877 }
878
pyrf_evlist__poll(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)879 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
880 PyObject *args, PyObject *kwargs)
881 {
882 struct evlist *evlist = &pevlist->evlist;
883 static char *kwlist[] = { "timeout", NULL };
884 int timeout = -1, n;
885
886 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
887 return NULL;
888
889 n = evlist__poll(evlist, timeout);
890 if (n < 0) {
891 PyErr_SetFromErrno(PyExc_OSError);
892 return NULL;
893 }
894
895 return Py_BuildValue("i", n);
896 }
897
pyrf_evlist__get_pollfd(struct pyrf_evlist * pevlist,PyObject * args __maybe_unused,PyObject * kwargs __maybe_unused)898 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
899 PyObject *args __maybe_unused,
900 PyObject *kwargs __maybe_unused)
901 {
902 struct evlist *evlist = &pevlist->evlist;
903 PyObject *list = PyList_New(0);
904 int i;
905
906 for (i = 0; i < evlist->core.pollfd.nr; ++i) {
907 PyObject *file;
908 file = PyFile_FromFd(evlist->core.pollfd.entries[i].fd, "perf", "r", -1,
909 NULL, NULL, NULL, 0);
910 if (file == NULL)
911 goto free_list;
912
913 if (PyList_Append(list, file) != 0) {
914 Py_DECREF(file);
915 goto free_list;
916 }
917
918 Py_DECREF(file);
919 }
920
921 return list;
922 free_list:
923 return PyErr_NoMemory();
924 }
925
926
pyrf_evlist__add(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __maybe_unused)927 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
928 PyObject *args,
929 PyObject *kwargs __maybe_unused)
930 {
931 struct evlist *evlist = &pevlist->evlist;
932 PyObject *pevsel;
933 struct evsel *evsel;
934
935 if (!PyArg_ParseTuple(args, "O", &pevsel))
936 return NULL;
937
938 Py_INCREF(pevsel);
939 evsel = &((struct pyrf_evsel *)pevsel)->evsel;
940 evsel->core.idx = evlist->core.nr_entries;
941 evlist__add(evlist, evsel);
942
943 return Py_BuildValue("i", evlist->core.nr_entries);
944 }
945
get_md(struct evlist * evlist,int cpu)946 static struct mmap *get_md(struct evlist *evlist, int cpu)
947 {
948 int i;
949
950 for (i = 0; i < evlist->core.nr_mmaps; i++) {
951 struct mmap *md = &evlist->mmap[i];
952
953 if (md->core.cpu.cpu == cpu)
954 return md;
955 }
956
957 return NULL;
958 }
959
pyrf_evlist__read_on_cpu(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)960 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
961 PyObject *args, PyObject *kwargs)
962 {
963 struct evlist *evlist = &pevlist->evlist;
964 union perf_event *event;
965 int sample_id_all = 1, cpu;
966 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
967 struct mmap *md;
968 int err;
969
970 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
971 &cpu, &sample_id_all))
972 return NULL;
973
974 md = get_md(evlist, cpu);
975 if (!md)
976 return NULL;
977
978 if (perf_mmap__read_init(&md->core) < 0)
979 goto end;
980
981 event = perf_mmap__read_event(&md->core);
982 if (event != NULL) {
983 PyObject *pyevent = pyrf_event__new(event);
984 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
985 struct evsel *evsel;
986
987 if (pyevent == NULL)
988 return PyErr_NoMemory();
989
990 evsel = evlist__event2evsel(evlist, event);
991 if (!evsel) {
992 Py_DECREF(pyevent);
993 Py_INCREF(Py_None);
994 return Py_None;
995 }
996
997 pevent->evsel = evsel;
998
999 perf_mmap__consume(&md->core);
1000
1001 err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample);
1002 if (err) {
1003 Py_DECREF(pyevent);
1004 return PyErr_Format(PyExc_OSError,
1005 "perf: can't parse sample, err=%d", err);
1006 }
1007
1008 return pyevent;
1009 }
1010 end:
1011 Py_INCREF(Py_None);
1012 return Py_None;
1013 }
1014
pyrf_evlist__open(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1015 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
1016 PyObject *args, PyObject *kwargs)
1017 {
1018 struct evlist *evlist = &pevlist->evlist;
1019
1020 if (evlist__open(evlist) < 0) {
1021 PyErr_SetFromErrno(PyExc_OSError);
1022 return NULL;
1023 }
1024
1025 Py_INCREF(Py_None);
1026 return Py_None;
1027 }
1028
1029 static PyMethodDef pyrf_evlist__methods[] = {
1030 {
1031 .ml_name = "mmap",
1032 .ml_meth = (PyCFunction)pyrf_evlist__mmap,
1033 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1034 .ml_doc = PyDoc_STR("mmap the file descriptor table.")
1035 },
1036 {
1037 .ml_name = "open",
1038 .ml_meth = (PyCFunction)pyrf_evlist__open,
1039 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1040 .ml_doc = PyDoc_STR("open the file descriptors.")
1041 },
1042 {
1043 .ml_name = "poll",
1044 .ml_meth = (PyCFunction)pyrf_evlist__poll,
1045 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1046 .ml_doc = PyDoc_STR("poll the file descriptor table.")
1047 },
1048 {
1049 .ml_name = "get_pollfd",
1050 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd,
1051 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1052 .ml_doc = PyDoc_STR("get the poll file descriptor table.")
1053 },
1054 {
1055 .ml_name = "add",
1056 .ml_meth = (PyCFunction)pyrf_evlist__add,
1057 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1058 .ml_doc = PyDoc_STR("adds an event selector to the list.")
1059 },
1060 {
1061 .ml_name = "read_on_cpu",
1062 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu,
1063 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1064 .ml_doc = PyDoc_STR("reads an event.")
1065 },
1066 { .ml_name = NULL, }
1067 };
1068
pyrf_evlist__length(PyObject * obj)1069 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
1070 {
1071 struct pyrf_evlist *pevlist = (void *)obj;
1072
1073 return pevlist->evlist.core.nr_entries;
1074 }
1075
pyrf_evlist__item(PyObject * obj,Py_ssize_t i)1076 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
1077 {
1078 struct pyrf_evlist *pevlist = (void *)obj;
1079 struct evsel *pos;
1080
1081 if (i >= pevlist->evlist.core.nr_entries) {
1082 PyErr_SetString(PyExc_IndexError, "Index out of range");
1083 return NULL;
1084 }
1085
1086 evlist__for_each_entry(&pevlist->evlist, pos) {
1087 if (i-- == 0)
1088 break;
1089 }
1090
1091 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
1092 }
1093
pyrf_evlist__str(PyObject * self)1094 static PyObject *pyrf_evlist__str(PyObject *self)
1095 {
1096 struct pyrf_evlist *pevlist = (void *)self;
1097 struct evsel *pos;
1098 struct strbuf sb = STRBUF_INIT;
1099 bool first = true;
1100 PyObject *result;
1101
1102 strbuf_addstr(&sb, "evlist([");
1103 evlist__for_each_entry(&pevlist->evlist, pos) {
1104 if (!first)
1105 strbuf_addch(&sb, ',');
1106 if (!pos->pmu)
1107 strbuf_addstr(&sb, evsel__name(pos));
1108 else
1109 strbuf_addf(&sb, "%s/%s/", pos->pmu->name, evsel__name(pos));
1110 first = false;
1111 }
1112 strbuf_addstr(&sb, "])");
1113 result = PyUnicode_FromString(sb.buf);
1114 strbuf_release(&sb);
1115 return result;
1116 }
1117
1118 static PySequenceMethods pyrf_evlist__sequence_methods = {
1119 .sq_length = pyrf_evlist__length,
1120 .sq_item = pyrf_evlist__item,
1121 };
1122
1123 static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
1124
1125 static PyTypeObject pyrf_evlist__type = {
1126 PyVarObject_HEAD_INIT(NULL, 0)
1127 .tp_name = "perf.evlist",
1128 .tp_basicsize = sizeof(struct pyrf_evlist),
1129 .tp_dealloc = (destructor)pyrf_evlist__delete,
1130 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1131 .tp_as_sequence = &pyrf_evlist__sequence_methods,
1132 .tp_doc = pyrf_evlist__doc,
1133 .tp_methods = pyrf_evlist__methods,
1134 .tp_init = (initproc)pyrf_evlist__init,
1135 .tp_repr = pyrf_evlist__str,
1136 .tp_str = pyrf_evlist__str,
1137 };
1138
pyrf_evlist__setup_types(void)1139 static int pyrf_evlist__setup_types(void)
1140 {
1141 pyrf_evlist__type.tp_new = PyType_GenericNew;
1142 return PyType_Ready(&pyrf_evlist__type);
1143 }
1144
1145 #define PERF_CONST(name) { #name, PERF_##name }
1146
1147 struct perf_constant {
1148 const char *name;
1149 int value;
1150 };
1151
1152 static const struct perf_constant perf__constants[] = {
1153 PERF_CONST(TYPE_HARDWARE),
1154 PERF_CONST(TYPE_SOFTWARE),
1155 PERF_CONST(TYPE_TRACEPOINT),
1156 PERF_CONST(TYPE_HW_CACHE),
1157 PERF_CONST(TYPE_RAW),
1158 PERF_CONST(TYPE_BREAKPOINT),
1159
1160 PERF_CONST(COUNT_HW_CPU_CYCLES),
1161 PERF_CONST(COUNT_HW_INSTRUCTIONS),
1162 PERF_CONST(COUNT_HW_CACHE_REFERENCES),
1163 PERF_CONST(COUNT_HW_CACHE_MISSES),
1164 PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS),
1165 PERF_CONST(COUNT_HW_BRANCH_MISSES),
1166 PERF_CONST(COUNT_HW_BUS_CYCLES),
1167 PERF_CONST(COUNT_HW_CACHE_L1D),
1168 PERF_CONST(COUNT_HW_CACHE_L1I),
1169 PERF_CONST(COUNT_HW_CACHE_LL),
1170 PERF_CONST(COUNT_HW_CACHE_DTLB),
1171 PERF_CONST(COUNT_HW_CACHE_ITLB),
1172 PERF_CONST(COUNT_HW_CACHE_BPU),
1173 PERF_CONST(COUNT_HW_CACHE_OP_READ),
1174 PERF_CONST(COUNT_HW_CACHE_OP_WRITE),
1175 PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH),
1176 PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS),
1177 PERF_CONST(COUNT_HW_CACHE_RESULT_MISS),
1178
1179 PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND),
1180 PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND),
1181
1182 PERF_CONST(COUNT_SW_CPU_CLOCK),
1183 PERF_CONST(COUNT_SW_TASK_CLOCK),
1184 PERF_CONST(COUNT_SW_PAGE_FAULTS),
1185 PERF_CONST(COUNT_SW_CONTEXT_SWITCHES),
1186 PERF_CONST(COUNT_SW_CPU_MIGRATIONS),
1187 PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN),
1188 PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ),
1189 PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS),
1190 PERF_CONST(COUNT_SW_EMULATION_FAULTS),
1191 PERF_CONST(COUNT_SW_DUMMY),
1192
1193 PERF_CONST(SAMPLE_IP),
1194 PERF_CONST(SAMPLE_TID),
1195 PERF_CONST(SAMPLE_TIME),
1196 PERF_CONST(SAMPLE_ADDR),
1197 PERF_CONST(SAMPLE_READ),
1198 PERF_CONST(SAMPLE_CALLCHAIN),
1199 PERF_CONST(SAMPLE_ID),
1200 PERF_CONST(SAMPLE_CPU),
1201 PERF_CONST(SAMPLE_PERIOD),
1202 PERF_CONST(SAMPLE_STREAM_ID),
1203 PERF_CONST(SAMPLE_RAW),
1204
1205 PERF_CONST(FORMAT_TOTAL_TIME_ENABLED),
1206 PERF_CONST(FORMAT_TOTAL_TIME_RUNNING),
1207 PERF_CONST(FORMAT_ID),
1208 PERF_CONST(FORMAT_GROUP),
1209
1210 PERF_CONST(RECORD_MMAP),
1211 PERF_CONST(RECORD_LOST),
1212 PERF_CONST(RECORD_COMM),
1213 PERF_CONST(RECORD_EXIT),
1214 PERF_CONST(RECORD_THROTTLE),
1215 PERF_CONST(RECORD_UNTHROTTLE),
1216 PERF_CONST(RECORD_FORK),
1217 PERF_CONST(RECORD_READ),
1218 PERF_CONST(RECORD_SAMPLE),
1219 PERF_CONST(RECORD_MMAP2),
1220 PERF_CONST(RECORD_AUX),
1221 PERF_CONST(RECORD_ITRACE_START),
1222 PERF_CONST(RECORD_LOST_SAMPLES),
1223 PERF_CONST(RECORD_SWITCH),
1224 PERF_CONST(RECORD_SWITCH_CPU_WIDE),
1225
1226 PERF_CONST(RECORD_MISC_SWITCH_OUT),
1227 { .name = NULL, },
1228 };
1229
pyrf__tracepoint(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)1230 static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1231 PyObject *args, PyObject *kwargs)
1232 {
1233 #ifndef HAVE_LIBTRACEEVENT
1234 return NULL;
1235 #else
1236 struct tep_event *tp_format;
1237 static char *kwlist[] = { "sys", "name", NULL };
1238 char *sys = NULL;
1239 char *name = NULL;
1240
1241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist,
1242 &sys, &name))
1243 return NULL;
1244
1245 tp_format = trace_event__tp_format(sys, name);
1246 if (IS_ERR(tp_format))
1247 return PyLong_FromLong(-1);
1248
1249 return PyLong_FromLong(tp_format->id);
1250 #endif // HAVE_LIBTRACEEVENT
1251 }
1252
pyrf_evsel__from_evsel(struct evsel * evsel)1253 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
1254 {
1255 struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
1256
1257 if (!pevsel)
1258 return NULL;
1259
1260 memset(&pevsel->evsel, 0, sizeof(pevsel->evsel));
1261 evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx);
1262
1263 evsel__clone(&pevsel->evsel, evsel);
1264 return (PyObject *)pevsel;
1265 }
1266
pyrf_evlist__from_evlist(struct evlist * evlist)1267 static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
1268 {
1269 struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
1270 struct evsel *pos;
1271
1272 if (!pevlist)
1273 return NULL;
1274
1275 memset(&pevlist->evlist, 0, sizeof(pevlist->evlist));
1276 evlist__init(&pevlist->evlist, evlist->core.all_cpus, evlist->core.threads);
1277 evlist__for_each_entry(evlist, pos) {
1278 struct pyrf_evsel *pevsel = (void *)pyrf_evsel__from_evsel(pos);
1279
1280 evlist__add(&pevlist->evlist, &pevsel->evsel);
1281 }
1282 return (PyObject *)pevlist;
1283 }
1284
pyrf__parse_events(PyObject * self,PyObject * args)1285 static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
1286 {
1287 const char *input;
1288 struct evlist evlist = {};
1289 struct parse_events_error err;
1290 PyObject *result;
1291
1292 if (!PyArg_ParseTuple(args, "s", &input))
1293 return NULL;
1294
1295 parse_events_error__init(&err);
1296 evlist__init(&evlist, NULL, NULL);
1297 if (parse_events(&evlist, input, &err)) {
1298 parse_events_error__print(&err, input);
1299 PyErr_SetFromErrno(PyExc_OSError);
1300 return NULL;
1301 }
1302 result = pyrf_evlist__from_evlist(&evlist);
1303 evlist__exit(&evlist);
1304 return result;
1305 }
1306
1307 static PyMethodDef perf__methods[] = {
1308 {
1309 .ml_name = "tracepoint",
1310 .ml_meth = (PyCFunction) pyrf__tracepoint,
1311 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1312 .ml_doc = PyDoc_STR("Get tracepoint config.")
1313 },
1314 {
1315 .ml_name = "parse_events",
1316 .ml_meth = (PyCFunction) pyrf__parse_events,
1317 .ml_flags = METH_VARARGS,
1318 .ml_doc = PyDoc_STR("Parse a string of events and return an evlist.")
1319 },
1320 { .ml_name = NULL, }
1321 };
1322
PyInit_perf(void)1323 PyMODINIT_FUNC PyInit_perf(void)
1324 {
1325 PyObject *obj;
1326 int i;
1327 PyObject *dict;
1328 static struct PyModuleDef moduledef = {
1329 PyModuleDef_HEAD_INIT,
1330 "perf", /* m_name */
1331 "", /* m_doc */
1332 -1, /* m_size */
1333 perf__methods, /* m_methods */
1334 NULL, /* m_reload */
1335 NULL, /* m_traverse */
1336 NULL, /* m_clear */
1337 NULL, /* m_free */
1338 };
1339 PyObject *module = PyModule_Create(&moduledef);
1340
1341 if (module == NULL ||
1342 pyrf_event__setup_types() < 0 ||
1343 pyrf_evlist__setup_types() < 0 ||
1344 pyrf_evsel__setup_types() < 0 ||
1345 pyrf_thread_map__setup_types() < 0 ||
1346 pyrf_cpu_map__setup_types() < 0)
1347 return module;
1348
1349 /* The page_size is placed in util object. */
1350 page_size = sysconf(_SC_PAGE_SIZE);
1351
1352 Py_INCREF(&pyrf_evlist__type);
1353 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
1354
1355 Py_INCREF(&pyrf_evsel__type);
1356 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
1357
1358 Py_INCREF(&pyrf_mmap_event__type);
1359 PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type);
1360
1361 Py_INCREF(&pyrf_lost_event__type);
1362 PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type);
1363
1364 Py_INCREF(&pyrf_comm_event__type);
1365 PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type);
1366
1367 Py_INCREF(&pyrf_task_event__type);
1368 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
1369
1370 Py_INCREF(&pyrf_throttle_event__type);
1371 PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type);
1372
1373 Py_INCREF(&pyrf_task_event__type);
1374 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
1375
1376 Py_INCREF(&pyrf_read_event__type);
1377 PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type);
1378
1379 Py_INCREF(&pyrf_sample_event__type);
1380 PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type);
1381
1382 Py_INCREF(&pyrf_context_switch_event__type);
1383 PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type);
1384
1385 Py_INCREF(&pyrf_thread_map__type);
1386 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
1387
1388 Py_INCREF(&pyrf_cpu_map__type);
1389 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
1390
1391 dict = PyModule_GetDict(module);
1392 if (dict == NULL)
1393 goto error;
1394
1395 for (i = 0; perf__constants[i].name != NULL; i++) {
1396 obj = PyLong_FromLong(perf__constants[i].value);
1397 if (obj == NULL)
1398 goto error;
1399 PyDict_SetItemString(dict, perf__constants[i].name, obj);
1400 Py_DECREF(obj);
1401 }
1402
1403 error:
1404 if (PyErr_Occurred())
1405 PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1406 return module;
1407 }
1408