projects/linux·blob master · refs

4343 lines · 114.8 KiB

1// SPDX-License-Identifier: GPL-2.0
2#define PY_SSIZE_T_CLEAN
3#include <Python.h>
4
5#include <inttypes.h>
6#include <string.h>
7
8#include <linux/err.h>
9#include <poll.h>
10#include <unistd.h>
11
12#include <internal/lib.h>
13#include <perf/cpumap.h>
14#include <perf/mmap.h>
15#include <structmember.h>
16
17#include "addr_location.h"
18#include "build-id.h"
19#include "callchain.h"
20#include "comm.h"
21#include "config.h"
22#include "counts.h"
23#include "data.h"
24#include "debug.h"
25#include "dso.h"
26#include "dwarf-regs.h"
27#include "event.h"
28#include "branch.h"
29#include "evlist.h"
30#include "evsel.h"
31#include "expr.h"
32#include "map.h"
33#include "metricgroup.h"
34#include "mmap.h"
35#include "pmus.h"
36#include "print_binary.h"
37#include "record.h"
38#include "sample.h"
39#include "session.h"
40#include "srccode.h"
41#include "srcline.h"
42#include "strbuf.h"
43#include "symbol.h"
44#include "stat.h"
45#include "header.h"
46#include "trace/beauty/syscalltbl.h"
47#include "thread.h"
48#include "thread_map.h"
49#include "tool.h"
50#include "tp_pmu.h"
51#include "trace-event.h"
52
53#ifdef HAVE_LIBTRACEEVENT
54#include <event-parse.h>
55#endif
56
57PyMODINIT_FUNC PyInit_perf(void);
58
59static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel);
60
61#define member_def(type, member, ptype, help) \
62 { #member, ptype, \
63 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
64 0, help }
65
66#define sample_member_def(name, member, ptype, help) \
67 { #name, ptype, \
68 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
69 0, help }
70
71#define CHECK_INITIALIZED(ptr, msg) \
72 do { \
73 if (!(ptr)) { \
74 PyErr_SetString(PyExc_ValueError, msg " not initialized"); \
75 return NULL; \
76 } \
77 } while (0)
78
79#define CHECK_INITIALIZED_INT(ptr, msg) \
80 do { \
81 if (!(ptr)) { \
82 PyErr_SetString(PyExc_ValueError, msg " not initialized"); \
83 return -1; \
84 } \
85 } while (0)
86
87struct pyrf_event {
88 PyObject_HEAD
89 /** @sample: The parsed sample from the event. */
90 struct perf_sample sample;
91 /** @al: The address location from machine__resolve, lazily computed. */
92 struct addr_location al;
93 /** @al_resolved: True when machine__resolve been called. */
94 bool al_resolved;
95 /** @callchain: Resolved callchain, eagerly computed if requested. */
96 PyObject *callchain;
97 /** @brstack: Resolved branch stack, eagerly computed if requested. */
98 PyObject *brstack;
99 /** @event: The underlying perf_event that may be in a file or ring buffer. */
100 union perf_event event;
101};
102
103#define sample_members \
104 sample_member_def(sample_pid, pid, T_INT, "event pid"), \
105 sample_member_def(sample_tid, tid, T_INT, "event tid"), \
106 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
107 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
108 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
109 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
110 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
111
112static PyObject *pyrf_event__get_evsel(PyObject *self, void *closure __maybe_unused)
113{
114 struct pyrf_event *pevent = (void *)self;
115
116 if (!pevent->sample.evsel)
117 Py_RETURN_NONE;
118
119 return pyrf_evsel__from_evsel(pevent->sample.evsel);
120}
121
122static PyGetSetDef pyrf_event__getset[] = {
123 {
124 .name = "evsel",
125 .get = pyrf_event__get_evsel,
126 .set = NULL,
127 .doc = "tracking event.",
128 },
129 { .name = NULL, },
130};
131
132static void pyrf_event__delete(struct pyrf_event *pevent)
133{
134 if (pevent->al_resolved)
135 addr_location__exit(&pevent->al);
136 Py_XDECREF(pevent->callchain);
137 Py_XDECREF(pevent->brstack);
138 perf_sample__exit(&pevent->sample);
139 Py_TYPE(pevent)->tp_free((PyObject *)pevent);
140}
141
142static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
143
144static PyMemberDef pyrf_mmap_event__members[] = {
145 sample_members
146 member_def(perf_event_header, type, T_UINT, "event type"),
147 member_def(perf_event_header, misc, T_USHORT, "event misc"),
148 member_def(perf_record_mmap, pid, T_UINT, "event pid"),
149 member_def(perf_record_mmap, tid, T_UINT, "event tid"),
150 member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"),
151 member_def(perf_record_mmap, len, T_ULONGLONG, "map length"),
152 member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"),
153 member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"),
154 { .name = NULL, },
155};
156
157static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent)
158{
159 PyObject *ret;
160 char *s;
161
162 if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", "
163 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", "
164 "filename: %s }",
165 pevent->event.mmap.pid, pevent->event.mmap.tid,
166 pevent->event.mmap.start, pevent->event.mmap.len,
167 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
168 ret = PyErr_NoMemory();
169 } else {
170 ret = PyUnicode_FromString(s);
171 free(s);
172 }
173 return ret;
174}
175
176static PyTypeObject pyrf_mmap_event__type = {
177 PyVarObject_HEAD_INIT(NULL, 0)
178 .tp_name = "perf.mmap_event",
179 .tp_basicsize = sizeof(struct pyrf_event),
180 .tp_dealloc = (destructor)pyrf_event__delete,
181 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
182 .tp_doc = pyrf_mmap_event__doc,
183 .tp_members = pyrf_mmap_event__members,
184 .tp_getset = pyrf_event__getset,
185 .tp_repr = (reprfunc)pyrf_mmap_event__repr,
186};
187
188static const char pyrf_mmap2_event__doc[] = PyDoc_STR("perf mmap2 event object.");
189
190static PyObject *pyrf_mmap2_event__get_maj(PyObject *self, void *closure __maybe_unused)
191{
192 struct pyrf_event *pevent = (void *)self;
193
194 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)
195 Py_RETURN_NONE;
196
197 return PyLong_FromUnsignedLong(pevent->event.mmap2.maj);
198}
199
200static PyObject *pyrf_mmap2_event__get_min(PyObject *self, void *closure __maybe_unused)
201{
202 struct pyrf_event *pevent = (void *)self;
203
204 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)
205 Py_RETURN_NONE;
206
207 return PyLong_FromUnsignedLong(pevent->event.mmap2.min);
208}
209
210static PyObject *pyrf_mmap2_event__get_ino(PyObject *self, void *closure __maybe_unused)
211{
212 struct pyrf_event *pevent = (void *)self;
213
214 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)
215 Py_RETURN_NONE;
216
217 return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino);
218}
219
220static PyObject *pyrf_mmap2_event__get_ino_generation(PyObject *self, void *closure __maybe_unused)
221{
222 struct pyrf_event *pevent = (void *)self;
223
224 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)
225 Py_RETURN_NONE;
226
227 return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino_generation);
228}
229
230static PyObject *pyrf_mmap2_event__get_build_id(PyObject *self, void *closure __maybe_unused)
231{
232 struct pyrf_event *pevent = (void *)self;
233
234 if (!(pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID))
235 Py_RETURN_NONE;
236
237 int size = pevent->event.mmap2.build_id_size;
238
239 if (size > 20)
240 size = 20;
241
242 return PyBytes_FromStringAndSize((const char *)pevent->event.mmap2.build_id, size);
243}
244
245static PyGetSetDef pyrf_mmap2_event__getset[] = {
246 {
247 .name = "evsel",
248 .get = pyrf_event__get_evsel,
249 .set = NULL,
250 .doc = "tracking event.",
251 },
252 {
253 .name = "maj",
254 .get = pyrf_mmap2_event__get_maj,
255 .set = NULL,
256 .doc = "major number.",
257 },
258 {
259 .name = "min",
260 .get = pyrf_mmap2_event__get_min,
261 .set = NULL,
262 .doc = "minor number.",
263 },
264 {
265 .name = "ino",
266 .get = pyrf_mmap2_event__get_ino,
267 .set = NULL,
268 .doc = "inode number.",
269 },
270 {
271 .name = "ino_generation",
272 .get = pyrf_mmap2_event__get_ino_generation,
273 .set = NULL,
274 .doc = "inode generation.",
275 },
276 {
277 .name = "build_id",
278 .get = pyrf_mmap2_event__get_build_id,
279 .set = NULL,
280 .doc = "binary build ID.",
281 },
282 { .name = NULL, },
283};
284
285static PyMemberDef pyrf_mmap2_event__members[] = {
286 sample_members
287 member_def(perf_event_header, type, T_UINT, "event type"),
288 member_def(perf_event_header, misc, T_USHORT, "event misc"),
289 member_def(perf_record_mmap2, pid, T_UINT, "event pid"),
290 member_def(perf_record_mmap2, tid, T_UINT, "event tid"),
291 member_def(perf_record_mmap2, start, T_ULONGLONG, "start of the map"),
292 member_def(perf_record_mmap2, len, T_ULONGLONG, "map length"),
293 member_def(perf_record_mmap2, pgoff, T_ULONGLONG, "page offset"),
294 member_def(perf_record_mmap2, prot, T_UINT, "protection"),
295 member_def(perf_record_mmap2, flags, T_UINT, "flags"),
296 member_def(perf_record_mmap2, filename, T_STRING_INPLACE, "backing store"),
297 { .name = NULL, },
298};
299
300static PyObject *pyrf_mmap2_event__repr(const struct pyrf_event *pevent)
301{
302 PyObject *ret;
303 char *s;
304
305 if (asprintf(&s, "{ type: mmap2, pid: %u, tid: %u, start: %#" PRI_lx64 ", length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", flags: %#x, prot: %#x, filename: %s }",
306 pevent->event.mmap2.pid, pevent->event.mmap2.tid,
307 pevent->event.mmap2.start, pevent->event.mmap2.len,
308 pevent->event.mmap2.pgoff, pevent->event.mmap2.flags,
309 pevent->event.mmap2.prot, pevent->event.mmap2.filename) < 0)
310 return PyErr_NoMemory();
311
312 ret = PyUnicode_FromString(s);
313 free(s);
314 return ret;
315}
316
317static PyTypeObject pyrf_mmap2_event__type = {
318 PyVarObject_HEAD_INIT(NULL, 0)
319 .tp_name = "perf.mmap2_event",
320 .tp_basicsize = sizeof(struct pyrf_event),
321 .tp_dealloc = (destructor)pyrf_event__delete,
322 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
323 .tp_doc = pyrf_mmap2_event__doc,
324 .tp_members = pyrf_mmap2_event__members,
325 .tp_getset = pyrf_mmap2_event__getset,
326 .tp_repr = (reprfunc)pyrf_mmap2_event__repr,
327};
328
329static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
330
331static PyMemberDef pyrf_task_event__members[] = {
332 sample_members
333 member_def(perf_event_header, type, T_UINT, "event type"),
334 member_def(perf_record_fork, pid, T_UINT, "event pid"),
335 member_def(perf_record_fork, ppid, T_UINT, "event ppid"),
336 member_def(perf_record_fork, tid, T_UINT, "event tid"),
337 member_def(perf_record_fork, ptid, T_UINT, "event ptid"),
338 member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"),
339 { .name = NULL, },
340};
341
342static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent)
343{
344 return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
345 "ptid: %u, time: %" PRI_lu64 "}",
346 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
347 pevent->event.fork.pid,
348 pevent->event.fork.ppid,
349 pevent->event.fork.tid,
350 pevent->event.fork.ptid,
351 pevent->event.fork.time);
352}
353
354static PyTypeObject pyrf_task_event__type = {
355 PyVarObject_HEAD_INIT(NULL, 0)
356 .tp_name = "perf.task_event",
357 .tp_basicsize = sizeof(struct pyrf_event),
358 .tp_dealloc = (destructor)pyrf_event__delete,
359 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
360 .tp_doc = pyrf_task_event__doc,
361 .tp_members = pyrf_task_event__members,
362 .tp_getset = pyrf_event__getset,
363 .tp_repr = (reprfunc)pyrf_task_event__repr,
364};
365
366static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
367
368static PyMemberDef pyrf_comm_event__members[] = {
369 sample_members
370 member_def(perf_event_header, type, T_UINT, "event type"),
371 member_def(perf_record_comm, pid, T_UINT, "event pid"),
372 member_def(perf_record_comm, tid, T_UINT, "event tid"),
373 member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"),
374 { .name = NULL, },
375};
376
377static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent)
378{
379 return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
380 pevent->event.comm.pid,
381 pevent->event.comm.tid,
382 pevent->event.comm.comm);
383}
384
385static PyTypeObject pyrf_comm_event__type = {
386 PyVarObject_HEAD_INIT(NULL, 0)
387 .tp_name = "perf.comm_event",
388 .tp_basicsize = sizeof(struct pyrf_event),
389 .tp_dealloc = (destructor)pyrf_event__delete,
390 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
391 .tp_doc = pyrf_comm_event__doc,
392 .tp_members = pyrf_comm_event__members,
393 .tp_getset = pyrf_event__getset,
394 .tp_repr = (reprfunc)pyrf_comm_event__repr,
395};
396
397static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
398
399static PyMemberDef pyrf_throttle_event__members[] = {
400 sample_members
401 member_def(perf_event_header, type, T_UINT, "event type"),
402 member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"),
403 member_def(perf_record_throttle, id, T_ULONGLONG, "event id"),
404 member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"),
405 { .name = NULL, },
406};
407
408static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent)
409{
410 const struct perf_record_throttle *te = (const struct perf_record_throttle *)
411 (&pevent->event.header + 1);
412
413 return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64
414 ", stream_id: %" PRI_lu64 " }",
415 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
416 te->time, te->id, te->stream_id);
417}
418
419static PyTypeObject pyrf_throttle_event__type = {
420 PyVarObject_HEAD_INIT(NULL, 0)
421 .tp_name = "perf.throttle_event",
422 .tp_basicsize = sizeof(struct pyrf_event),
423 .tp_dealloc = (destructor)pyrf_event__delete,
424 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
425 .tp_doc = pyrf_throttle_event__doc,
426 .tp_members = pyrf_throttle_event__members,
427 .tp_getset = pyrf_event__getset,
428 .tp_repr = (reprfunc)pyrf_throttle_event__repr,
429};
430
431static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
432
433static PyMemberDef pyrf_lost_event__members[] = {
434 sample_members
435 member_def(perf_event_header, type, T_UINT, "event type"),
436 member_def(perf_record_lost, id, T_ULONGLONG, "event id"),
437 member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"),
438 { .name = NULL, },
439};
440
441static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent)
442{
443 PyObject *ret;
444 char *s;
445
446 if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", "
447 "lost: %#" PRI_lx64 " }",
448 pevent->event.lost.id, pevent->event.lost.lost) < 0) {
449 ret = PyErr_NoMemory();
450 } else {
451 ret = PyUnicode_FromString(s);
452 free(s);
453 }
454 return ret;
455}
456
457static PyTypeObject pyrf_lost_event__type = {
458 PyVarObject_HEAD_INIT(NULL, 0)
459 .tp_name = "perf.lost_event",
460 .tp_basicsize = sizeof(struct pyrf_event),
461 .tp_dealloc = (destructor)pyrf_event__delete,
462 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
463 .tp_doc = pyrf_lost_event__doc,
464 .tp_members = pyrf_lost_event__members,
465 .tp_getset = pyrf_event__getset,
466 .tp_repr = (reprfunc)pyrf_lost_event__repr,
467};
468
469static const char pyrf_stat_event__doc[] = PyDoc_STR("perf stat event object.");
470
471static PyMemberDef pyrf_stat_event__members[] = {
472 sample_members
473 member_def(perf_event_header, type, T_UINT, "event type"),
474 member_def(perf_record_stat, id, T_ULONGLONG, "event id"),
475 member_def(perf_record_stat, cpu, T_UINT, "event cpu"),
476 member_def(perf_record_stat, thread, T_UINT, "event thread"),
477 member_def(perf_record_stat, val, T_ULONGLONG, "counter value"),
478 member_def(perf_record_stat, ena, T_ULONGLONG, "enabled time"),
479 member_def(perf_record_stat, run, T_ULONGLONG, "running time"),
480 { .name = NULL, },
481};
482
483static PyObject *pyrf_stat_event__repr(const struct pyrf_event *pevent)
484{
485 return PyUnicode_FromFormat(
486 "{ type: stat, id: %llu, cpu: %u, thread: %u, val: %llu, ena: %llu, run: %llu }",
487 pevent->event.stat.id,
488 pevent->event.stat.cpu,
489 pevent->event.stat.thread,
490 pevent->event.stat.val,
491 pevent->event.stat.ena,
492 pevent->event.stat.run);
493}
494
495static PyTypeObject pyrf_stat_event__type = {
496 PyVarObject_HEAD_INIT(NULL, 0)
497 .tp_name = "perf.stat_event",
498 .tp_basicsize = sizeof(struct pyrf_event),
499 .tp_new = PyType_GenericNew,
500 .tp_dealloc = (destructor)pyrf_event__delete,
501 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
502 .tp_doc = pyrf_stat_event__doc,
503 .tp_members = pyrf_stat_event__members,
504 .tp_getset = pyrf_event__getset,
505 .tp_repr = (reprfunc)pyrf_stat_event__repr,
506};
507
508static const char pyrf_stat_round_event__doc[] = PyDoc_STR("perf stat round event object.");
509
510static PyMemberDef pyrf_stat_round_event__members[] = {
511 sample_members
512 member_def(perf_event_header, type, T_UINT, "event type"),
513 { .name = "stat_round_type", .type = T_ULONGLONG,
514 .offset = offsetof(struct pyrf_event, event) + offsetof(struct perf_record_stat_round, type),
515 .doc = "round type" },
516 member_def(perf_record_stat_round, time, T_ULONGLONG, "round time"),
517 { .name = NULL, },
518};
519
520static PyObject *pyrf_stat_round_event__repr(const struct pyrf_event *pevent)
521{
522 return PyUnicode_FromFormat("{ type: stat_round, type: %llu, time: %llu }",
523 pevent->event.stat_round.type,
524 pevent->event.stat_round.time);
525}
526
527static PyTypeObject pyrf_stat_round_event__type = {
528 PyVarObject_HEAD_INIT(NULL, 0)
529 .tp_name = "perf.stat_round_event",
530 .tp_basicsize = sizeof(struct pyrf_event),
531 .tp_new = PyType_GenericNew,
532 .tp_dealloc = (destructor)pyrf_event__delete,
533 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
534 .tp_doc = pyrf_stat_round_event__doc,
535 .tp_members = pyrf_stat_round_event__members,
536 .tp_getset = pyrf_event__getset,
537 .tp_repr = (reprfunc)pyrf_stat_round_event__repr,
538};
539
540static const char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
541
542static PyMemberDef pyrf_read_event__members[] = {
543 sample_members
544 member_def(perf_event_header, type, T_UINT, "event type"),
545 member_def(perf_record_read, pid, T_UINT, "event pid"),
546 member_def(perf_record_read, tid, T_UINT, "event tid"),
547 { .name = NULL, },
548};
549
550static PyObject *pyrf_read_event__repr(const struct pyrf_event *pevent)
551{
552 return PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
553 pevent->event.read.pid,
554 pevent->event.read.tid);
555 /*
556 * FIXME: return the array of read values,
557 * making this method useful ;-)
558 */
559}
560
561static PyTypeObject pyrf_read_event__type = {
562 PyVarObject_HEAD_INIT(NULL, 0)
563 .tp_name = "perf.read_event",
564 .tp_basicsize = sizeof(struct pyrf_event),
565 .tp_dealloc = (destructor)pyrf_event__delete,
566 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
567 .tp_doc = pyrf_read_event__doc,
568 .tp_members = pyrf_read_event__members,
569 .tp_getset = pyrf_event__getset,
570 .tp_repr = (reprfunc)pyrf_read_event__repr,
571};
572
573static const char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
574
575static PyMemberDef pyrf_sample_event__members[] = {
576 sample_members
577 sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"),
578 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),
579 sample_member_def(sample_phys_addr, phys_addr, T_ULONGLONG, "event physical addr"),
580 sample_member_def(sample_weight, weight, T_ULONGLONG, "event weight"),
581 sample_member_def(sample_data_src, data_src, T_ULONGLONG, "event data source"),
582 sample_member_def(sample_insn_count, insn_cnt, T_ULONGLONG, "event instruction count"),
583 sample_member_def(sample_cyc_count, cyc_cnt, T_ULONGLONG, "event cycle count"),
584 member_def(perf_event_header, type, T_UINT, "event type"),
585 { .name = NULL, },
586};
587
588static PyObject *pyrf_sample_event__repr(const struct pyrf_event *pevent)
589{
590 PyObject *ret;
591 char *s;
592
593 if (asprintf(&s, "{ type: sample }") < 0) {
594 ret = PyErr_NoMemory();
595 } else {
596 ret = PyUnicode_FromString(s);
597 free(s);
598 }
599 return ret;
600}
601
602#ifdef HAVE_LIBTRACEEVENT
603static bool is_tracepoint(const struct pyrf_event *pevent)
604{
605 if (!pevent->sample.evsel)
606 return false;
607 return pevent->sample.evsel->core.attr.type == PERF_TYPE_TRACEPOINT;
608}
609
610static PyObject*
611tracepoint_field(const struct pyrf_event *pe, struct tep_format_field *field)
612{
613 struct tep_handle *pevent = field->event->tep;
614 void *data = pe->sample.raw_data;
615 PyObject *ret = NULL;
616 unsigned long long val;
617 unsigned int offset, len;
618
619 if (field->flags & TEP_FIELD_IS_ARRAY) {
620 offset = field->offset;
621 len = field->size;
622 if (field->flags & TEP_FIELD_IS_DYNAMIC) {
623 val = tep_read_number(pevent, data + offset, len);
624 offset = val;
625 len = offset >> 16;
626 offset &= 0xffff;
627 if (tep_field_is_relative(field->flags))
628 offset += field->offset + field->size;
629 }
630 if (field->flags & TEP_FIELD_IS_STRING &&
631 is_printable_array(data + offset, len)) {
632 ret = PyUnicode_FromString((char *)data + offset);
633 } else {
634 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
635 field->flags &= ~TEP_FIELD_IS_STRING;
636 }
637 } else {
638 val = tep_read_number(pevent, data + field->offset,
639 field->size);
640 if (field->flags & TEP_FIELD_IS_POINTER)
641 ret = PyLong_FromUnsignedLong((unsigned long) val);
642 else if (field->flags & TEP_FIELD_IS_SIGNED)
643 ret = PyLong_FromLong((long) val);
644 else
645 ret = PyLong_FromUnsignedLong((unsigned long) val);
646 }
647
648 return ret;
649}
650
651static PyObject*
652get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
653{
654 struct evsel *evsel = pevent->sample.evsel;
655 struct tep_event *tp_format = evsel__tp_format(evsel);
656 struct tep_format_field *field;
657
658 if (IS_ERR_OR_NULL(tp_format))
659 return NULL;
660
661 PyObject *obj = PyObject_Str(attr_name);
662 if (obj == NULL)
663 return NULL;
664
665 const char *str = PyUnicode_AsUTF8(obj);
666 if (str == NULL) {
667 Py_DECREF(obj);
668 return NULL;
669 }
670
671 field = tep_find_any_field(tp_format, str);
672 Py_DECREF(obj);
673 return field ? tracepoint_field(pevent, field) : NULL;
674}
675#endif /* HAVE_LIBTRACEEVENT */
676
677static int pyrf_sample_event__resolve_al(struct pyrf_event *pevent)
678{
679 struct evsel *evsel = pevent->sample.evsel;
680 struct evlist *evlist = evsel ? evsel->evlist : NULL;
681 struct perf_session *session = evlist ? evlist__session(evlist) : NULL;
682
683 if (pevent->al_resolved)
684 return 0;
685
686 if (!session)
687 return -1;
688
689 addr_location__init(&pevent->al);
690 if (machine__resolve(&session->machines.host, &pevent->al, &pevent->sample) < 0) {
691 addr_location__exit(&pevent->al);
692 return -1;
693 }
694
695 pevent->al_resolved = true;
696 return 0;
697}
698
699static PyObject *pyrf_sample_event__get_dso(struct pyrf_event *pevent,
700 void *closure __maybe_unused)
701{
702 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
703 Py_RETURN_NONE;
704
705 return PyUnicode_FromString(dso__name(map__dso(pevent->al.map)));
706}
707
708static PyObject *pyrf_sample_event__get_dso_long_name(struct pyrf_event *pevent,
709 void *closure __maybe_unused)
710{
711 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
712 Py_RETURN_NONE;
713
714 return PyUnicode_FromString(dso__long_name(map__dso(pevent->al.map)));
715}
716
717static PyObject *pyrf_sample_event__get_dso_bid(struct pyrf_event *pevent,
718 void *closure __maybe_unused)
719{
720 char sbuild_id[SBUILD_ID_SIZE];
721
722 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
723 Py_RETURN_NONE;
724
725 build_id__snprintf(dso__bid(map__dso(pevent->al.map)), sbuild_id, sizeof(sbuild_id));
726 return PyUnicode_FromString(sbuild_id);
727}
728
729static PyObject *pyrf_sample_event__get_map_start(struct pyrf_event *pevent,
730 void *closure __maybe_unused)
731{
732 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
733 Py_RETURN_NONE;
734
735 return PyLong_FromUnsignedLong(map__start(pevent->al.map));
736}
737
738static PyObject *pyrf_sample_event__get_map_end(struct pyrf_event *pevent,
739 void *closure __maybe_unused)
740{
741 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
742 Py_RETURN_NONE;
743
744 return PyLong_FromUnsignedLong(map__end(pevent->al.map));
745}
746
747static PyObject *pyrf_sample_event__get_map_pgoff(struct pyrf_event *pevent,
748 void *closure __maybe_unused)
749{
750 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map)
751 Py_RETURN_NONE;
752
753 return PyLong_FromUnsignedLongLong(map__pgoff(pevent->al.map));
754}
755
756static PyObject *pyrf_sample_event__get_symbol(struct pyrf_event *pevent,
757 void *closure __maybe_unused)
758{
759 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym)
760 Py_RETURN_NONE;
761
762 return PyUnicode_FromString(pevent->al.sym->name);
763}
764
765static PyObject *pyrf_sample_event__get_sym_start(struct pyrf_event *pevent,
766 void *closure __maybe_unused)
767{
768 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym)
769 Py_RETURN_NONE;
770
771 return PyLong_FromUnsignedLongLong(pevent->al.sym->start);
772}
773
774static PyObject *pyrf_sample_event__get_sym_end(struct pyrf_event *pevent,
775 void *closure __maybe_unused)
776{
777 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym)
778 Py_RETURN_NONE;
779
780 return PyLong_FromUnsignedLongLong(pevent->al.sym->end);
781}
782
783static PyObject *pyrf_sample_event__get_raw_buf(struct pyrf_event *pevent,
784 void *closure __maybe_unused)
785{
786 if (pevent->event.header.type != PERF_RECORD_SAMPLE)
787 Py_RETURN_NONE;
788
789 return PyBytes_FromStringAndSize((const char *)pevent->sample.raw_data,
790 pevent->sample.raw_size);
791}
792
793static PyObject *pyrf_sample_event__srccode(PyObject *self, PyObject *args)
794{
795 struct pyrf_event *pevent = (void *)self;
796 u64 addr = pevent->sample.ip;
797 char *srcfile = NULL;
798 char *srccode = NULL;
799 unsigned int line = 0;
800 int len = 0;
801 PyObject *result;
802 struct addr_location al;
803
804 if (!PyArg_ParseTuple(args, "|K", &addr))
805 return NULL;
806
807 if (pyrf_sample_event__resolve_al(pevent) < 0)
808 Py_RETURN_NONE;
809
810 if (addr != pevent->sample.ip) {
811 addr_location__init(&al);
812 thread__find_symbol_fb(pevent->al.thread, pevent->sample.cpumode, addr, &al);
813 } else {
814 addr_location__init(&al);
815 al.thread = thread__get(pevent->al.thread);
816 al.map = map__get(pevent->al.map);
817 al.sym = pevent->al.sym;
818 al.addr = pevent->al.addr;
819 }
820
821 if (al.map) {
822 struct dso *dso = map__dso(al.map);
823
824 if (dso) {
825 srcfile = get_srcline_split(dso, map__rip_2objdump(al.map, addr),
826 &line);
827 }
828 }
829 addr_location__exit(&al);
830
831 if (srcfile) {
832 srccode = find_sourceline(srcfile, line, &len);
833 result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len);
834 free(srcfile);
835 } else {
836 result = Py_BuildValue("(sIs#)", NULL, 0, NULL, (Py_ssize_t)0);
837 }
838
839 return result;
840}
841
842static PyObject *pyrf_sample_event__insn(PyObject *self, PyObject *args __maybe_unused)
843{
844 struct pyrf_event *pevent = (void *)self;
845 struct thread *thread;
846 struct machine *machine;
847
848 if (pyrf_sample_event__resolve_al(pevent) < 0)
849 Py_RETURN_NONE;
850
851 thread = pevent->al.thread;
852
853 if (!thread || !thread__maps(thread))
854 Py_RETURN_NONE;
855
856 machine = maps__machine(thread__maps(thread));
857 if (!machine)
858 Py_RETURN_NONE;
859
860 if (pevent->sample.ip && !pevent->sample.insn_len)
861 perf_sample__fetch_insn(&pevent->sample, thread, machine);
862
863 if (!pevent->sample.insn_len)
864 Py_RETURN_NONE;
865
866 return PyBytes_FromStringAndSize((const char *)pevent->sample.insn,
867 pevent->sample.insn_len);
868}
869
870struct pyrf_callchain_node {
871 PyObject_HEAD
872 u64 ip;
873 struct map *map;
874 struct symbol *sym;
875};
876
877static void pyrf_callchain_node__delete(struct pyrf_callchain_node *pnode)
878{
879 map__put(pnode->map);
880 Py_TYPE(pnode)->tp_free((PyObject *)pnode);
881}
882
883static PyObject *pyrf_callchain_node__get_ip(struct pyrf_callchain_node *pnode,
884 void *closure __maybe_unused)
885{
886 return PyLong_FromUnsignedLongLong(pnode->ip);
887}
888
889static PyObject *pyrf_callchain_node__get_symbol(struct pyrf_callchain_node *pnode,
890 void *closure __maybe_unused)
891{
892 if (pnode->sym)
893 return PyUnicode_FromString(pnode->sym->name);
894 return PyUnicode_FromString("[unknown]");
895}
896
897static PyObject *pyrf_callchain_node__get_dso(struct pyrf_callchain_node *pnode,
898 void *closure __maybe_unused)
899{
900 const char *dsoname = "[unknown]";
901
902 if (pnode->map) {
903 struct dso *dso = map__dso(pnode->map);
904
905 if (dso) {
906 if (symbol_conf.show_kernel_path && dso__long_name(dso))
907 dsoname = dso__long_name(dso);
908 else
909 dsoname = dso__name(dso);
910 }
911 }
912 return PyUnicode_FromString(dsoname);
913}
914
915static PyGetSetDef pyrf_callchain_node__getset[] = {
916 { .name = "ip", .get = (getter)pyrf_callchain_node__get_ip, },
917 { .name = "symbol", .get = (getter)pyrf_callchain_node__get_symbol, },
918 { .name = "dso", .get = (getter)pyrf_callchain_node__get_dso, },
919 { .name = NULL, },
920};
921
922static PyTypeObject pyrf_callchain_node__type = {
923 PyVarObject_HEAD_INIT(NULL, 0)
924 .tp_name = "perf.callchain_node",
925 .tp_basicsize = sizeof(struct pyrf_callchain_node),
926 .tp_dealloc = (destructor)pyrf_callchain_node__delete,
927 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
928 .tp_doc = "perf callchain node object.",
929 .tp_getset = pyrf_callchain_node__getset,
930};
931
932struct pyrf_callchain_frame {
933 u64 ip;
934 struct map *map;
935 struct symbol *sym;
936};
937
938struct pyrf_callchain {
939 PyObject_HEAD
940 struct pyrf_callchain_frame *frames;
941 u64 nr_frames;
942};
943
944static void pyrf_callchain__delete(struct pyrf_callchain *pchain)
945{
946 if (pchain->frames) {
947 for (u64 i = 0; i < pchain->nr_frames; i++)
948 map__put(pchain->frames[i].map);
949 free(pchain->frames);
950 }
951 Py_TYPE(pchain)->tp_free((PyObject *)pchain);
952}
953
954static Py_ssize_t pyrf_callchain__length(PyObject *obj)
955{
956 struct pyrf_callchain *pchain = (void *)obj;
957
958 return pchain->nr_frames;
959}
960
961static PyObject *pyrf_callchain__item(PyObject *obj, Py_ssize_t i)
962{
963 struct pyrf_callchain *pchain = (void *)obj;
964 struct pyrf_callchain_node *pnode;
965
966 if (i < 0 || i >= (Py_ssize_t)pchain->nr_frames) {
967 PyErr_SetString(PyExc_IndexError, "Index out of range");
968 return NULL;
969 }
970
971 pnode = PyObject_New(struct pyrf_callchain_node, &pyrf_callchain_node__type);
972 if (!pnode)
973 return NULL;
974
975 pnode->ip = pchain->frames[i].ip;
976 pnode->map = map__get(pchain->frames[i].map);
977 pnode->sym = pchain->frames[i].sym;
978
979 return (PyObject *)pnode;
980}
981
982static PySequenceMethods pyrf_callchain__sequence_methods = {
983 .sq_length = pyrf_callchain__length,
984 .sq_item = pyrf_callchain__item,
985};
986
987static PyTypeObject pyrf_callchain__type = {
988 PyVarObject_HEAD_INIT(NULL, 0)
989 .tp_name = "perf.callchain",
990 .tp_basicsize = sizeof(struct pyrf_callchain),
991 .tp_dealloc = (destructor)pyrf_callchain__delete,
992 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
993 .tp_doc = "perf callchain object.",
994 .tp_as_sequence = &pyrf_callchain__sequence_methods,
995};
996
997static PyObject *pyrf_sample_event__get_callchain(PyObject *self, void *closure __maybe_unused)
998{
999 struct pyrf_event *pevent = (void *)self;
1000
1001 if (!pevent->callchain)
1002 Py_RETURN_NONE;
1003
1004 Py_INCREF(pevent->callchain);
1005 return pevent->callchain;
1006}
1007
1008struct pyrf_branch_entry {
1009 PyObject_HEAD
1010 u64 from;
1011 u64 to;
1012 struct branch_flags flags;
1013};
1014
1015static void pyrf_branch_entry__delete(struct pyrf_branch_entry *pentry)
1016{
1017 Py_TYPE(pentry)->tp_free((PyObject *)pentry);
1018}
1019
1020static PyObject *pyrf_branch_entry__get_from(struct pyrf_branch_entry *pentry,
1021 void *closure __maybe_unused)
1022{
1023 return PyLong_FromUnsignedLongLong(pentry->from);
1024}
1025
1026static PyObject *pyrf_branch_entry__get_to(struct pyrf_branch_entry *pentry,
1027 void *closure __maybe_unused)
1028{
1029 return PyLong_FromUnsignedLongLong(pentry->to);
1030}
1031
1032static PyObject *pyrf_branch_entry__get_mispred(struct pyrf_branch_entry *pentry,
1033 void *closure __maybe_unused)
1034{
1035 return PyBool_FromLong(pentry->flags.mispred);
1036}
1037
1038static PyObject *pyrf_branch_entry__get_predicted(struct pyrf_branch_entry *pentry,
1039 void *closure __maybe_unused)
1040{
1041 return PyBool_FromLong(pentry->flags.predicted);
1042}
1043
1044static PyObject *pyrf_branch_entry__get_in_tx(struct pyrf_branch_entry *pentry,
1045 void *closure __maybe_unused)
1046{
1047 return PyBool_FromLong(pentry->flags.in_tx);
1048}
1049
1050static PyObject *pyrf_branch_entry__get_abort(struct pyrf_branch_entry *pentry,
1051 void *closure __maybe_unused)
1052{
1053 return PyBool_FromLong(pentry->flags.abort);
1054}
1055
1056static PyObject *pyrf_branch_entry__get_cycles(struct pyrf_branch_entry *pentry,
1057 void *closure __maybe_unused)
1058{
1059 return PyLong_FromUnsignedLongLong(pentry->flags.cycles);
1060}
1061
1062static PyObject *pyrf_branch_entry__get_type(struct pyrf_branch_entry *pentry,
1063 void *closure __maybe_unused)
1064{
1065 return PyLong_FromUnsignedLongLong((unsigned long long)pentry->flags.type);
1066}
1067
1068static PyGetSetDef pyrf_branch_entry__getset[] = {
1069 { .name = "from_ip", .get = (getter)pyrf_branch_entry__get_from, },
1070 { .name = "to_ip", .get = (getter)pyrf_branch_entry__get_to, },
1071 { .name = "mispred", .get = (getter)pyrf_branch_entry__get_mispred, },
1072 { .name = "predicted", .get = (getter)pyrf_branch_entry__get_predicted, },
1073 { .name = "in_tx", .get = (getter)pyrf_branch_entry__get_in_tx, },
1074 { .name = "abort", .get = (getter)pyrf_branch_entry__get_abort, },
1075 { .name = "cycles", .get = (getter)pyrf_branch_entry__get_cycles, },
1076 { .name = "type", .get = (getter)pyrf_branch_entry__get_type, },
1077 { .name = NULL, },
1078};
1079
1080static PyTypeObject pyrf_branch_entry__type = {
1081 PyVarObject_HEAD_INIT(NULL, 0)
1082 .tp_name = "perf.branch_entry",
1083 .tp_basicsize = sizeof(struct pyrf_branch_entry),
1084 .tp_dealloc = (destructor)pyrf_branch_entry__delete,
1085 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1086 .tp_doc = "perf branch entry object.",
1087 .tp_getset = pyrf_branch_entry__getset,
1088};
1089
1090struct pyrf_branch_stack {
1091 PyObject_HEAD
1092 struct branch_entry *entries;
1093 u64 nr;
1094};
1095
1096static void pyrf_branch_stack__delete(struct pyrf_branch_stack *pstack)
1097{
1098 free(pstack->entries);
1099 Py_TYPE(pstack)->tp_free((PyObject *)pstack);
1100}
1101
1102static Py_ssize_t pyrf_branch_stack__length(PyObject *obj)
1103{
1104 struct pyrf_branch_stack *pstack = (void *)obj;
1105
1106 return pstack->nr;
1107}
1108
1109static PyObject *pyrf_branch_stack__item(PyObject *obj, Py_ssize_t i)
1110{
1111 struct pyrf_branch_stack *pstack = (void *)obj;
1112 struct pyrf_branch_entry *pentry;
1113
1114 if (i < 0 || i >= (Py_ssize_t)pstack->nr) {
1115 PyErr_SetString(PyExc_IndexError, "Index out of range");
1116 return NULL;
1117 }
1118
1119 pentry = PyObject_New(struct pyrf_branch_entry, &pyrf_branch_entry__type);
1120 if (!pentry)
1121 return NULL;
1122
1123 pentry->from = pstack->entries[i].from;
1124 pentry->to = pstack->entries[i].to;
1125 pentry->flags = pstack->entries[i].flags;
1126
1127 return (PyObject *)pentry;
1128}
1129
1130static PySequenceMethods pyrf_branch_stack__sequence_methods = {
1131 .sq_length = pyrf_branch_stack__length,
1132 .sq_item = pyrf_branch_stack__item,
1133};
1134
1135static PyTypeObject pyrf_branch_stack__type = {
1136 PyVarObject_HEAD_INIT(NULL, 0)
1137 .tp_name = "perf.branch_stack",
1138 .tp_basicsize = sizeof(struct pyrf_branch_stack),
1139 .tp_dealloc = (destructor)pyrf_branch_stack__delete,
1140 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1141 .tp_doc = "perf branch stack object.",
1142 .tp_as_sequence = &pyrf_branch_stack__sequence_methods,
1143};
1144
1145static PyObject *pyrf_sample_event__get_brstack(PyObject *self, void *closure __maybe_unused)
1146{
1147 struct pyrf_event *pevent = (void *)self;
1148
1149 if (!pevent->brstack)
1150 Py_RETURN_NONE;
1151
1152 Py_INCREF(pevent->brstack);
1153 return pevent->brstack;
1154}
1155
1156static PyObject*
1157pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
1158{
1159 PyObject *obj = NULL;
1160
1161#ifdef HAVE_LIBTRACEEVENT
1162 if (is_tracepoint(pevent))
1163 obj = get_tracepoint_field(pevent, attr_name);
1164#endif
1165
1166 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
1167}
1168
1169static PyGetSetDef pyrf_sample_event__getset[] = {
1170 {
1171 .name = "callchain",
1172 .get = pyrf_sample_event__get_callchain,
1173 .set = NULL,
1174 .doc = "event callchain.",
1175 },
1176 {
1177 .name = "brstack",
1178 .get = pyrf_sample_event__get_brstack,
1179 .set = NULL,
1180 .doc = "event branch stack.",
1181 },
1182 {
1183 .name = "raw_buf",
1184 .get = (getter)pyrf_sample_event__get_raw_buf,
1185 .set = NULL,
1186 .doc = "event raw buffer.",
1187 },
1188 {
1189 .name = "evsel",
1190 .get = pyrf_event__get_evsel,
1191 .set = NULL,
1192 .doc = "tracking event.",
1193 },
1194 {
1195 .name = "dso",
1196 .get = (getter)pyrf_sample_event__get_dso,
1197 .set = NULL,
1198 .doc = "event dso short name.",
1199 },
1200 {
1201 .name = "dso_long_name",
1202 .get = (getter)pyrf_sample_event__get_dso_long_name,
1203 .set = NULL,
1204 .doc = "event dso long name.",
1205 },
1206 {
1207 .name = "dso_bid",
1208 .get = (getter)pyrf_sample_event__get_dso_bid,
1209 .set = NULL,
1210 .doc = "event dso build id.",
1211 },
1212 {
1213 .name = "map_start",
1214 .get = (getter)pyrf_sample_event__get_map_start,
1215 .set = NULL,
1216 .doc = "event map start address.",
1217 },
1218 {
1219 .name = "map_end",
1220 .get = (getter)pyrf_sample_event__get_map_end,
1221 .set = NULL,
1222 .doc = "event map end address.",
1223 },
1224 {
1225 .name = "map_pgoff",
1226 .get = (getter)pyrf_sample_event__get_map_pgoff,
1227 .set = NULL,
1228 .doc = "event map page offset.",
1229 },
1230 {
1231 .name = "symbol",
1232 .get = (getter)pyrf_sample_event__get_symbol,
1233 .set = NULL,
1234 .doc = "event symbol name.",
1235 },
1236 {
1237 .name = "sym_start",
1238 .get = (getter)pyrf_sample_event__get_sym_start,
1239 .set = NULL,
1240 .doc = "event symbol start address.",
1241 },
1242 {
1243 .name = "sym_end",
1244 .get = (getter)pyrf_sample_event__get_sym_end,
1245 .set = NULL,
1246 .doc = "event symbol end address.",
1247 },
1248 { .name = NULL, },
1249};
1250
1251static PyMethodDef pyrf_sample_event__methods[] = {
1252 {
1253 .ml_name = "srccode",
1254 .ml_meth = (PyCFunction)pyrf_sample_event__srccode,
1255 .ml_flags = METH_VARARGS,
1256 .ml_doc = PyDoc_STR("Get source code for an address.")
1257 },
1258 {
1259 .ml_name = "insn",
1260 .ml_meth = (PyCFunction)pyrf_sample_event__insn,
1261 .ml_flags = METH_NOARGS,
1262 .ml_doc = PyDoc_STR("Get instruction bytes for a sample.")
1263 },
1264 { .ml_name = NULL, }
1265};
1266
1267static PyTypeObject pyrf_sample_event__type = {
1268 PyVarObject_HEAD_INIT(NULL, 0)
1269 .tp_name = "perf.sample_event",
1270 .tp_basicsize = sizeof(struct pyrf_event),
1271 .tp_dealloc = (destructor)pyrf_event__delete,
1272 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1273 .tp_doc = pyrf_sample_event__doc,
1274 .tp_members = pyrf_sample_event__members,
1275 .tp_getset = pyrf_sample_event__getset,
1276 .tp_methods = pyrf_sample_event__methods,
1277 .tp_repr = (reprfunc)pyrf_sample_event__repr,
1278 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro,
1279};
1280
1281static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
1282
1283static PyMemberDef pyrf_context_switch_event__members[] = {
1284 sample_members
1285 member_def(perf_event_header, type, T_UINT, "event type"),
1286 member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"),
1287 member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"),
1288 { .name = NULL, },
1289};
1290
1291static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent)
1292{
1293 PyObject *ret;
1294 char *s;
1295
1296 if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
1297 pevent->event.context_switch.next_prev_pid,
1298 pevent->event.context_switch.next_prev_tid,
1299 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
1300 ret = PyErr_NoMemory();
1301 } else {
1302 ret = PyUnicode_FromString(s);
1303 free(s);
1304 }
1305 return ret;
1306}
1307
1308static PyTypeObject pyrf_context_switch_event__type = {
1309 PyVarObject_HEAD_INIT(NULL, 0)
1310 .tp_name = "perf.context_switch_event",
1311 .tp_basicsize = sizeof(struct pyrf_event),
1312 .tp_dealloc = (destructor)pyrf_event__delete,
1313 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1314 .tp_doc = pyrf_context_switch_event__doc,
1315 .tp_members = pyrf_context_switch_event__members,
1316 .tp_getset = pyrf_event__getset,
1317 .tp_repr = (reprfunc)pyrf_context_switch_event__repr,
1318};
1319
1320static int pyrf_event__setup_types(void)
1321{
1322 int err;
1323
1324 err = PyType_Ready(&pyrf_mmap_event__type);
1325 if (err < 0)
1326 goto out;
1327 err = PyType_Ready(&pyrf_mmap2_event__type);
1328 if (err < 0)
1329 goto out;
1330 err = PyType_Ready(&pyrf_lost_event__type);
1331 if (err < 0)
1332 goto out;
1333 err = PyType_Ready(&pyrf_task_event__type);
1334 if (err < 0)
1335 goto out;
1336 err = PyType_Ready(&pyrf_comm_event__type);
1337 if (err < 0)
1338 goto out;
1339 err = PyType_Ready(&pyrf_throttle_event__type);
1340 if (err < 0)
1341 goto out;
1342 err = PyType_Ready(&pyrf_read_event__type);
1343 if (err < 0)
1344 goto out;
1345 err = PyType_Ready(&pyrf_sample_event__type);
1346 if (err < 0)
1347 goto out;
1348 err = PyType_Ready(&pyrf_context_switch_event__type);
1349 if (err < 0)
1350 goto out;
1351 err = PyType_Ready(&pyrf_stat_event__type);
1352 if (err < 0)
1353 goto out;
1354 err = PyType_Ready(&pyrf_stat_round_event__type);
1355 if (err < 0)
1356 goto out;
1357 err = PyType_Ready(&pyrf_callchain_node__type);
1358 if (err < 0)
1359 goto out;
1360 err = PyType_Ready(&pyrf_callchain__type);
1361 if (err < 0)
1362 goto out;
1363 err = PyType_Ready(&pyrf_branch_entry__type);
1364 if (err < 0)
1365 goto out;
1366 err = PyType_Ready(&pyrf_branch_stack__type);
1367 if (err < 0)
1368 goto out;
1369out:
1370 return err;
1371}
1372
1373static PyTypeObject *pyrf_event__type[] = {
1374 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type,
1375 [PERF_RECORD_MMAP2] = &pyrf_mmap2_event__type,
1376 [PERF_RECORD_LOST] = &pyrf_lost_event__type,
1377 [PERF_RECORD_COMM] = &pyrf_comm_event__type,
1378 [PERF_RECORD_EXIT] = &pyrf_task_event__type,
1379 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type,
1380 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
1381 [PERF_RECORD_FORK] = &pyrf_task_event__type,
1382 [PERF_RECORD_READ] = &pyrf_read_event__type,
1383 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type,
1384 [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type,
1385 [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type,
1386 [PERF_RECORD_STAT] = &pyrf_stat_event__type,
1387 [PERF_RECORD_STAT_ROUND] = &pyrf_stat_round_event__type,
1388};
1389
1390static PyObject *pyrf_event__new(const union perf_event *event, struct evsel *evsel,
1391 struct perf_session *session,
1392 struct machine *machine)
1393{
1394 struct pyrf_event *pevent;
1395 struct perf_sample *sample;
1396 int err;
1397 u32 min_size;
1398 bool needs_swap;
1399
1400 if (!machine)
1401 machine = session ? &session->machines.host : NULL;
1402
1403 if (event->header.type >= ARRAY_SIZE(pyrf_event__type) ||
1404 pyrf_event__type[event->header.type] == NULL) {
1405 return PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
1406 event->header.type);
1407 }
1408
1409 if (perf_event__too_small(event, &min_size)) {
1410 return PyErr_Format(PyExc_ValueError, "Event size %u too small for type %u",
1411 event->header.size, event->header.type);
1412 }
1413
1414 size_t copy_size = event->header.size;
1415
1416 if (copy_size > sizeof(pevent->event)) {
1417 return PyErr_Format(PyExc_TypeError, "Unexpected event size: %zd < %zu",
1418 sizeof(pevent->event), copy_size);
1419 }
1420
1421 pevent = PyObject_New(struct pyrf_event, pyrf_event__type[event->header.type]);
1422 if (pevent == NULL)
1423 return PyErr_NoMemory();
1424
1425 /* Copy the event for memory safety and initialize variables. */
1426 memcpy(&pevent->event, event, copy_size);
1427 if (copy_size < sizeof(pevent->event))
1428 memset((char *)&pevent->event + copy_size, 0, sizeof(pevent->event) - copy_size);
1429
1430 if (event->header.type == PERF_RECORD_MMAP2)
1431 pevent->event.mmap2.filename[sizeof(pevent->event.mmap2.filename) - 1] = '\0';
1432
1433 perf_sample__init(&pevent->sample, /*all=*/true);
1434 pevent->callchain = NULL;
1435 pevent->brstack = NULL;
1436 pevent->al_resolved = false;
1437 addr_location__init(&pevent->al);
1438
1439 if (!evsel)
1440 return (PyObject *)pevent;
1441
1442 /* Parse the sample again so that pointers are within the copied event. */
1443 needs_swap = evsel->needs_swap;
1444
1445 evsel->needs_swap = false;
1446 err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample);
1447 evsel->needs_swap = needs_swap;
1448 if (err < 0) {
1449 Py_DECREF(pevent);
1450 return PyErr_Format(PyExc_OSError,
1451 "perf: can't parse sample, err=%d", err);
1452 }
1453 sample = &pevent->sample;
1454 if (machine && sample->callchain) {
1455 struct addr_location al;
1456 struct callchain_cursor *cursor;
1457 u64 i;
1458 struct pyrf_callchain *pchain;
1459
1460 addr_location__init(&al);
1461 if (machine__resolve(machine, &al, sample) >= 0) {
1462 cursor = get_tls_callchain_cursor();
1463 if (thread__resolve_callchain(al.thread, cursor, sample,
1464 NULL, NULL, PERF_MAX_STACK_DEPTH) == 0) {
1465 callchain_cursor_commit(cursor);
1466
1467 pchain = PyObject_New(struct pyrf_callchain, &pyrf_callchain__type);
1468 if (!pchain) {
1469 addr_location__exit(&al);
1470 Py_DECREF(pevent);
1471 return NULL;
1472 }
1473 pchain->nr_frames = cursor->nr;
1474 pchain->frames = calloc(pchain->nr_frames,
1475 sizeof(*pchain->frames));
1476 if (!pchain->frames) {
1477 Py_DECREF(pchain);
1478 addr_location__exit(&al);
1479 Py_DECREF(pevent);
1480 return PyErr_NoMemory();
1481 }
1482 struct callchain_cursor_node *node;
1483
1484 for (i = 0; i < pchain->nr_frames; i++) {
1485 node = callchain_cursor_current(cursor);
1486 pchain->frames[i].ip = node->ip;
1487 pchain->frames[i].map =
1488 map__get(node->ms.map);
1489 pchain->frames[i].sym = node->ms.sym;
1490 callchain_cursor_advance(cursor);
1491 }
1492 pevent->callchain = (PyObject *)pchain;
1493 }
1494 addr_location__exit(&al);
1495 }
1496 }
1497 if (sample->branch_stack) {
1498 struct branch_stack *bs = sample->branch_stack;
1499 struct branch_entry *entries = perf_sample__branch_entries(sample);
1500 struct pyrf_branch_stack *pstack;
1501
1502 pstack = PyObject_New(struct pyrf_branch_stack, &pyrf_branch_stack__type);
1503 if (!pstack) {
1504 Py_DECREF(pevent);
1505 return NULL;
1506 }
1507 pstack->nr = bs->nr;
1508 pstack->entries = calloc(bs->nr, sizeof(struct branch_entry));
1509 if (!pstack->entries) {
1510 Py_DECREF(pstack);
1511 Py_DECREF(pevent);
1512 return PyErr_NoMemory();
1513 }
1514 memcpy(pstack->entries, entries,
1515 bs->nr * sizeof(struct branch_entry));
1516 pevent->brstack = (PyObject *)pstack;
1517 }
1518 return (PyObject *)pevent;
1519}
1520
1521struct pyrf_cpu_map {
1522 PyObject_HEAD
1523
1524 struct perf_cpu_map *cpus;
1525};
1526
1527static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
1528 PyObject *args, PyObject *kwargs)
1529{
1530 static char *kwlist[] = { "cpustr", NULL };
1531 char *cpustr = NULL;
1532
1533 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
1534 kwlist, &cpustr))
1535 return -1;
1536
1537 pcpus->cpus = perf_cpu_map__new(cpustr);
1538 if (pcpus->cpus == NULL)
1539 return -1;
1540 return 0;
1541}
1542
1543static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
1544{
1545 perf_cpu_map__put(pcpus->cpus);
1546 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
1547}
1548
1549static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
1550{
1551 struct pyrf_cpu_map *pcpus = (void *)obj;
1552
1553 return perf_cpu_map__nr(pcpus->cpus);
1554}
1555
1556static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
1557{
1558 struct pyrf_cpu_map *pcpus = (void *)obj;
1559
1560 if (i >= perf_cpu_map__nr(pcpus->cpus)) {
1561 PyErr_SetString(PyExc_IndexError, "Index out of range");
1562 return NULL;
1563 }
1564
1565 return Py_BuildValue("i", perf_cpu_map__cpu(pcpus->cpus, i).cpu);
1566}
1567
1568static PySequenceMethods pyrf_cpu_map__sequence_methods = {
1569 .sq_length = pyrf_cpu_map__length,
1570 .sq_item = pyrf_cpu_map__item,
1571};
1572
1573static const char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
1574
1575static PyTypeObject pyrf_cpu_map__type = {
1576 PyVarObject_HEAD_INIT(NULL, 0)
1577 .tp_name = "perf.cpu_map",
1578 .tp_basicsize = sizeof(struct pyrf_cpu_map),
1579 .tp_dealloc = (destructor)pyrf_cpu_map__delete,
1580 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1581 .tp_doc = pyrf_cpu_map__doc,
1582 .tp_as_sequence = &pyrf_cpu_map__sequence_methods,
1583 .tp_init = (initproc)pyrf_cpu_map__init,
1584};
1585
1586static int pyrf_cpu_map__setup_types(void)
1587{
1588 pyrf_cpu_map__type.tp_new = PyType_GenericNew;
1589 return PyType_Ready(&pyrf_cpu_map__type);
1590}
1591
1592struct pyrf_thread_map {
1593 PyObject_HEAD
1594
1595 struct perf_thread_map *threads;
1596};
1597
1598static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
1599 PyObject *args, PyObject *kwargs)
1600{
1601 static char *kwlist[] = { "pid", "tid", NULL };
1602 int pid = -1, tid = -1;
1603
1604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
1605 kwlist, &pid, &tid))
1606 return -1;
1607
1608 pthreads->threads = thread_map__new(pid, tid);
1609 if (pthreads->threads == NULL)
1610 return -1;
1611 return 0;
1612}
1613
1614static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
1615{
1616 perf_thread_map__put(pthreads->threads);
1617 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
1618}
1619
1620static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
1621{
1622 struct pyrf_thread_map *pthreads = (void *)obj;
1623
1624 return perf_thread_map__nr(pthreads->threads);
1625}
1626
1627static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
1628{
1629 struct pyrf_thread_map *pthreads = (void *)obj;
1630
1631 if (i >= perf_thread_map__nr(pthreads->threads)) {
1632 PyErr_SetString(PyExc_IndexError, "Index out of range");
1633 return NULL;
1634 }
1635
1636 return Py_BuildValue("i", perf_thread_map__pid(pthreads->threads, i));
1637}
1638
1639static PySequenceMethods pyrf_thread_map__sequence_methods = {
1640 .sq_length = pyrf_thread_map__length,
1641 .sq_item = pyrf_thread_map__item,
1642};
1643
1644static const char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
1645
1646static PyTypeObject pyrf_thread_map__type = {
1647 PyVarObject_HEAD_INIT(NULL, 0)
1648 .tp_name = "perf.thread_map",
1649 .tp_basicsize = sizeof(struct pyrf_thread_map),
1650 .tp_dealloc = (destructor)pyrf_thread_map__delete,
1651 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1652 .tp_doc = pyrf_thread_map__doc,
1653 .tp_as_sequence = &pyrf_thread_map__sequence_methods,
1654 .tp_init = (initproc)pyrf_thread_map__init,
1655};
1656
1657static int pyrf_thread_map__setup_types(void)
1658{
1659 pyrf_thread_map__type.tp_new = PyType_GenericNew;
1660 return PyType_Ready(&pyrf_thread_map__type);
1661}
1662
1663/**
1664 * A python wrapper for perf_pmus that are globally owned by the pmus.c code.
1665 */
1666struct pyrf_pmu {
1667 PyObject_HEAD
1668
1669 struct perf_pmu *pmu;
1670};
1671
1672static void pyrf_pmu__delete(struct pyrf_pmu *ppmu)
1673{
1674 Py_TYPE(ppmu)->tp_free((PyObject *)ppmu);
1675}
1676
1677static PyObject *pyrf_pmu__name(PyObject *self)
1678{
1679 struct pyrf_pmu *ppmu = (void *)self;
1680
1681 CHECK_INITIALIZED(ppmu->pmu, "pmu");
1682 return PyUnicode_FromString(ppmu->pmu->name);
1683}
1684
1685static bool add_to_dict(PyObject *dict, const char *key, const char *value)
1686{
1687 PyObject *pkey, *pvalue;
1688 bool ret;
1689
1690 if (value == NULL)
1691 return true;
1692
1693 pkey = PyUnicode_FromString(key);
1694 pvalue = PyUnicode_FromString(value);
1695
1696 ret = pkey && pvalue && PyDict_SetItem(dict, pkey, pvalue) == 0;
1697 Py_XDECREF(pkey);
1698 Py_XDECREF(pvalue);
1699 return ret;
1700}
1701
1702static int pyrf_pmu__events_cb(void *state, struct pmu_event_info *info)
1703{
1704 PyObject *py_list = state;
1705 PyObject *dict = PyDict_New();
1706
1707 if (!dict)
1708 return -ENOMEM;
1709
1710 if (!add_to_dict(dict, "name", info->name) ||
1711 !add_to_dict(dict, "alias", info->alias) ||
1712 !add_to_dict(dict, "scale_unit", info->scale_unit) ||
1713 !add_to_dict(dict, "desc", info->desc) ||
1714 !add_to_dict(dict, "long_desc", info->long_desc) ||
1715 !add_to_dict(dict, "encoding_desc", info->encoding_desc) ||
1716 !add_to_dict(dict, "topic", info->topic) ||
1717 !add_to_dict(dict, "event_type_desc", info->event_type_desc) ||
1718 !add_to_dict(dict, "str", info->str) ||
1719 !add_to_dict(dict, "deprecated", info->deprecated ? "deprecated" : NULL) ||
1720 PyList_Append(py_list, dict) != 0) {
1721 Py_DECREF(dict);
1722 return -ENOMEM;
1723 }
1724 Py_DECREF(dict);
1725 return 0;
1726}
1727
1728static PyObject *pyrf_pmu__events(PyObject *self)
1729{
1730 struct pyrf_pmu *ppmu = (void *)self;
1731 PyObject *py_list;
1732 int ret;
1733
1734 CHECK_INITIALIZED(ppmu->pmu, "pmu");
1735
1736 py_list = PyList_New(0);
1737 if (!py_list)
1738 return NULL;
1739
1740 ret = perf_pmu__for_each_event(ppmu->pmu,
1741 /*skip_duplicate_pmus=*/false,
1742 py_list,
1743 pyrf_pmu__events_cb);
1744 if (ret) {
1745 Py_DECREF(py_list);
1746 errno = -ret;
1747 PyErr_SetFromErrno(PyExc_OSError);
1748 return NULL;
1749 }
1750 return py_list;
1751}
1752
1753static PyObject *pyrf_pmu__repr(PyObject *self)
1754{
1755 struct pyrf_pmu *ppmu = (void *)self;
1756
1757 CHECK_INITIALIZED(ppmu->pmu, "pmu");
1758 return PyUnicode_FromFormat("pmu(%s)", ppmu->pmu->name);
1759}
1760
1761static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object.");
1762
1763static PyMethodDef pyrf_pmu__methods[] = {
1764 {
1765 .ml_name = "events",
1766 .ml_meth = (PyCFunction)pyrf_pmu__events,
1767 .ml_flags = METH_NOARGS,
1768 .ml_doc = PyDoc_STR("Returns a sequence of events encoded as a dictionaries.")
1769 },
1770 {
1771 .ml_name = "name",
1772 .ml_meth = (PyCFunction)pyrf_pmu__name,
1773 .ml_flags = METH_NOARGS,
1774 .ml_doc = PyDoc_STR("Name of the PMU including suffixes.")
1775 },
1776 { .ml_name = NULL, }
1777};
1778
1779/** The python type for a perf.pmu. */
1780static PyTypeObject pyrf_pmu__type = {
1781 PyVarObject_HEAD_INIT(NULL, 0)
1782 .tp_name = "perf.pmu",
1783 .tp_basicsize = sizeof(struct pyrf_pmu),
1784 .tp_dealloc = (destructor)pyrf_pmu__delete,
1785 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1786 .tp_doc = pyrf_pmu__doc,
1787 .tp_methods = pyrf_pmu__methods,
1788 .tp_str = pyrf_pmu__name,
1789 .tp_repr = pyrf_pmu__repr,
1790};
1791
1792static int pyrf_pmu__setup_types(void)
1793{
1794 pyrf_pmu__type.tp_new = PyType_GenericNew;
1795 return PyType_Ready(&pyrf_pmu__type);
1796}
1797
1798
1799/** A python iterator for pmus that has no equivalent in the C code. */
1800struct pyrf_pmu_iterator {
1801 PyObject_HEAD
1802 struct perf_pmu *pmu;
1803};
1804
1805static void pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator *self)
1806{
1807 Py_TYPE(self)->tp_free((PyObject *) self);
1808}
1809
1810static PyObject *pyrf_pmu_iterator__new(PyTypeObject *type, PyObject *args __maybe_unused,
1811 PyObject *kwds __maybe_unused)
1812{
1813 struct pyrf_pmu_iterator *itr = (void *)type->tp_alloc(type, 0);
1814
1815 if (itr != NULL)
1816 itr->pmu = perf_pmus__scan(/*pmu=*/NULL);
1817
1818 return (PyObject *) itr;
1819}
1820
1821static PyObject *pyrf_pmu_iterator__iter(PyObject *self)
1822{
1823 Py_INCREF(self);
1824 return self;
1825}
1826
1827static PyObject *pyrf_pmu_iterator__iternext(PyObject *self)
1828{
1829 struct pyrf_pmu_iterator *itr = (void *)self;
1830 struct pyrf_pmu *ppmu;
1831
1832 if (itr->pmu == NULL) {
1833 PyErr_SetNone(PyExc_StopIteration);
1834 return NULL;
1835 }
1836 // Create object to return.
1837 ppmu = PyObject_New(struct pyrf_pmu, &pyrf_pmu__type);
1838 if (ppmu) {
1839 ppmu->pmu = itr->pmu;
1840 // Advance iterator.
1841 itr->pmu = perf_pmus__scan(itr->pmu);
1842 }
1843 return (PyObject *)ppmu;
1844}
1845
1846/** The python type for the PMU iterator. */
1847static PyTypeObject pyrf_pmu_iterator__type = {
1848 PyVarObject_HEAD_INIT(NULL, 0)
1849 .tp_name = "pmus.iterator",
1850 .tp_doc = "Iterator for the pmus string sequence.",
1851 .tp_basicsize = sizeof(struct pyrf_pmu_iterator),
1852 .tp_itemsize = 0,
1853 .tp_flags = Py_TPFLAGS_DEFAULT,
1854 .tp_new = pyrf_pmu_iterator__new,
1855 .tp_dealloc = (destructor) pyrf_pmu_iterator__dealloc,
1856 .tp_iter = pyrf_pmu_iterator__iter,
1857 .tp_iternext = pyrf_pmu_iterator__iternext,
1858};
1859
1860static int pyrf_pmu_iterator__setup_types(void)
1861{
1862 return PyType_Ready(&pyrf_pmu_iterator__type);
1863}
1864
1865static PyObject *pyrf__pmus(PyObject *self, PyObject *args)
1866{
1867 // Calling the class creates an instance of the iterator.
1868 return PyObject_CallObject((PyObject *) &pyrf_pmu_iterator__type, /*args=*/NULL);
1869}
1870
1871struct pyrf_counts_values {
1872 PyObject_HEAD
1873
1874 struct perf_counts_values values;
1875};
1876
1877static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object.");
1878
1879static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values)
1880{
1881 Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values);
1882}
1883
1884#define counts_values_member_def(member, ptype, help) \
1885 { #member, ptype, \
1886 offsetof(struct pyrf_counts_values, values.member), \
1887 0, help }
1888
1889static PyMemberDef pyrf_counts_values_members[] = {
1890 counts_values_member_def(val, T_ULONGLONG, "Value of event"),
1891 counts_values_member_def(ena, T_ULONGLONG, "Time for which enabled"),
1892 counts_values_member_def(run, T_ULONGLONG, "Time for which running"),
1893 counts_values_member_def(id, T_ULONGLONG, "Unique ID for an event"),
1894 counts_values_member_def(lost, T_ULONGLONG, "Num of lost samples"),
1895 { .name = NULL, },
1896};
1897
1898static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure)
1899{
1900 PyObject *vals = PyList_New(5);
1901
1902 if (!vals)
1903 return NULL;
1904 for (int i = 0; i < 5; i++) {
1905 PyObject *val = PyLong_FromUnsignedLongLong(self->values.values[i]);
1906
1907 if (!val) {
1908 Py_DECREF(vals);
1909 return NULL;
1910 }
1911 PyList_SetItem(vals, i, val);
1912 }
1913
1914 return vals;
1915}
1916
1917static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list,
1918 void *closure)
1919{
1920 Py_ssize_t size;
1921 PyObject *item = NULL;
1922
1923 if (list == NULL) {
1924 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
1925 return -1;
1926 }
1927
1928 if (!PyList_Check(list)) {
1929 PyErr_SetString(PyExc_TypeError, "Value assigned must be a list");
1930 return -1;
1931 }
1932
1933 size = PyList_Size(list);
1934 if (size != 5) {
1935 PyErr_SetString(PyExc_ValueError, "List must have exactly 5 entries");
1936 return -1;
1937 }
1938
1939 for (Py_ssize_t i = 0; i < size; i++) {
1940 unsigned long long val;
1941
1942 item = PyList_GetItem(list, i);
1943 if (!PyLong_Check(item)) {
1944 PyErr_SetString(PyExc_TypeError, "List members should be numbers");
1945 return -1;
1946 }
1947 val = PyLong_AsUnsignedLongLong(item);
1948 if (val == (unsigned long long)-1 && PyErr_Occurred())
1949 return -1;
1950 self->values.values[i] = val;
1951 }
1952
1953 return 0;
1954}
1955
1956static PyGetSetDef pyrf_counts_values_getset[] = {
1957 {"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values,
1958 "Name field", NULL},
1959 { .name = NULL, },
1960};
1961
1962static PyTypeObject pyrf_counts_values__type = {
1963 PyVarObject_HEAD_INIT(NULL, 0)
1964 .tp_name = "perf.counts_values",
1965 .tp_basicsize = sizeof(struct pyrf_counts_values),
1966 .tp_dealloc = (destructor)pyrf_counts_values__delete,
1967 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1968 .tp_doc = pyrf_counts_values__doc,
1969 .tp_members = pyrf_counts_values_members,
1970 .tp_getset = pyrf_counts_values_getset,
1971};
1972
1973static int pyrf_counts_values__setup_types(void)
1974{
1975 pyrf_counts_values__type.tp_new = PyType_GenericNew;
1976 return PyType_Ready(&pyrf_counts_values__type);
1977}
1978
1979struct pyrf_evsel {
1980 PyObject_HEAD
1981
1982 struct evsel *evsel;
1983};
1984
1985static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
1986 PyObject *args, PyObject *kwargs)
1987{
1988 struct perf_event_attr attr = {
1989 .type = PERF_TYPE_HARDWARE,
1990 .config = PERF_COUNT_HW_CPU_CYCLES,
1991 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
1992 };
1993 static char *kwlist[] = {
1994 "type",
1995 "config",
1996 "sample_freq",
1997 "sample_period",
1998 "sample_type",
1999 "read_format",
2000 "disabled",
2001 "inherit",
2002 "pinned",
2003 "exclusive",
2004 "exclude_user",
2005 "exclude_kernel",
2006 "exclude_hv",
2007 "exclude_idle",
2008 "mmap",
2009 "context_switch",
2010 "comm",
2011 "freq",
2012 "inherit_stat",
2013 "enable_on_exec",
2014 "task",
2015 "watermark",
2016 "precise_ip",
2017 "mmap_data",
2018 "sample_id_all",
2019 "wakeup_events",
2020 "bp_type",
2021 "bp_addr",
2022 "bp_len",
2023 "idx",
2024 NULL
2025 };
2026 u64 sample_period = 0;
2027 u32 disabled = 0,
2028 inherit = 0,
2029 pinned = 0,
2030 exclusive = 0,
2031 exclude_user = 0,
2032 exclude_kernel = 0,
2033 exclude_hv = 0,
2034 exclude_idle = 0,
2035 mmap = 0,
2036 context_switch = 0,
2037 comm = 0,
2038 freq = 1,
2039 inherit_stat = 0,
2040 enable_on_exec = 0,
2041 task = 0,
2042 watermark = 0,
2043 precise_ip = 0,
2044 mmap_data = 0,
2045 sample_id_all = 1,
2046 idx = 0;
2047
2048 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
2049 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKKi", kwlist,
2050 &attr.type, &attr.config, &attr.sample_freq,
2051 &sample_period, &attr.sample_type,
2052 &attr.read_format, &disabled, &inherit,
2053 &pinned, &exclusive, &exclude_user,
2054 &exclude_kernel, &exclude_hv, &exclude_idle,
2055 &mmap, &context_switch, &comm, &freq, &inherit_stat,
2056 &enable_on_exec, &task, &watermark,
2057 &precise_ip, &mmap_data, &sample_id_all,
2058 &attr.wakeup_events, &attr.bp_type,
2059 &attr.bp_addr, &attr.bp_len, &idx))
2060 return -1;
2061
2062 /* union... */
2063 if (sample_period != 0) {
2064 if (attr.sample_freq != 0)
2065 return -1; /* FIXME: throw right exception */
2066 attr.sample_period = sample_period;
2067 }
2068
2069 /* Bitfields */
2070 attr.disabled = disabled;
2071 attr.inherit = inherit;
2072 attr.pinned = pinned;
2073 attr.exclusive = exclusive;
2074 attr.exclude_user = exclude_user;
2075 attr.exclude_kernel = exclude_kernel;
2076 attr.exclude_hv = exclude_hv;
2077 attr.exclude_idle = exclude_idle;
2078 attr.mmap = mmap;
2079 attr.context_switch = context_switch;
2080 attr.comm = comm;
2081 attr.freq = freq;
2082 attr.inherit_stat = inherit_stat;
2083 attr.enable_on_exec = enable_on_exec;
2084 attr.task = task;
2085 attr.watermark = watermark;
2086 attr.precise_ip = precise_ip;
2087 attr.mmap_data = mmap_data;
2088 attr.sample_id_all = sample_id_all;
2089 attr.size = sizeof(attr);
2090
2091 evsel__put(pevsel->evsel);
2092 pevsel->evsel = evsel__new(&attr);
2093 if (!pevsel->evsel) {
2094 PyErr_NoMemory();
2095 return -1;
2096 }
2097 return 0;
2098}
2099
2100static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
2101{
2102 evsel__put(pevsel->evsel);
2103 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
2104}
2105
2106static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
2107 PyObject *args, PyObject *kwargs)
2108{
2109 struct evsel *evsel = pevsel->evsel;
2110 struct perf_cpu_map *cpus = NULL;
2111 struct perf_thread_map *threads = NULL;
2112 PyObject *pcpus = NULL, *pthreads = NULL;
2113 int group = 0, inherit = 0;
2114 static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
2115
2116 CHECK_INITIALIZED(evsel, "evsel");
2117
2118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
2119 &pcpus, &pthreads, &group, &inherit))
2120 return NULL;
2121
2122 if (pthreads != NULL && pthreads != Py_None) {
2123 if (!PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) {
2124 PyErr_SetString(PyExc_TypeError, "threads must be a thread_map");
2125 return NULL;
2126 }
2127 threads = ((struct pyrf_thread_map *)pthreads)->threads;
2128 }
2129
2130 if (pcpus != NULL && pcpus != Py_None) {
2131 if (!PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) {
2132 PyErr_SetString(PyExc_TypeError, "cpus must be a cpu_map");
2133 return NULL;
2134 }
2135 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
2136 }
2137
2138 evsel->core.attr.inherit = inherit;
2139 /*
2140 * This will group just the fds for this single evsel, to group
2141 * multiple events, use evlist.open().
2142 */
2143 if (evsel__open(evsel, cpus, threads) < 0) {
2144 PyErr_SetFromErrno(PyExc_OSError);
2145 return NULL;
2146 }
2147
2148 Py_INCREF(Py_None);
2149 return Py_None;
2150}
2151
2152static PyObject *pyrf_evsel__cpus(struct pyrf_evsel *pevsel)
2153{
2154 struct pyrf_cpu_map *pcpu_map;
2155
2156 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2157
2158 pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type);
2159 if (pcpu_map)
2160 pcpu_map->cpus = perf_cpu_map__get(pevsel->evsel->core.cpus);
2161
2162 return (PyObject *)pcpu_map;
2163}
2164
2165static PyObject *pyrf_evsel__threads(struct pyrf_evsel *pevsel)
2166{
2167 struct pyrf_thread_map *pthread_map;
2168
2169 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2170
2171 pthread_map = PyObject_New(struct pyrf_thread_map, &pyrf_thread_map__type);
2172 if (pthread_map)
2173 pthread_map->threads = perf_thread_map__get(pevsel->evsel->core.threads);
2174
2175 return (PyObject *)pthread_map;
2176}
2177
2178/*
2179 * Ensure evsel's counts and prev_raw_counts are allocated, the latter
2180 * used by tool PMUs to compute the cumulative count as expected by
2181 * stat's process_counter_values.
2182 */
2183static int evsel__ensure_counts(struct evsel *evsel)
2184{
2185 int nthreads, ncpus;
2186
2187 if (evsel->counts != NULL)
2188 return 0;
2189
2190 nthreads = perf_thread_map__nr(evsel->core.threads);
2191 ncpus = perf_cpu_map__nr(evsel->core.cpus);
2192
2193 evsel->counts = perf_counts__new(ncpus, nthreads);
2194 if (evsel->counts == NULL)
2195 return -ENOMEM;
2196
2197 evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads);
2198 if (evsel->prev_raw_counts == NULL)
2199 return -ENOMEM;
2200
2201 return 0;
2202}
2203
2204static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel,
2205 PyObject *args, PyObject *kwargs)
2206{
2207 struct evsel *evsel = pevsel->evsel;
2208 int cpu = 0, cpu_idx, thread = 0, thread_idx;
2209 struct perf_counts_values *old_count, *new_count;
2210 struct pyrf_counts_values *count_values;
2211
2212 CHECK_INITIALIZED(evsel, "evsel");
2213
2214 if (!PyArg_ParseTuple(args, "ii", &cpu, &thread))
2215 return NULL;
2216
2217 cpu_idx = perf_cpu_map__idx(evsel->core.cpus, (struct perf_cpu){.cpu = cpu});
2218 if (cpu_idx < 0) {
2219 PyErr_Format(PyExc_TypeError, "CPU %d is not part of evsel's CPUs", cpu);
2220 return NULL;
2221 }
2222 thread_idx = perf_thread_map__idx(evsel->core.threads, thread);
2223 if (thread_idx < 0) {
2224 PyErr_Format(PyExc_TypeError, "Thread %d is not part of evsel's threads",
2225 thread);
2226 return NULL;
2227 }
2228
2229 if (evsel__ensure_counts(evsel))
2230 return PyErr_NoMemory();
2231
2232 count_values = PyObject_New(struct pyrf_counts_values, &pyrf_counts_values__type);
2233 if (!count_values)
2234 return NULL;
2235
2236 /* Set up pointers to the old and newly read counter values. */
2237 old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx);
2238 new_count = perf_counts(evsel->counts, cpu_idx, thread_idx);
2239 /* Update the value in evsel->counts. */
2240 evsel__read_counter(evsel, cpu_idx, thread_idx);
2241 /* Copy the value and turn it into the delta from old_count. */
2242 count_values->values = *new_count;
2243 count_values->values.val -= old_count->val;
2244 count_values->values.ena -= old_count->ena;
2245 count_values->values.run -= old_count->run;
2246 /* Save the new count over the old_count for the next read. */
2247 *old_count = *new_count;
2248 return (PyObject *)count_values;
2249}
2250
2251static PyObject *pyrf_evsel__str(PyObject *self)
2252{
2253 struct pyrf_evsel *pevsel = (void *)self;
2254 struct evsel *evsel = pevsel->evsel;
2255
2256 if (!evsel)
2257 return PyUnicode_FromString("evsel(uninitialized)");
2258
2259 return PyUnicode_FromFormat("evsel(%s)", evsel__name(evsel));
2260}
2261
2262static PyMethodDef pyrf_evsel__methods[] = {
2263 {
2264 .ml_name = "open",
2265 .ml_meth = (PyCFunction)pyrf_evsel__open,
2266 .ml_flags = METH_VARARGS | METH_KEYWORDS,
2267 .ml_doc = PyDoc_STR("open the event selector file descriptor table.")
2268 },
2269 {
2270 .ml_name = "cpus",
2271 .ml_meth = (PyCFunction)pyrf_evsel__cpus,
2272 .ml_flags = METH_NOARGS,
2273 .ml_doc = PyDoc_STR("CPUs the event is to be used with.")
2274 },
2275 {
2276 .ml_name = "threads",
2277 .ml_meth = (PyCFunction)pyrf_evsel__threads,
2278 .ml_flags = METH_NOARGS,
2279 .ml_doc = PyDoc_STR("threads the event is to be used with.")
2280 },
2281 {
2282 .ml_name = "read",
2283 .ml_meth = (PyCFunction)pyrf_evsel__read,
2284 .ml_flags = METH_VARARGS | METH_KEYWORDS,
2285 .ml_doc = PyDoc_STR("read counters")
2286 },
2287 { .ml_name = NULL, }
2288};
2289
2290static PyObject *pyrf_evsel__get_tracking(PyObject *self, void *closure __maybe_unused)
2291{
2292 struct pyrf_evsel *pevsel = (void *)self;
2293
2294 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2295
2296 if (pevsel->evsel->tracking)
2297 Py_RETURN_TRUE;
2298 else
2299 Py_RETURN_FALSE;
2300}
2301
2302static int pyrf_evsel__set_tracking(PyObject *self, PyObject *val, void *closure __maybe_unused)
2303{
2304 struct pyrf_evsel *pevsel = (void *)self;
2305 int is_true;
2306
2307 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2308
2309 if (val == NULL) {
2310 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2311 return -1;
2312 }
2313
2314 is_true = PyObject_IsTrue(val);
2315 if (is_true < 0)
2316 return -1;
2317
2318 pevsel->evsel->tracking = is_true;
2319 return 0;
2320}
2321
2322static int pyrf_evsel__set_attr_config(PyObject *self, PyObject *val, void *closure __maybe_unused)
2323{
2324 struct pyrf_evsel *pevsel = (void *)self;
2325 unsigned long long new_val;
2326
2327 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2328
2329 if (val == NULL) {
2330 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2331 return -1;
2332 }
2333
2334 new_val = PyLong_AsUnsignedLongLong(val);
2335 if (PyErr_Occurred())
2336 return -1;
2337
2338 pevsel->evsel->core.attr.config = new_val;
2339 return 0;
2340}
2341
2342static PyObject *pyrf_evsel__get_attr_config(PyObject *self, void *closure __maybe_unused)
2343{
2344 struct pyrf_evsel *pevsel = (void *)self;
2345
2346 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2347
2348 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.config);
2349}
2350
2351static int pyrf_evsel__set_attr_read_format(PyObject *self, PyObject *val, void *closure __maybe_unused)
2352{
2353 struct pyrf_evsel *pevsel = (void *)self;
2354 unsigned long long new_val;
2355
2356 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2357
2358 if (val == NULL) {
2359 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2360 return -1;
2361 }
2362
2363 new_val = PyLong_AsUnsignedLongLong(val);
2364 if (PyErr_Occurred())
2365 return -1;
2366
2367 pevsel->evsel->core.attr.read_format = new_val;
2368 return 0;
2369}
2370
2371static PyObject *pyrf_evsel__get_attr_read_format(PyObject *self, void *closure __maybe_unused)
2372{
2373 struct pyrf_evsel *pevsel = (void *)self;
2374
2375 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2376
2377 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.read_format);
2378}
2379
2380static int pyrf_evsel__set_attr_sample_period(PyObject *self, PyObject *val, void *closure __maybe_unused)
2381{
2382 struct pyrf_evsel *pevsel = (void *)self;
2383 unsigned long long new_val;
2384
2385 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2386
2387 if (val == NULL) {
2388 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2389 return -1;
2390 }
2391
2392 new_val = PyLong_AsUnsignedLongLong(val);
2393 if (PyErr_Occurred())
2394 return -1;
2395
2396 pevsel->evsel->core.attr.sample_period = new_val;
2397 return 0;
2398}
2399
2400static PyObject *pyrf_evsel__get_attr_sample_period(PyObject *self, void *closure __maybe_unused)
2401{
2402 struct pyrf_evsel *pevsel = (void *)self;
2403
2404 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2405
2406 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.sample_period);
2407}
2408
2409static int pyrf_evsel__set_attr_sample_type(PyObject *self, PyObject *val, void *closure __maybe_unused)
2410{
2411 struct pyrf_evsel *pevsel = (void *)self;
2412 unsigned long long new_val;
2413
2414 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2415
2416 if (val == NULL) {
2417 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2418 return -1;
2419 }
2420
2421 new_val = PyLong_AsUnsignedLongLong(val);
2422 if (PyErr_Occurred())
2423 return -1;
2424
2425 pevsel->evsel->core.attr.sample_type = new_val;
2426 return 0;
2427}
2428
2429static PyObject *pyrf_evsel__get_attr_sample_type(PyObject *self, void *closure __maybe_unused)
2430{
2431 struct pyrf_evsel *pevsel = (void *)self;
2432
2433 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2434
2435 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.sample_type);
2436}
2437
2438static PyObject *pyrf_evsel__get_attr_size(PyObject *self, void *closure __maybe_unused)
2439{
2440 struct pyrf_evsel *pevsel = (void *)self;
2441
2442 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2443
2444 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.size);
2445}
2446
2447static int pyrf_evsel__set_attr_type(PyObject *self, PyObject *val, void *closure __maybe_unused)
2448{
2449 struct pyrf_evsel *pevsel = (void *)self;
2450 unsigned long new_val;
2451
2452 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2453
2454 if (val == NULL) {
2455 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2456 return -1;
2457 }
2458
2459 new_val = PyLong_AsUnsignedLong(val);
2460 if (PyErr_Occurred())
2461 return -1;
2462
2463 pevsel->evsel->core.attr.type = new_val;
2464 return 0;
2465}
2466
2467static PyObject *pyrf_evsel__get_attr_type(PyObject *self, void *closure __maybe_unused)
2468{
2469 struct pyrf_evsel *pevsel = (void *)self;
2470
2471 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2472
2473 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.type);
2474}
2475
2476static int pyrf_evsel__set_attr_wakeup_events(PyObject *self, PyObject *val, void *closure __maybe_unused)
2477{
2478 struct pyrf_evsel *pevsel = (void *)self;
2479 unsigned long new_val;
2480
2481 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel");
2482
2483 if (val == NULL) {
2484 PyErr_SetString(PyExc_TypeError, "cannot delete attribute");
2485 return -1;
2486 }
2487
2488 new_val = PyLong_AsUnsignedLong(val);
2489 if (PyErr_Occurred())
2490 return -1;
2491
2492 pevsel->evsel->core.attr.wakeup_events = new_val;
2493 return 0;
2494}
2495
2496static PyObject *pyrf_evsel__get_attr_wakeup_events(PyObject *self, void *closure __maybe_unused)
2497{
2498 struct pyrf_evsel *pevsel = (void *)self;
2499
2500 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2501
2502 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.wakeup_events);
2503}
2504
2505static PyObject *pyrf_evsel__get_ids(struct pyrf_evsel *pevsel, void *closure __maybe_unused)
2506{
2507 struct evsel *evsel;
2508 PyObject *list;
2509
2510 CHECK_INITIALIZED(pevsel->evsel, "evsel");
2511
2512 evsel = pevsel->evsel;
2513 list = PyList_New(0);
2514
2515 if (!list)
2516 return NULL;
2517
2518 for (u32 i = 0; i < evsel->core.ids; i++) {
2519 PyObject *id = PyLong_FromUnsignedLongLong(evsel->core.id[i]);
2520 int ret;
2521
2522 if (!id) {
2523 Py_DECREF(list);
2524 return NULL;
2525 }
2526 ret = PyList_Append(list, id);
2527 Py_DECREF(id);
2528 if (ret < 0) {
2529 Py_DECREF(list);
2530 return NULL;
2531 }
2532 }
2533
2534 return list;
2535}
2536
2537static PyGetSetDef pyrf_evsel__getset[] = {
2538 {
2539 .name = "ids",
2540 .get = (getter)pyrf_evsel__get_ids,
2541 .set = NULL,
2542 .doc = "event IDs.",
2543 },
2544 {
2545 .name = "tracking",
2546 .get = pyrf_evsel__get_tracking,
2547 .set = pyrf_evsel__set_tracking,
2548 .doc = "tracking event.",
2549 },
2550 {
2551 .name = "config",
2552 .get = pyrf_evsel__get_attr_config,
2553 .set = pyrf_evsel__set_attr_config,
2554 .doc = "attribute config.",
2555 },
2556 {
2557 .name = "read_format",
2558 .get = pyrf_evsel__get_attr_read_format,
2559 .set = pyrf_evsel__set_attr_read_format,
2560 .doc = "attribute read_format.",
2561 },
2562 {
2563 .name = "sample_period",
2564 .get = pyrf_evsel__get_attr_sample_period,
2565 .set = pyrf_evsel__set_attr_sample_period,
2566 .doc = "attribute sample_period.",
2567 },
2568 {
2569 .name = "sample_type",
2570 .get = pyrf_evsel__get_attr_sample_type,
2571 .set = pyrf_evsel__set_attr_sample_type,
2572 .doc = "attribute sample_type.",
2573 },
2574 {
2575 .name = "size",
2576 .get = pyrf_evsel__get_attr_size,
2577 .doc = "attribute size.",
2578 },
2579 {
2580 .name = "type",
2581 .get = pyrf_evsel__get_attr_type,
2582 .set = pyrf_evsel__set_attr_type,
2583 .doc = "attribute type.",
2584 },
2585 {
2586 .name = "wakeup_events",
2587 .get = pyrf_evsel__get_attr_wakeup_events,
2588 .set = pyrf_evsel__set_attr_wakeup_events,
2589 .doc = "attribute wakeup_events.",
2590 },
2591 { .name = NULL},
2592};
2593
2594static const char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
2595
2596static PyObject *pyrf_evsel__getattro(struct pyrf_evsel *pevsel, PyObject *attr_name)
2597{
2598 if (!pevsel->evsel) {
2599 PyErr_SetString(PyExc_ValueError, "evsel not initialized");
2600 return NULL;
2601 }
2602 return PyObject_GenericGetAttr((PyObject *) pevsel, attr_name);
2603}
2604
2605static int pyrf_evsel__setattro(struct pyrf_evsel *pevsel, PyObject *attr_name, PyObject *value)
2606{
2607 if (!pevsel->evsel) {
2608 PyErr_SetString(PyExc_ValueError, "evsel not initialized");
2609 return -1;
2610 }
2611 return PyObject_GenericSetAttr((PyObject *) pevsel, attr_name, value);
2612}
2613
2614static PyTypeObject pyrf_evsel__type = {
2615 PyVarObject_HEAD_INIT(NULL, 0)
2616 .tp_name = "perf.evsel",
2617 .tp_basicsize = sizeof(struct pyrf_evsel),
2618 .tp_dealloc = (destructor)pyrf_evsel__delete,
2619 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2620 .tp_doc = pyrf_evsel__doc,
2621 .tp_getset = pyrf_evsel__getset,
2622 .tp_methods = pyrf_evsel__methods,
2623 .tp_init = (initproc)pyrf_evsel__init,
2624 .tp_str = pyrf_evsel__str,
2625 .tp_repr = pyrf_evsel__str,
2626 .tp_getattro = (getattrofunc) pyrf_evsel__getattro,
2627 .tp_setattro = (setattrofunc) pyrf_evsel__setattro,
2628};
2629
2630static PyObject *pyrf_evsel__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2631{
2632 struct pyrf_evsel *pevsel;
2633
2634 pevsel = (struct pyrf_evsel *)PyType_GenericNew(type, args, kwargs);
2635 if (pevsel)
2636 pevsel->evsel = NULL;
2637 return (PyObject *)pevsel;
2638}
2639
2640static int pyrf_evsel__setup_types(void)
2641{
2642 pyrf_evsel__type.tp_new = pyrf_evsel__new;
2643 return PyType_Ready(&pyrf_evsel__type);
2644}
2645
2646struct pyrf_evlist {
2647 PyObject_HEAD
2648
2649 struct evlist *evlist;
2650};
2651
2652static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
2653 PyObject *args, PyObject *kwargs __maybe_unused)
2654{
2655 PyObject *pcpus = NULL, *pthreads = NULL;
2656 struct perf_cpu_map *cpus;
2657 struct perf_thread_map *threads;
2658
2659 if (!PyArg_ParseTuple(args, "O!O!",
2660 &pyrf_cpu_map__type, &pcpus,
2661 &pyrf_thread_map__type, &pthreads))
2662 return -1;
2663
2664 evlist__put(pevlist->evlist);
2665 pevlist->evlist = evlist__new();
2666 if (!pevlist->evlist) {
2667 PyErr_NoMemory();
2668 return -1;
2669 }
2670 threads = ((struct pyrf_thread_map *)pthreads)->threads;
2671 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
2672 perf_evlist__set_maps(evlist__core(pevlist->evlist), cpus, threads);
2673
2674 return 0;
2675}
2676
2677static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
2678{
2679 evlist__put(pevlist->evlist);
2680 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
2681}
2682
2683static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist)
2684{
2685 struct pyrf_cpu_map *pcpu_map;
2686
2687 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2688
2689 pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type);
2690 if (pcpu_map)
2691 pcpu_map->cpus = perf_cpu_map__get(evlist__core(pevlist->evlist)->all_cpus);
2692
2693 return (PyObject *)pcpu_map;
2694}
2695
2696static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
2697{
2698 PyObject *list;
2699 struct rb_node *node;
2700
2701 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2702
2703 list = PyList_New(/*len=*/0);
2704 if (!list)
2705 return NULL;
2706
2707 for (node = rb_first_cached(&evlist__metric_events(pevlist->evlist)->entries); node;
2708 node = rb_next(node)) {
2709 struct metric_event *me = container_of(node, struct metric_event, nd);
2710 struct list_head *pos;
2711
2712 list_for_each(pos, &me->head) {
2713 struct metric_expr *expr = container_of(pos, struct metric_expr, nd);
2714 PyObject *str = PyUnicode_FromString(expr->metric_name);
2715
2716 if (!str || PyList_Append(list, str) != 0) {
2717 Py_DECREF(list);
2718 return NULL;
2719 }
2720 Py_DECREF(str);
2721 }
2722 }
2723 return list;
2724}
2725
2726static int prepare_metric(const struct metric_expr *mexp,
2727 const struct evsel *evsel,
2728 struct expr_parse_ctx *pctx,
2729 int cpu_idx, int thread_idx)
2730{
2731 struct evsel * const *metric_events = mexp->metric_events;
2732 struct metric_ref *metric_refs = mexp->metric_refs;
2733
2734 for (int i = 0; metric_events[i]; i++) {
2735 struct evsel *cur = metric_events[i];
2736 double val, ena, run;
2737 int ret, source_count = 0;
2738 struct perf_counts_values *old_count, *new_count;
2739 char *n = strdup(evsel__metric_id(cur));
2740
2741 if (!n)
2742 return -ENOMEM;
2743
2744 /*
2745 * If there are multiple uncore PMUs and we're not reading the
2746 * leader's stats, determine the stats for the appropriate
2747 * uncore PMU.
2748 */
2749 if (evsel && evsel->metric_leader &&
2750 evsel->pmu != evsel->metric_leader->pmu &&
2751 cur->pmu == evsel->metric_leader->pmu) {
2752 struct evsel *pos;
2753
2754 evlist__for_each_entry(evsel->evlist, pos) {
2755 if (pos->pmu != evsel->pmu)
2756 continue;
2757 if (pos->metric_leader != cur)
2758 continue;
2759 cur = pos;
2760 source_count = 1;
2761 break;
2762 }
2763 }
2764
2765 if (source_count == 0)
2766 source_count = evsel__source_count(cur);
2767
2768 ret = evsel__ensure_counts(cur);
2769 if (ret)
2770 return ret;
2771
2772 /* Set up pointers to the old and newly read counter values. */
2773 old_count = perf_counts(cur->prev_raw_counts, cpu_idx, thread_idx);
2774 new_count = perf_counts(cur->counts, cpu_idx, thread_idx);
2775 /* Update the value in cur->counts. */
2776 evsel__read_counter(cur, cpu_idx, thread_idx);
2777
2778 val = new_count->val - old_count->val;
2779 ena = new_count->ena - old_count->ena;
2780 run = new_count->run - old_count->run;
2781
2782 if (ena != run && run != 0)
2783 val = val * ena / run;
2784 ret = expr__add_id_val_source_count(pctx, n, val, source_count);
2785 if (ret)
2786 return ret;
2787 }
2788
2789 for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) {
2790 int ret = expr__add_ref(pctx, &metric_refs[i]);
2791
2792 if (ret)
2793 return ret;
2794 }
2795
2796 return 0;
2797}
2798
2799static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
2800 PyObject *args, PyObject *kwargs)
2801{
2802 int ret, cpu = 0, cpu_idx = 0, thread = 0, thread_idx = 0;
2803 const char *metric;
2804 struct rb_node *node;
2805 struct metric_expr *mexp = NULL;
2806 struct expr_parse_ctx *pctx;
2807 double result = 0;
2808 struct evsel *metric_evsel = NULL;
2809
2810 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2811
2812 if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread))
2813 return NULL;
2814
2815 for (node = rb_first_cached(&evlist__metric_events(pevlist->evlist)->entries);
2816 mexp == NULL && node;
2817 node = rb_next(node)) {
2818 struct metric_event *me = container_of(node, struct metric_event, nd);
2819 struct list_head *pos;
2820
2821 list_for_each(pos, &me->head) {
2822 struct metric_expr *e = container_of(pos, struct metric_expr, nd);
2823 struct evsel *pos2;
2824
2825 if (strcmp(e->metric_name, metric))
2826 continue;
2827
2828 if (e->metric_events[0] == NULL)
2829 continue;
2830
2831 evlist__for_each_entry(pevlist->evlist, pos2) {
2832 if (pos2->metric_leader != e->metric_events[0])
2833 continue;
2834 cpu_idx = perf_cpu_map__idx(pos2->core.cpus,
2835 (struct perf_cpu){.cpu = cpu});
2836 if (cpu_idx < 0)
2837 continue;
2838
2839 thread_idx = perf_thread_map__idx(pos2->core.threads, thread);
2840 if (thread_idx < 0)
2841 continue;
2842 metric_evsel = pos2;
2843 mexp = e;
2844 goto done;
2845 }
2846 }
2847 }
2848done:
2849 if (!mexp) {
2850 PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'",
2851 metric, cpu, thread);
2852 return NULL;
2853 }
2854
2855 pctx = expr__ctx_new();
2856 if (!pctx)
2857 return PyErr_NoMemory();
2858
2859 ret = prepare_metric(mexp, metric_evsel, pctx, cpu_idx, thread_idx);
2860 if (ret) {
2861 expr__ctx_free(pctx);
2862 errno = -ret;
2863 PyErr_SetFromErrno(PyExc_OSError);
2864 return NULL;
2865 }
2866 if (expr__parse(&result, pctx, mexp->metric_expr))
2867 result = 0.0;
2868
2869 expr__ctx_free(pctx);
2870 return PyFloat_FromDouble(result);
2871}
2872
2873static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
2874 PyObject *args, PyObject *kwargs)
2875{
2876 struct evlist *evlist;
2877 static char *kwlist[] = { "pages", "overwrite", NULL };
2878 int pages = 128, overwrite = false;
2879
2880 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2881
2882 evlist = pevlist->evlist;
2883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
2884 &pages, &overwrite))
2885 return NULL;
2886
2887 if (evlist__do_mmap(evlist, pages) < 0) {
2888 PyErr_SetFromErrno(PyExc_OSError);
2889 return NULL;
2890 }
2891
2892 Py_INCREF(Py_None);
2893 return Py_None;
2894}
2895
2896static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
2897 PyObject *args, PyObject *kwargs)
2898{
2899 struct evlist *evlist;
2900 static char *kwlist[] = { "timeout", NULL };
2901 int timeout = -1, n;
2902
2903 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2904
2905 evlist = pevlist->evlist;
2906 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
2907 return NULL;
2908
2909 n = evlist__poll(evlist, timeout);
2910 if (n < 0) {
2911 PyErr_SetFromErrno(PyExc_OSError);
2912 return NULL;
2913 }
2914
2915 return Py_BuildValue("i", n);
2916}
2917
2918static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
2919 PyObject *args __maybe_unused,
2920 PyObject *kwargs __maybe_unused)
2921{
2922 struct evlist *evlist;
2923 PyObject *list;
2924 int i;
2925
2926 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2927
2928 evlist = pevlist->evlist;
2929 list = PyList_New(0);
2930 if (!list)
2931 return NULL;
2932
2933 for (i = 0; i < evlist__core(evlist)->pollfd.nr; ++i) {
2934 PyObject *file;
2935 file = PyFile_FromFd(evlist__core(evlist)->pollfd.entries[i].fd, "perf", "r", -1,
2936 NULL, NULL, NULL, 0);
2937 if (file == NULL)
2938 goto free_list;
2939
2940 if (PyList_Append(list, file) != 0) {
2941 Py_DECREF(file);
2942 goto free_list;
2943 }
2944
2945 Py_DECREF(file);
2946 }
2947
2948 return list;
2949free_list:
2950 Py_XDECREF(list);
2951 return PyErr_NoMemory();
2952}
2953
2954
2955static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
2956 PyObject *args,
2957 PyObject *kwargs __maybe_unused)
2958{
2959 struct evlist *evlist;
2960 PyObject *pevsel;
2961 struct evsel *evsel;
2962
2963 CHECK_INITIALIZED(pevlist->evlist, "evlist");
2964
2965 evlist = pevlist->evlist;
2966 if (!PyArg_ParseTuple(args, "O!", &pyrf_evsel__type, &pevsel))
2967 return NULL;
2968
2969 CHECK_INITIALIZED(((struct pyrf_evsel *)pevsel)->evsel, "evsel");
2970
2971 evsel = ((struct pyrf_evsel *)pevsel)->evsel;
2972 CHECK_INITIALIZED(evsel, "evsel");
2973
2974 evsel->core.idx = evlist__nr_entries(evlist);
2975 evlist__add(evlist, evsel__get(evsel));
2976
2977 return Py_BuildValue("i", evlist__nr_entries(evlist));
2978}
2979
2980static struct mmap *get_md(struct evlist *evlist, int cpu)
2981{
2982 int i;
2983
2984 for (i = 0; i < evlist__core(evlist)->nr_mmaps; i++) {
2985 struct mmap *md = &evlist__mmap(evlist)[i];
2986
2987 if (md->core.cpu.cpu == cpu)
2988 return md;
2989 }
2990
2991 return NULL;
2992}
2993
2994static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
2995 PyObject *args, PyObject *kwargs)
2996{
2997 struct evlist *evlist;
2998 union perf_event *event;
2999 struct evsel *evsel;
3000 int sample_id_all = 1, cpu;
3001 static char *kwlist[] = { "cpu", "sample_id_all", NULL };
3002 struct mmap *md;
3003 PyObject *pyevent;
3004 int err;
3005
3006 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3007
3008 evlist = pevlist->evlist;
3009 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
3010 &cpu, &sample_id_all))
3011 return NULL;
3012
3013 md = get_md(evlist, cpu);
3014 if (!md)
3015 return PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
3016
3017 err = perf_mmap__read_init(&md->core);
3018 if (err < 0) {
3019 if (err == -EAGAIN)
3020 Py_RETURN_NONE;
3021 return PyErr_Format(PyExc_OSError,
3022 "perf: error mmap read init, err=%d", err);
3023 }
3024
3025 event = perf_mmap__read_event(&md->core);
3026 if (event == NULL)
3027 Py_RETURN_NONE;
3028
3029 evsel = evlist__event2evsel(evlist, event);
3030 if (!evsel) {
3031 /* Unknown evsel. */
3032 perf_mmap__consume(&md->core);
3033 Py_RETURN_NONE;
3034 }
3035 pyevent = pyrf_event__new(event, evsel, evlist__session(evlist), /*machine=*/NULL);
3036 perf_mmap__consume(&md->core);
3037 if (pyevent == NULL)
3038 return PyErr_Occurred() ? NULL : PyErr_NoMemory();
3039
3040 return pyevent;
3041}
3042
3043static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
3044 PyObject *args, PyObject *kwargs)
3045{
3046 struct evlist *evlist;
3047
3048 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3049
3050 evlist = pevlist->evlist;
3051 if (evlist__open(evlist) < 0) {
3052 PyErr_SetFromErrno(PyExc_OSError);
3053 return NULL;
3054 }
3055
3056 Py_INCREF(Py_None);
3057 return Py_None;
3058}
3059
3060static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist)
3061{
3062 struct evlist *evlist;
3063
3064 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3065
3066 evlist = pevlist->evlist;
3067 evlist__close(evlist);
3068
3069 Py_INCREF(Py_None);
3070 return Py_None;
3071}
3072
3073static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
3074{
3075 struct record_opts opts = {
3076 .sample_time = true,
3077 .mmap_pages = UINT_MAX,
3078 .user_freq = UINT_MAX,
3079 .user_interval = ULLONG_MAX,
3080 .freq = 4000,
3081 .target = {
3082 .uses_mmap = true,
3083 .default_per_cpu = true,
3084 },
3085 .nr_threads_synthesize = 1,
3086 .ctl_fd = -1,
3087 .ctl_fd_ack = -1,
3088 .no_buffering = true,
3089 .no_inherit = true,
3090 };
3091 struct evlist *evlist;
3092
3093 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3094
3095 evlist = pevlist->evlist;
3096 evlist__config(evlist, &opts, &callchain_param);
3097 Py_INCREF(Py_None);
3098 return Py_None;
3099}
3100
3101static PyObject *pyrf_evlist__disable(struct pyrf_evlist *pevlist)
3102{
3103 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3104 evlist__disable(pevlist->evlist);
3105 Py_INCREF(Py_None);
3106 return Py_None;
3107}
3108
3109static PyObject *pyrf_evlist__enable(struct pyrf_evlist *pevlist)
3110{
3111 CHECK_INITIALIZED(pevlist->evlist, "evlist");
3112 evlist__enable(pevlist->evlist);
3113 Py_INCREF(Py_None);
3114 return Py_None;
3115}
3116
3117static PyMethodDef pyrf_evlist__methods[] = {
3118 {
3119 .ml_name = "all_cpus",
3120 .ml_meth = (PyCFunction)pyrf_evlist__all_cpus,
3121 .ml_flags = METH_NOARGS,
3122 .ml_doc = PyDoc_STR("CPU map union of all evsel CPU maps.")
3123 },
3124 {
3125 .ml_name = "metrics",
3126 .ml_meth = (PyCFunction)pyrf_evlist__metrics,
3127 .ml_flags = METH_NOARGS,
3128 .ml_doc = PyDoc_STR("List of metric names within the evlist.")
3129 },
3130 {
3131 .ml_name = "compute_metric",
3132 .ml_meth = (PyCFunction)pyrf_evlist__compute_metric,
3133 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3134 .ml_doc = PyDoc_STR("compute metric for given name, cpu and thread")
3135 },
3136 {
3137 .ml_name = "mmap",
3138 .ml_meth = (PyCFunction)pyrf_evlist__mmap,
3139 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3140 .ml_doc = PyDoc_STR("mmap the file descriptor table.")
3141 },
3142 {
3143 .ml_name = "open",
3144 .ml_meth = (PyCFunction)pyrf_evlist__open,
3145 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3146 .ml_doc = PyDoc_STR("open the file descriptors.")
3147 },
3148 {
3149 .ml_name = "close",
3150 .ml_meth = (PyCFunction)pyrf_evlist__close,
3151 .ml_flags = METH_NOARGS,
3152 .ml_doc = PyDoc_STR("close the file descriptors.")
3153 },
3154 {
3155 .ml_name = "poll",
3156 .ml_meth = (PyCFunction)pyrf_evlist__poll,
3157 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3158 .ml_doc = PyDoc_STR("poll the file descriptor table.")
3159 },
3160 {
3161 .ml_name = "get_pollfd",
3162 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd,
3163 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3164 .ml_doc = PyDoc_STR("get the poll file descriptor table.")
3165 },
3166 {
3167 .ml_name = "add",
3168 .ml_meth = (PyCFunction)pyrf_evlist__add,
3169 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3170 .ml_doc = PyDoc_STR("adds an event selector to the list.")
3171 },
3172 {
3173 .ml_name = "read_on_cpu",
3174 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu,
3175 .ml_flags = METH_VARARGS | METH_KEYWORDS,
3176 .ml_doc = PyDoc_STR("reads an event.")
3177 },
3178 {
3179 .ml_name = "config",
3180 .ml_meth = (PyCFunction)pyrf_evlist__config,
3181 .ml_flags = METH_NOARGS,
3182 .ml_doc = PyDoc_STR("Apply default record options to the evlist.")
3183 },
3184 {
3185 .ml_name = "disable",
3186 .ml_meth = (PyCFunction)pyrf_evlist__disable,
3187 .ml_flags = METH_NOARGS,
3188 .ml_doc = PyDoc_STR("Disable the evsels in the evlist.")
3189 },
3190 {
3191 .ml_name = "enable",
3192 .ml_meth = (PyCFunction)pyrf_evlist__enable,
3193 .ml_flags = METH_NOARGS,
3194 .ml_doc = PyDoc_STR("Enable the evsels in the evlist.")
3195 },
3196 { .ml_name = NULL, }
3197};
3198
3199static Py_ssize_t pyrf_evlist__length(PyObject *obj)
3200{
3201 struct pyrf_evlist *pevlist = (void *)obj;
3202
3203 if (!pevlist->evlist)
3204 return 0;
3205
3206 return evlist__nr_entries(pevlist->evlist);
3207}
3208
3209static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
3210{
3211 struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
3212
3213 if (!pevsel)
3214 return NULL;
3215
3216 pevsel->evsel = evsel__get(evsel);
3217 return (PyObject *)pevsel;
3218}
3219
3220static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
3221{
3222 struct pyrf_evlist *pevlist = (void *)obj;
3223 struct evsel *pos;
3224
3225 if (!pevlist->evlist || i >= evlist__nr_entries(pevlist->evlist)) {
3226 PyErr_SetString(PyExc_IndexError, "Index out of range");
3227 return NULL;
3228 }
3229
3230 evlist__for_each_entry(pevlist->evlist, pos) {
3231 if (i-- == 0)
3232 break;
3233 }
3234 return pyrf_evsel__from_evsel(pos);
3235}
3236
3237static PyObject *pyrf_evlist__str(PyObject *self)
3238{
3239 struct pyrf_evlist *pevlist = (void *)self;
3240 struct evsel *pos;
3241 struct strbuf sb = STRBUF_INIT;
3242 bool first = true;
3243 PyObject *result;
3244
3245 if (!pevlist->evlist)
3246 return PyUnicode_FromString("evlist(uninitialized)");
3247
3248 strbuf_addstr(&sb, "evlist([");
3249 evlist__for_each_entry(pevlist->evlist, pos) {
3250 if (!first)
3251 strbuf_addch(&sb, ',');
3252 strbuf_addstr(&sb, evsel__name(pos));
3253 first = false;
3254 }
3255 strbuf_addstr(&sb, "])");
3256 result = PyUnicode_FromString(sb.buf);
3257 strbuf_release(&sb);
3258 return result;
3259}
3260
3261static PySequenceMethods pyrf_evlist__sequence_methods = {
3262 .sq_length = pyrf_evlist__length,
3263 .sq_item = pyrf_evlist__item,
3264};
3265
3266static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
3267
3268static PyObject *pyrf_evlist__getattro(struct pyrf_evlist *pevlist, PyObject *attr_name)
3269{
3270 if (!pevlist->evlist) {
3271 PyErr_SetString(PyExc_ValueError, "evlist not initialized");
3272 return NULL;
3273 }
3274 return PyObject_GenericGetAttr((PyObject *) pevlist, attr_name);
3275}
3276
3277static int pyrf_evlist__setattro(struct pyrf_evlist *pevlist, PyObject *attr_name, PyObject *value)
3278{
3279 if (!pevlist->evlist) {
3280 PyErr_SetString(PyExc_ValueError, "evlist not initialized");
3281 return -1;
3282 }
3283 return PyObject_GenericSetAttr((PyObject *) pevlist, attr_name, value);
3284}
3285
3286static PyTypeObject pyrf_evlist__type = {
3287 PyVarObject_HEAD_INIT(NULL, 0)
3288 .tp_name = "perf.evlist",
3289 .tp_basicsize = sizeof(struct pyrf_evlist),
3290 .tp_dealloc = (destructor)pyrf_evlist__delete,
3291 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3292 .tp_as_sequence = &pyrf_evlist__sequence_methods,
3293 .tp_doc = pyrf_evlist__doc,
3294 .tp_methods = pyrf_evlist__methods,
3295 .tp_init = (initproc)pyrf_evlist__init,
3296 .tp_repr = pyrf_evlist__str,
3297 .tp_str = pyrf_evlist__str,
3298 .tp_getattro = (getattrofunc) pyrf_evlist__getattro,
3299 .tp_setattro = (setattrofunc) pyrf_evlist__setattro,
3300};
3301
3302static PyObject *pyrf_evlist__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3303{
3304 struct pyrf_evlist *pevlist;
3305
3306 pevlist = (struct pyrf_evlist *)PyType_GenericNew(type, args, kwargs);
3307 if (pevlist)
3308 pevlist->evlist = NULL;
3309 return (PyObject *)pevlist;
3310}
3311
3312static int pyrf_evlist__setup_types(void)
3313{
3314 pyrf_evlist__type.tp_new = pyrf_evlist__new;
3315 return PyType_Ready(&pyrf_evlist__type);
3316}
3317
3318#define PERF_CONST(name) { #name, PERF_##name }
3319
3320struct perf_constant {
3321 const char *name;
3322 int value;
3323};
3324
3325static const struct perf_constant perf__constants[] = {
3326 PERF_CONST(TYPE_HARDWARE),
3327 PERF_CONST(TYPE_SOFTWARE),
3328 PERF_CONST(TYPE_TRACEPOINT),
3329 PERF_CONST(TYPE_HW_CACHE),
3330 PERF_CONST(TYPE_RAW),
3331 PERF_CONST(TYPE_BREAKPOINT),
3332
3333 PERF_CONST(COUNT_HW_CPU_CYCLES),
3334 PERF_CONST(COUNT_HW_REF_CPU_CYCLES),
3335 PERF_CONST(COUNT_HW_INSTRUCTIONS),
3336 PERF_CONST(COUNT_HW_CACHE_REFERENCES),
3337 PERF_CONST(COUNT_HW_CACHE_MISSES),
3338 PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS),
3339 PERF_CONST(COUNT_HW_BRANCH_MISSES),
3340 PERF_CONST(COUNT_HW_BUS_CYCLES),
3341 PERF_CONST(COUNT_HW_CACHE_L1D),
3342 PERF_CONST(COUNT_HW_CACHE_L1I),
3343 PERF_CONST(COUNT_HW_CACHE_LL),
3344 PERF_CONST(COUNT_HW_CACHE_DTLB),
3345 PERF_CONST(COUNT_HW_CACHE_ITLB),
3346 PERF_CONST(COUNT_HW_CACHE_BPU),
3347 PERF_CONST(COUNT_HW_CACHE_OP_READ),
3348 PERF_CONST(COUNT_HW_CACHE_OP_WRITE),
3349 PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH),
3350 PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS),
3351 PERF_CONST(COUNT_HW_CACHE_RESULT_MISS),
3352
3353 PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND),
3354 PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND),
3355
3356 PERF_CONST(COUNT_SW_CPU_CLOCK),
3357 PERF_CONST(COUNT_SW_TASK_CLOCK),
3358 PERF_CONST(COUNT_SW_PAGE_FAULTS),
3359 PERF_CONST(COUNT_SW_CONTEXT_SWITCHES),
3360 PERF_CONST(COUNT_SW_CPU_MIGRATIONS),
3361 PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN),
3362 PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ),
3363 PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS),
3364 PERF_CONST(COUNT_SW_EMULATION_FAULTS),
3365 PERF_CONST(COUNT_SW_DUMMY),
3366
3367 PERF_CONST(SAMPLE_IP),
3368 PERF_CONST(SAMPLE_TID),
3369 PERF_CONST(SAMPLE_TIME),
3370 PERF_CONST(SAMPLE_ADDR),
3371 PERF_CONST(SAMPLE_READ),
3372 PERF_CONST(SAMPLE_CALLCHAIN),
3373 PERF_CONST(SAMPLE_ID),
3374 PERF_CONST(SAMPLE_CPU),
3375 PERF_CONST(SAMPLE_PERIOD),
3376 PERF_CONST(SAMPLE_STREAM_ID),
3377 PERF_CONST(SAMPLE_RAW),
3378
3379 PERF_CONST(FORMAT_TOTAL_TIME_ENABLED),
3380 PERF_CONST(FORMAT_TOTAL_TIME_RUNNING),
3381 PERF_CONST(FORMAT_ID),
3382 PERF_CONST(FORMAT_GROUP),
3383
3384 PERF_CONST(RECORD_MMAP),
3385 PERF_CONST(RECORD_LOST),
3386 PERF_CONST(RECORD_COMM),
3387 PERF_CONST(RECORD_EXIT),
3388 PERF_CONST(RECORD_THROTTLE),
3389 PERF_CONST(RECORD_UNTHROTTLE),
3390 PERF_CONST(RECORD_FORK),
3391 PERF_CONST(RECORD_READ),
3392 PERF_CONST(RECORD_SAMPLE),
3393 PERF_CONST(RECORD_MMAP2),
3394 PERF_CONST(RECORD_AUX),
3395 PERF_CONST(RECORD_ITRACE_START),
3396 PERF_CONST(RECORD_LOST_SAMPLES),
3397 PERF_CONST(RECORD_SWITCH),
3398 PERF_CONST(RECORD_SWITCH_CPU_WIDE),
3399 PERF_CONST(RECORD_STAT),
3400 PERF_CONST(RECORD_STAT_ROUND),
3401
3402 PERF_CONST(RECORD_MISC_SWITCH_OUT),
3403 { .name = NULL, },
3404};
3405
3406static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
3407 PyObject *args, PyObject *kwargs)
3408{
3409 static char *kwlist[] = { "sys", "name", NULL };
3410 char *sys = NULL;
3411 char *name = NULL;
3412
3413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist,
3414 &sys, &name))
3415 return NULL;
3416
3417 return PyLong_FromLong(tp_pmu__id(sys, name));
3418}
3419
3420static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
3421{
3422 struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
3423
3424 if (!pevlist)
3425 return NULL;
3426
3427 pevlist->evlist = evlist__get(evlist);
3428 return (PyObject *)pevlist;
3429}
3430
3431static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
3432{
3433 const char *input;
3434 struct evlist *evlist = evlist__new();
3435 struct parse_events_error err;
3436 PyObject *result;
3437 PyObject *pcpus = NULL, *pthreads = NULL;
3438 struct perf_cpu_map *cpus;
3439 struct perf_thread_map *threads;
3440
3441 if (!evlist)
3442 return PyErr_NoMemory();
3443
3444 if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) {
3445 evlist__put(evlist);
3446 return NULL;
3447 }
3448
3449 if (pthreads && pthreads != Py_None &&
3450 !PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) {
3451 PyErr_SetString(PyExc_TypeError, "threads must be a perf.thread_map or None");
3452 evlist__put(evlist);
3453 return NULL;
3454 }
3455
3456 if (pcpus && pcpus != Py_None &&
3457 !PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) {
3458 PyErr_SetString(PyExc_TypeError, "cpus must be a perf.cpu_map or None");
3459 evlist__put(evlist);
3460 return NULL;
3461 }
3462
3463 threads = (pthreads && pthreads != Py_None) ?
3464 ((struct pyrf_thread_map *)pthreads)->threads : NULL;
3465 cpus = (pcpus && pcpus != Py_None) ?
3466 ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
3467
3468 parse_events_error__init(&err);
3469 perf_evlist__set_maps(evlist__core(evlist), cpus, threads);
3470 if (parse_events(evlist, input, &err)) {
3471 parse_events_error__print(&err, input);
3472 PyErr_SetFromErrno(PyExc_OSError);
3473 evlist__put(evlist);
3474 return NULL;
3475 }
3476 result = pyrf_evlist__from_evlist(evlist);
3477 evlist__put(evlist);
3478 return result;
3479}
3480
3481static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
3482{
3483 const char *input, *pmu = NULL;
3484 struct evlist *evlist = evlist__new();
3485 PyObject *result;
3486 PyObject *pcpus = NULL, *pthreads = NULL;
3487 struct perf_cpu_map *cpus;
3488 struct perf_thread_map *threads;
3489 int ret;
3490
3491 if (!evlist)
3492 return PyErr_NoMemory();
3493
3494 if (!PyArg_ParseTuple(args, "s|sOO", &input, &pmu, &pcpus, &pthreads)) {
3495 evlist__put(evlist);
3496 return NULL;
3497 }
3498
3499 if (pthreads && pthreads != Py_None &&
3500 !PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) {
3501 PyErr_SetString(PyExc_TypeError, "threads must be a perf.thread_map or None");
3502 evlist__put(evlist);
3503 return NULL;
3504 }
3505
3506 if (pcpus && pcpus != Py_None &&
3507 !PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) {
3508 PyErr_SetString(PyExc_TypeError, "cpus must be a perf.cpu_map or None");
3509 evlist__put(evlist);
3510 return NULL;
3511 }
3512
3513 threads = (pthreads && pthreads != Py_None) ?
3514 ((struct pyrf_thread_map *)pthreads)->threads : NULL;
3515 cpus = (pcpus && pcpus != Py_None) ?
3516 ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
3517
3518 perf_evlist__set_maps(evlist__core(evlist), cpus, threads);
3519 ret = metricgroup__parse_groups(evlist, pmu ?: "all",
3520 /*cputype_filter=*/false, input,
3521 /*metric_no_group=*/ false,
3522 /*metric_no_merge=*/ false,
3523 /*metric_no_threshold=*/ true,
3524 /*user_requested_cpu_list=*/ NULL,
3525 /*system_wide=*/true,
3526 /*hardware_aware_grouping=*/ false);
3527 if (ret) {
3528 evlist__put(evlist);
3529 errno = -ret;
3530 PyErr_SetFromErrno(PyExc_OSError);
3531 return NULL;
3532 }
3533 result = pyrf_evlist__from_evlist(evlist);
3534 evlist__put(evlist);
3535 return result;
3536}
3537
3538static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm)
3539{
3540 PyObject *groups = PyList_New(/*len=*/0);
3541 const char *mg = pm->metric_group;
3542
3543 if (!groups)
3544 return NULL;
3545
3546 while (mg) {
3547 PyObject *val = NULL;
3548 const char *sep = strchr(mg, ';');
3549 size_t len = sep ? (size_t)(sep - mg) : strlen(mg);
3550
3551 if (len > 0) {
3552 val = PyUnicode_FromStringAndSize(mg, len);
3553 if (val)
3554 PyList_Append(groups, val);
3555
3556 Py_XDECREF(val);
3557 }
3558 mg = sep ? sep + 1 : NULL;
3559 }
3560 return groups;
3561}
3562
3563static int pyrf__metrics_cb(const struct pmu_metric *pm,
3564 const struct pmu_metrics_table *table __maybe_unused,
3565 void *vdata)
3566{
3567 PyObject *py_list = vdata;
3568 PyObject *dict = PyDict_New();
3569 PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL;
3570 PyObject *value = key ? pyrf__metrics_groups(pm) : NULL;
3571
3572 if (!value || PyDict_SetItem(dict, key, value) != 0) {
3573 Py_XDECREF(key);
3574 Py_XDECREF(value);
3575 Py_XDECREF(dict);
3576 return -ENOMEM;
3577 }
3578 Py_DECREF(key);
3579 Py_DECREF(value);
3580
3581 if (!add_to_dict(dict, "MetricName", pm->metric_name) ||
3582 !add_to_dict(dict, "PMU", pm->pmu) ||
3583 !add_to_dict(dict, "MetricExpr", pm->metric_expr) ||
3584 !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) ||
3585 !add_to_dict(dict, "ScaleUnit", pm->unit) ||
3586 !add_to_dict(dict, "Compat", pm->compat) ||
3587 !add_to_dict(dict, "BriefDescription", pm->desc) ||
3588 !add_to_dict(dict, "PublicDescription", pm->long_desc) ||
3589 PyList_Append(py_list, dict) != 0) {
3590 Py_DECREF(dict);
3591 return -ENOMEM;
3592 }
3593 Py_DECREF(dict);
3594 return 0;
3595}
3596
3597static PyObject *pyrf__metrics(PyObject *self, PyObject *args)
3598{
3599 const struct pmu_metrics_table *table = pmu_metrics_table__find();
3600 PyObject *list = PyList_New(/*len=*/0);
3601 int ret;
3602
3603 if (!list)
3604 return NULL;
3605
3606 ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list);
3607 if (!ret)
3608 ret = pmu_for_each_sys_metric(pyrf__metrics_cb, list);
3609
3610 if (ret) {
3611 Py_DECREF(list);
3612 errno = -ret;
3613 PyErr_SetFromErrno(PyExc_OSError);
3614 return NULL;
3615 }
3616 return list;
3617}
3618
3619struct pyrf_data {
3620 PyObject_HEAD
3621
3622 struct perf_data data;
3623};
3624
3625static int pyrf_data__init(struct pyrf_data *pdata, PyObject *args, PyObject *kwargs)
3626{
3627 static char *kwlist[] = { "path", "fd", NULL };
3628 char *path = NULL;
3629 int fd = -1;
3630
3631 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &path, &fd))
3632 return -1;
3633
3634 if (pdata->data.open)
3635 perf_data__close(&pdata->data);
3636 free((char *)pdata->data.path);
3637 memset(&pdata->data, 0, sizeof(pdata->data));
3638
3639 if (fd != -1) {
3640 struct stat st;
3641
3642 if (fstat(fd, &st) < 0 || !S_ISFIFO(st.st_mode)) {
3643 PyErr_SetString(PyExc_ValueError,
3644 "fd argument is only supported for pipes");
3645 return -1;
3646 }
3647 if (!path)
3648 path = "-";
3649 else if (strcmp(path, "-") != 0) {
3650 PyErr_SetString(PyExc_ValueError,
3651 "path must be '-' when fd is provided");
3652 return -1;
3653 }
3654 fd = dup(fd);
3655 if (fd < 0) {
3656 PyErr_SetFromErrno(PyExc_OSError);
3657 return -1;
3658 }
3659 } else if (path && strcmp(path, "-") == 0) {
3660 fd = dup(0);
3661 if (fd < 0) {
3662 PyErr_SetFromErrno(PyExc_OSError);
3663 return -1;
3664 }
3665 }
3666
3667 if (!path)
3668 path = "perf.data";
3669
3670 pdata->data.path = strdup(path);
3671 if (!pdata->data.path) {
3672 if (fd != -1)
3673 close(fd);
3674 PyErr_NoMemory();
3675 return -1;
3676 }
3677
3678 pdata->data.mode = PERF_DATA_MODE_READ;
3679 pdata->data.file.fd = fd;
3680 if (perf_data__open(&pdata->data) < 0) {
3681 PyErr_Format(PyExc_IOError, "Failed to open perf data: %s",
3682 pdata->data.path ? pdata->data.path : "perf.data");
3683 return -1;
3684 }
3685 return 0;
3686}
3687
3688static void pyrf_data__delete(struct pyrf_data *pdata)
3689{
3690 perf_data__close(&pdata->data);
3691 free((char *)pdata->data.path);
3692 Py_TYPE(pdata)->tp_free((PyObject *)pdata);
3693}
3694
3695static PyObject *pyrf_data__str(PyObject *self)
3696{
3697 const struct pyrf_data *pdata = (const struct pyrf_data *)self;
3698
3699 if (!pdata->data.path)
3700 return PyUnicode_FromString("[uninitialized]");
3701 return PyUnicode_FromString(pdata->data.path);
3702}
3703
3704static PyObject *pyrf_data__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3705{
3706 struct pyrf_data *pdata;
3707
3708 pdata = (struct pyrf_data *)PyType_GenericNew(type, args, kwargs);
3709 if (pdata)
3710 memset(&pdata->data, 0, sizeof(pdata->data));
3711 return (PyObject *)pdata;
3712}
3713
3714static const char pyrf_data__doc[] = PyDoc_STR("perf data file object.");
3715
3716static PyTypeObject pyrf_data__type = {
3717 PyVarObject_HEAD_INIT(NULL, 0)
3718 .tp_name = "perf.data",
3719 .tp_basicsize = sizeof(struct pyrf_data),
3720 .tp_dealloc = (destructor)pyrf_data__delete,
3721 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3722 .tp_doc = pyrf_data__doc,
3723 .tp_init = (initproc)pyrf_data__init,
3724 .tp_repr = pyrf_data__str,
3725 .tp_str = pyrf_data__str,
3726};
3727
3728static int pyrf_data__setup_types(void)
3729{
3730 pyrf_data__type.tp_new = pyrf_data__new;
3731 return PyType_Ready(&pyrf_data__type);
3732}
3733
3734struct pyrf_thread {
3735 PyObject_HEAD
3736
3737 struct thread *thread;
3738};
3739
3740static void pyrf_thread__delete(struct pyrf_thread *pthread)
3741{
3742 thread__put(pthread->thread);
3743 Py_TYPE(pthread)->tp_free((PyObject *)pthread);
3744}
3745
3746static PyObject *pyrf_thread__comm(PyObject *obj)
3747{
3748 struct pyrf_thread *pthread = (void *)obj;
3749 const char *str;
3750
3751 CHECK_INITIALIZED(pthread->thread, "perf.thread");
3752
3753 str = thread__comm_str(pthread->thread);
3754
3755 if (!str)
3756 Py_RETURN_NONE;
3757
3758 return PyUnicode_FromString(str);
3759}
3760
3761static PyMethodDef pyrf_thread__methods[] = {
3762 {
3763 .ml_name = "comm",
3764 .ml_meth = (PyCFunction)pyrf_thread__comm,
3765 .ml_flags = METH_NOARGS,
3766 .ml_doc = PyDoc_STR("Comm(and) associated with this thread.")
3767 },
3768 { .ml_name = NULL, }
3769};
3770
3771static PyObject *pyrf_thread__get_pid(struct pyrf_thread *pthread, void *closure __maybe_unused)
3772{
3773 CHECK_INITIALIZED(pthread->thread, "thread");
3774 return PyLong_FromLong(thread__pid(pthread->thread));
3775}
3776
3777static PyObject *pyrf_thread__get_tid(struct pyrf_thread *pthread, void *closure __maybe_unused)
3778{
3779 CHECK_INITIALIZED(pthread->thread, "thread");
3780 return PyLong_FromLong(thread__tid(pthread->thread));
3781}
3782
3783static PyObject *pyrf_thread__get_ppid(struct pyrf_thread *pthread, void *closure __maybe_unused)
3784{
3785 CHECK_INITIALIZED(pthread->thread, "thread");
3786 return PyLong_FromLong(thread__ppid(pthread->thread));
3787}
3788
3789static PyObject *pyrf_thread__get_cpu(struct pyrf_thread *pthread, void *closure __maybe_unused)
3790{
3791 CHECK_INITIALIZED(pthread->thread, "thread");
3792 return PyLong_FromLong(thread__cpu(pthread->thread));
3793}
3794
3795static PyGetSetDef pyrf_thread__getset[] = {
3796 { .name = "pid", .get = (getter)pyrf_thread__get_pid, .doc = "process ID" },
3797 { .name = "tid", .get = (getter)pyrf_thread__get_tid, .doc = "thread ID" },
3798 { .name = "ppid", .get = (getter)pyrf_thread__get_ppid, .doc = "parent process ID" },
3799 { .name = "cpu", .get = (getter)pyrf_thread__get_cpu, .doc = "cpu number" },
3800 { .name = NULL }
3801};
3802
3803static const char pyrf_thread__doc[] = PyDoc_STR("perf thread object.");
3804
3805static PyTypeObject pyrf_thread__type = {
3806 PyVarObject_HEAD_INIT(NULL, 0)
3807 .tp_name = "perf.thread",
3808 .tp_basicsize = sizeof(struct pyrf_thread),
3809 .tp_dealloc = (destructor)pyrf_thread__delete,
3810 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3811 .tp_methods = pyrf_thread__methods,
3812 .tp_getset = pyrf_thread__getset,
3813 .tp_doc = pyrf_thread__doc,
3814};
3815
3816static int pyrf_thread__setup_types(void)
3817{
3818 return PyType_Ready(&pyrf_thread__type);
3819}
3820
3821static PyObject *pyrf_thread__from_thread(struct thread *thread)
3822{
3823 struct pyrf_thread *pthread = PyObject_New(struct pyrf_thread, &pyrf_thread__type);
3824
3825 if (!pthread)
3826 return NULL;
3827
3828 pthread->thread = thread__get(thread);
3829 return (PyObject *)pthread;
3830}
3831
3832struct pyrf_session {
3833 PyObject_HEAD
3834
3835 struct perf_session *session;
3836 struct perf_tool tool;
3837 struct pyrf_data *pdata;
3838 PyObject *sample;
3839 PyObject *stat;
3840};
3841
3842static int pyrf_session_tool__sample(const struct perf_tool *tool,
3843 union perf_event *event,
3844 struct perf_sample *sample,
3845 struct machine *machine)
3846{
3847 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool);
3848 PyObject *pyevent = pyrf_event__new(event, sample->evsel, psession->session, machine);
3849 PyObject *ret;
3850
3851 if (pyevent == NULL)
3852 return -ENOMEM;
3853
3854 ret = PyObject_CallFunction(psession->sample, "O", pyevent);
3855 if (!ret) {
3856 Py_DECREF(pyevent);
3857 return -1;
3858 }
3859 Py_DECREF(ret);
3860 Py_DECREF(pyevent);
3861 return 0;
3862}
3863
3864static int pyrf_session_tool__stat(const struct perf_tool *tool,
3865 struct perf_session *session,
3866 union perf_event *event)
3867{
3868 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool);
3869 struct evsel *evsel = evlist__id2evsel(session->evlist, event->stat.id);
3870 PyObject *pyevent = pyrf_event__new(event, /*evsel=*/NULL, psession->session,
3871 /*machine=*/NULL);
3872 const char *name = evsel ? evsel__name(evsel) : "unknown";
3873 PyObject *ret;
3874
3875 if (pyevent == NULL)
3876 return -ENOMEM;
3877
3878 ret = PyObject_CallFunction(psession->stat, "Oz", pyevent, name);
3879 if (!ret) {
3880 Py_DECREF(pyevent);
3881 return -1;
3882 }
3883 Py_DECREF(ret);
3884 Py_DECREF(pyevent);
3885 return 0;
3886}
3887
3888static int pyrf_session_tool__stat_round(const struct perf_tool *tool,
3889 struct perf_session *session __maybe_unused,
3890 union perf_event *event)
3891{
3892 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool);
3893 PyObject *pyevent = pyrf_event__new(event, /*evsel=*/NULL, psession->session,
3894 /*machine=*/NULL);
3895 PyObject *ret;
3896
3897 if (pyevent == NULL)
3898 return -ENOMEM;
3899
3900 ret = PyObject_CallFunction(psession->stat, "Oz", pyevent, NULL);
3901 if (!ret) {
3902 Py_DECREF(pyevent);
3903 return -1;
3904 }
3905 Py_DECREF(ret);
3906 Py_DECREF(pyevent);
3907 return 0;
3908}
3909
3910static PyObject *pyrf_session__find_thread(struct pyrf_session *psession, PyObject *args)
3911{
3912 struct machine *machine;
3913 struct thread *thread = NULL;
3914 PyObject *result;
3915 int pid;
3916
3917 CHECK_INITIALIZED(psession->session, "session");
3918
3919 if (!PyArg_ParseTuple(args, "i", &pid))
3920 return NULL;
3921
3922 machine = &psession->session->machines.host;
3923 thread = machine__find_thread(machine, pid, pid);
3924
3925 if (!thread) {
3926 machine = perf_session__find_machine(psession->session, pid);
3927 if (machine)
3928 thread = machine__find_thread(machine, pid, pid);
3929 }
3930
3931 if (!thread) {
3932 PyErr_Format(PyExc_TypeError, "Failed to find thread %d", pid);
3933 return NULL;
3934 }
3935 result = pyrf_thread__from_thread(thread);
3936 thread__put(thread);
3937 return result;
3938}
3939
3940static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3941{
3942 struct pyrf_data *pdata;
3943 PyObject *sample = NULL, *stat = NULL;
3944 static char *kwlist[] = { "data", "sample", "stat", NULL };
3945 struct pyrf_session *psession;
3946 struct perf_session *session;
3947
3948 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &pyrf_data__type, &pdata,
3949 &sample, &stat))
3950 return NULL;
3951
3952 psession = PyObject_New(struct pyrf_session, type);
3953 if (!psession)
3954 return NULL;
3955
3956 psession->session = NULL;
3957 psession->sample = NULL;
3958 psession->stat = NULL;
3959 psession->pdata = NULL;
3960
3961 Py_INCREF(pdata);
3962 psession->pdata = pdata;
3963
3964 perf_tool__init(&psession->tool, /*ordered_events=*/true);
3965 psession->tool.ordering_requires_timestamps = true;
3966
3967 #define ADD_TOOL(name) \
3968 do { \
3969 if (name) { \
3970 if (!PyCallable_Check(name)) { \
3971 PyErr_SetString(PyExc_TypeError, #name " must be callable"); \
3972 goto err_out; \
3973 } \
3974 psession->tool.name = pyrf_session_tool__##name; \
3975 Py_INCREF(name); \
3976 psession->name = name; \
3977 } \
3978 } while (0)
3979
3980 ADD_TOOL(sample);
3981 ADD_TOOL(stat);
3982 #undef ADD_TOOL
3983
3984 if (stat)
3985 psession->tool.stat_round = pyrf_session_tool__stat_round;
3986
3987
3988 psession->tool.comm = perf_event__process_comm;
3989 psession->tool.mmap = perf_event__process_mmap;
3990 psession->tool.mmap2 = perf_event__process_mmap2;
3991 psession->tool.namespaces = perf_event__process_namespaces;
3992 psession->tool.cgroup = perf_event__process_cgroup;
3993 psession->tool.exit = perf_event__process_exit;
3994 psession->tool.fork = perf_event__process_fork;
3995 psession->tool.ksymbol = perf_event__process_ksymbol;
3996 psession->tool.text_poke = perf_event__process_text_poke;
3997 psession->tool.build_id = perf_event__process_build_id;
3998 psession->tool.attr = perf_event__process_attr;
3999 psession->tool.feature = perf_event__process_feature;
4000
4001 session = perf_session__new(&pdata->data, &psession->tool);
4002 if (IS_ERR(session)) {
4003 PyErr_Format(PyExc_IOError, "failed to create session: %ld", PTR_ERR(session));
4004 goto err_out;
4005 }
4006 psession->session = session;
4007
4008 symbol_conf.use_callchain = true;
4009 symbol_conf.show_kernel_path = true;
4010 symbol_conf.inline_name = false;
4011 if (symbol__init(perf_session__env(session)) < 0) {
4012 PyErr_SetString(PyExc_OSError, "perf: symbol__init failed");
4013 goto err_out;
4014 }
4015
4016
4017
4018 return (PyObject *)psession;
4019err_out:
4020 Py_DECREF(psession);
4021 return NULL;
4022}
4023
4024static void pyrf_session__delete(struct pyrf_session *psession)
4025{
4026 perf_session__delete(psession->session);
4027 Py_XDECREF(psession->pdata);
4028 Py_XDECREF(psession->sample);
4029 Py_XDECREF(psession->stat);
4030 Py_TYPE(psession)->tp_free((PyObject *)psession);
4031}
4032
4033static PyObject *pyrf_session__find_thread_events(struct pyrf_session *psession)
4034{
4035 int err;
4036
4037 CHECK_INITIALIZED(psession->session, "session");
4038
4039 err = perf_session__process_events(psession->session);
4040
4041 if (PyErr_Occurred())
4042 return NULL;
4043
4044 if (err < 0) {
4045 PyErr_Format(PyExc_OSError, "Process events failed: %d", err);
4046 return NULL;
4047 }
4048
4049 Py_RETURN_NONE;
4050}
4051
4052static PyMethodDef pyrf_session__methods[] = {
4053 {
4054 .ml_name = "process_events",
4055 .ml_meth = (PyCFunction)pyrf_session__find_thread_events,
4056 .ml_flags = METH_NOARGS,
4057 .ml_doc = PyDoc_STR("Iterate and process events.")
4058 },
4059 {
4060 .ml_name = "find_thread",
4061 .ml_meth = (PyCFunction)pyrf_session__find_thread,
4062 .ml_flags = METH_VARARGS,
4063 .ml_doc = PyDoc_STR("Returns the thread associated with a pid.")
4064 },
4065 { .ml_name = NULL, }
4066};
4067
4068static const char pyrf_session__doc[] = PyDoc_STR("perf session object.");
4069
4070static PyObject *pyrf_session__getattro(struct pyrf_session *psession, PyObject *attr_name)
4071{
4072 if (!psession->session) {
4073 PyErr_SetString(PyExc_ValueError, "session not initialized");
4074 return NULL;
4075 }
4076 return PyObject_GenericGetAttr((PyObject *) psession, attr_name);
4077}
4078
4079static int pyrf_session__setattro(struct pyrf_session *psession, PyObject *attr_name,
4080 PyObject *value)
4081{
4082 if (!psession->session) {
4083 PyErr_SetString(PyExc_ValueError, "session not initialized");
4084 return -1;
4085 }
4086 return PyObject_GenericSetAttr((PyObject *) psession, attr_name, value);
4087}
4088
4089static PyTypeObject pyrf_session__type = {
4090 PyVarObject_HEAD_INIT(NULL, 0)
4091 .tp_name = "perf.session",
4092 .tp_basicsize = sizeof(struct pyrf_session),
4093 .tp_dealloc = (destructor)pyrf_session__delete,
4094 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
4095 .tp_methods = pyrf_session__methods,
4096 .tp_doc = pyrf_session__doc,
4097 .tp_new = pyrf_session__new,
4098 .tp_getattro = (getattrofunc) pyrf_session__getattro,
4099 .tp_setattro = (setattrofunc) pyrf_session__setattro,
4100};
4101
4102static int pyrf_session__setup_types(void)
4103{
4104 return PyType_Ready(&pyrf_session__type);
4105}
4106
4107static PyObject *pyrf__syscall_name(PyObject *self, PyObject *args, PyObject *kwargs)
4108{
4109 const char *name;
4110 int id;
4111 int elf_machine = EM_HOST;
4112 static char *kwlist[] = { "id", "elf_machine", NULL };
4113
4114 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|$i", kwlist, &id, &elf_machine))
4115 return NULL;
4116
4117 name = syscalltbl__name(elf_machine, id);
4118 if (!name)
4119 Py_RETURN_NONE;
4120 return PyUnicode_FromString(name);
4121}
4122
4123static PyObject *pyrf__syscall_id(PyObject *self, PyObject *args, PyObject *kwargs)
4124{
4125 const char *name;
4126 int id;
4127 int elf_machine = EM_HOST;
4128 static char *kwlist[] = { "name", "elf_machine", NULL };
4129
4130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|$i", kwlist, &name, &elf_machine))
4131 return NULL;
4132
4133 id = syscalltbl__id(elf_machine, name);
4134 if (id < 0) {
4135 PyErr_Format(PyExc_ValueError, "Failed to find syscall %s", name);
4136 return NULL;
4137 }
4138 return PyLong_FromLong(id);
4139}
4140
4141static PyObject *pyrf__config_get(PyObject *self, PyObject *args)
4142{
4143 const char *config_name, *val;
4144
4145 if (!PyArg_ParseTuple(args, "s", &config_name))
4146 return NULL;
4147
4148 val = perf_config_get(config_name);
4149 if (!val)
4150 Py_RETURN_NONE;
4151 return PyUnicode_FromString(val);
4152}
4153
4154static PyMethodDef perf__methods[] = {
4155 {
4156 .ml_name = "config_get",
4157 .ml_meth = (PyCFunction) pyrf__config_get,
4158 .ml_flags = METH_VARARGS,
4159 .ml_doc = PyDoc_STR("Get a perf config value.")
4160 },
4161 {
4162 .ml_name = "metrics",
4163 .ml_meth = (PyCFunction) pyrf__metrics,
4164 .ml_flags = METH_NOARGS,
4165 .ml_doc = PyDoc_STR(
4166 "Returns a list of metrics represented as string values in dictionaries.")
4167 },
4168 {
4169 .ml_name = "tracepoint",
4170 .ml_meth = (PyCFunction) pyrf__tracepoint,
4171 .ml_flags = METH_VARARGS | METH_KEYWORDS,
4172 .ml_doc = PyDoc_STR("Get tracepoint config.")
4173 },
4174 {
4175 .ml_name = "parse_events",
4176 .ml_meth = (PyCFunction) pyrf__parse_events,
4177 .ml_flags = METH_VARARGS,
4178 .ml_doc = PyDoc_STR("Parse a string of events and return an evlist.")
4179 },
4180 {
4181 .ml_name = "parse_metrics",
4182 .ml_meth = (PyCFunction) pyrf__parse_metrics,
4183 .ml_flags = METH_VARARGS,
4184 .ml_doc = PyDoc_STR(
4185 "Parse a string of metrics or metric groups and return an evlist.")
4186 },
4187 {
4188 .ml_name = "pmus",
4189 .ml_meth = (PyCFunction) pyrf__pmus,
4190 .ml_flags = METH_NOARGS,
4191 .ml_doc = PyDoc_STR("Returns a sequence of pmus.")
4192 },
4193 {
4194 .ml_name = "syscall_name",
4195 .ml_meth = (PyCFunction) pyrf__syscall_name,
4196 .ml_flags = METH_VARARGS | METH_KEYWORDS,
4197 .ml_doc = PyDoc_STR("Turns a syscall number to a string.")
4198 },
4199 {
4200 .ml_name = "syscall_id",
4201 .ml_meth = (PyCFunction) pyrf__syscall_id,
4202 .ml_flags = METH_VARARGS | METH_KEYWORDS,
4203 .ml_doc = PyDoc_STR("Turns a syscall name to a number.")
4204 },
4205 { .ml_name = NULL, }
4206};
4207
4208PyMODINIT_FUNC PyInit_perf(void)
4209{
4210 PyObject *obj;
4211 int i;
4212 PyObject *dict;
4213 static struct PyModuleDef moduledef = {
4214 PyModuleDef_HEAD_INIT,
4215 "perf", /* m_name */
4216 "", /* m_doc */
4217 -1, /* m_size */
4218 perf__methods, /* m_methods */
4219 NULL, /* m_reload */
4220 NULL, /* m_traverse */
4221 NULL, /* m_clear */
4222 NULL, /* m_free */
4223 };
4224 PyObject *module = PyModule_Create(&moduledef);
4225
4226 if (module == NULL)
4227 return NULL;
4228
4229 if (pyrf_event__setup_types() < 0 ||
4230 pyrf_evlist__setup_types() < 0 ||
4231 pyrf_evsel__setup_types() < 0 ||
4232 pyrf_thread_map__setup_types() < 0 ||
4233 pyrf_cpu_map__setup_types() < 0 ||
4234 pyrf_pmu_iterator__setup_types() < 0 ||
4235 pyrf_pmu__setup_types() < 0 ||
4236 pyrf_counts_values__setup_types() < 0 ||
4237 pyrf_data__setup_types() < 0 ||
4238 pyrf_session__setup_types() < 0 ||
4239 pyrf_thread__setup_types() < 0) {
4240 Py_DECREF(module);
4241 return NULL;
4242 }
4243
4244 /* The page_size is placed in util object. */
4245 page_size = sysconf(_SC_PAGE_SIZE);
4246
4247 Py_INCREF(&pyrf_evlist__type);
4248 PyModule_AddObject(module, "evlist", (PyObject *)&pyrf_evlist__type);
4249
4250 Py_INCREF(&pyrf_evsel__type);
4251 PyModule_AddObject(module, "evsel", (PyObject *)&pyrf_evsel__type);
4252
4253 Py_INCREF(&pyrf_thread__type);
4254 PyModule_AddObject(module, "thread", (PyObject *)&pyrf_thread__type);
4255
4256 Py_INCREF(&pyrf_callchain__type);
4257 PyModule_AddObject(module, "callchain", (PyObject *)&pyrf_callchain__type);
4258
4259 Py_INCREF(&pyrf_callchain_node__type);
4260 PyModule_AddObject(module, "callchain_node", (PyObject *)&pyrf_callchain_node__type);
4261
4262 Py_INCREF(&pyrf_mmap_event__type);
4263 PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type);
4264
4265 Py_INCREF(&pyrf_mmap2_event__type);
4266 PyModule_AddObject(module, "mmap2_event", (PyObject *)&pyrf_mmap2_event__type);
4267
4268 Py_INCREF(&pyrf_lost_event__type);
4269 PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type);
4270
4271 Py_INCREF(&pyrf_comm_event__type);
4272 PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type);
4273
4274 Py_INCREF(&pyrf_task_event__type);
4275 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
4276
4277 Py_INCREF(&pyrf_throttle_event__type);
4278 PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type);
4279
4280 Py_INCREF(&pyrf_task_event__type);
4281 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
4282
4283 Py_INCREF(&pyrf_read_event__type);
4284 PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type);
4285
4286 Py_INCREF(&pyrf_sample_event__type);
4287 PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type);
4288
4289 Py_INCREF(&pyrf_context_switch_event__type);
4290 PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type);
4291
4292 Py_INCREF(&pyrf_stat_event__type);
4293 PyModule_AddObject(module, "stat_event", (PyObject *)&pyrf_stat_event__type);
4294
4295 Py_INCREF(&pyrf_stat_round_event__type);
4296 PyModule_AddObject(module, "stat_round_event", (PyObject *)&pyrf_stat_round_event__type);
4297
4298 Py_INCREF(&pyrf_thread_map__type);
4299 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
4300
4301 Py_INCREF(&pyrf_cpu_map__type);
4302 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
4303
4304 Py_INCREF(&pyrf_counts_values__type);
4305 PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type);
4306
4307 Py_INCREF(&pyrf_data__type);
4308 PyModule_AddObject(module, "data", (PyObject *)&pyrf_data__type);
4309
4310 Py_INCREF(&pyrf_session__type);
4311 PyModule_AddObject(module, "session", (PyObject *)&pyrf_session__type);
4312
4313 Py_INCREF(&pyrf_branch_entry__type);
4314 if (PyModule_AddObject(module, "branch_entry", (PyObject *)&pyrf_branch_entry__type) < 0) {
4315 Py_DECREF(&pyrf_branch_entry__type);
4316 goto error;
4317 }
4318
4319 Py_INCREF(&pyrf_branch_stack__type);
4320 if (PyModule_AddObject(module, "branch_stack", (PyObject *)&pyrf_branch_stack__type) < 0) {
4321 Py_DECREF(&pyrf_branch_stack__type);
4322 goto error;
4323 }
4324
4325 dict = PyModule_GetDict(module);
4326 if (dict == NULL)
4327 goto error;
4328
4329 for (i = 0; perf__constants[i].name != NULL; i++) {
4330 obj = PyLong_FromLong(perf__constants[i].value);
4331 if (obj == NULL)
4332 goto error;
4333 PyDict_SetItemString(dict, perf__constants[i].name, obj);
4334 Py_DECREF(obj);
4335 }
4336
4337error:
4338 if (PyErr_Occurred()) {
4339 Py_XDECREF(module);
4340 return NULL;
4341 }
4342 return module;
4343}