xref: /openbmc/linux/tools/perf/util/python.c (revision 8fdff1dc)
1 #include <Python.h>
2 #include <structmember.h>
3 #include <inttypes.h>
4 #include <poll.h>
5 #include "evlist.h"
6 #include "evsel.h"
7 #include "event.h"
8 #include "cpumap.h"
9 #include "thread_map.h"
10 
11 /* Define PyVarObject_HEAD_INIT for python 2.5 */
12 #ifndef PyVarObject_HEAD_INIT
13 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
14 #endif
15 
16 struct throttle_event {
17 	struct perf_event_header header;
18 	u64			 time;
19 	u64			 id;
20 	u64			 stream_id;
21 };
22 
23 PyMODINIT_FUNC initperf(void);
24 
25 #define member_def(type, member, ptype, help) \
26 	{ #member, ptype, \
27 	  offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
28 	  0, help }
29 
30 #define sample_member_def(name, member, ptype, help) \
31 	{ #name, ptype, \
32 	  offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
33 	  0, help }
34 
35 struct pyrf_event {
36 	PyObject_HEAD
37 	struct perf_sample sample;
38 	union perf_event   event;
39 };
40 
41 #define sample_members \
42 	sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"),			 \
43 	sample_member_def(sample_pid, pid, T_INT, "event pid"),			 \
44 	sample_member_def(sample_tid, tid, T_INT, "event tid"),			 \
45 	sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),		 \
46 	sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),		 \
47 	sample_member_def(sample_id, id, T_ULONGLONG, "event id"),			 \
48 	sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
49 	sample_member_def(sample_period, period, T_ULONGLONG, "event period"),		 \
50 	sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
51 
52 static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
53 
54 static PyMemberDef pyrf_mmap_event__members[] = {
55 	sample_members
56 	member_def(perf_event_header, type, T_UINT, "event type"),
57 	member_def(mmap_event, pid, T_UINT, "event pid"),
58 	member_def(mmap_event, tid, T_UINT, "event tid"),
59 	member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
60 	member_def(mmap_event, len, T_ULONGLONG, "map length"),
61 	member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
62 	member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
63 	{ .name = NULL, },
64 };
65 
66 static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
67 {
68 	PyObject *ret;
69 	char *s;
70 
71 	if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
72 			 "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
73 			 "filename: %s }",
74 		     pevent->event.mmap.pid, pevent->event.mmap.tid,
75 		     pevent->event.mmap.start, pevent->event.mmap.len,
76 		     pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
77 		ret = PyErr_NoMemory();
78 	} else {
79 		ret = PyString_FromString(s);
80 		free(s);
81 	}
82 	return ret;
83 }
84 
85 static PyTypeObject pyrf_mmap_event__type = {
86 	PyVarObject_HEAD_INIT(NULL, 0)
87 	.tp_name	= "perf.mmap_event",
88 	.tp_basicsize	= sizeof(struct pyrf_event),
89 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
90 	.tp_doc		= pyrf_mmap_event__doc,
91 	.tp_members	= pyrf_mmap_event__members,
92 	.tp_repr	= (reprfunc)pyrf_mmap_event__repr,
93 };
94 
95 static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
96 
97 static PyMemberDef pyrf_task_event__members[] = {
98 	sample_members
99 	member_def(perf_event_header, type, T_UINT, "event type"),
100 	member_def(fork_event, pid, T_UINT, "event pid"),
101 	member_def(fork_event, ppid, T_UINT, "event ppid"),
102 	member_def(fork_event, tid, T_UINT, "event tid"),
103 	member_def(fork_event, ptid, T_UINT, "event ptid"),
104 	member_def(fork_event, time, T_ULONGLONG, "timestamp"),
105 	{ .name = NULL, },
106 };
107 
108 static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
109 {
110 	return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
111 				   "ptid: %u, time: %" PRIu64 "}",
112 				   pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
113 				   pevent->event.fork.pid,
114 				   pevent->event.fork.ppid,
115 				   pevent->event.fork.tid,
116 				   pevent->event.fork.ptid,
117 				   pevent->event.fork.time);
118 }
119 
120 static PyTypeObject pyrf_task_event__type = {
121 	PyVarObject_HEAD_INIT(NULL, 0)
122 	.tp_name	= "perf.task_event",
123 	.tp_basicsize	= sizeof(struct pyrf_event),
124 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
125 	.tp_doc		= pyrf_task_event__doc,
126 	.tp_members	= pyrf_task_event__members,
127 	.tp_repr	= (reprfunc)pyrf_task_event__repr,
128 };
129 
130 static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
131 
132 static PyMemberDef pyrf_comm_event__members[] = {
133 	sample_members
134 	member_def(perf_event_header, type, T_UINT, "event type"),
135 	member_def(comm_event, pid, T_UINT, "event pid"),
136 	member_def(comm_event, tid, T_UINT, "event tid"),
137 	member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
138 	{ .name = NULL, },
139 };
140 
141 static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
142 {
143 	return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
144 				   pevent->event.comm.pid,
145 				   pevent->event.comm.tid,
146 				   pevent->event.comm.comm);
147 }
148 
149 static PyTypeObject pyrf_comm_event__type = {
150 	PyVarObject_HEAD_INIT(NULL, 0)
151 	.tp_name	= "perf.comm_event",
152 	.tp_basicsize	= sizeof(struct pyrf_event),
153 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
154 	.tp_doc		= pyrf_comm_event__doc,
155 	.tp_members	= pyrf_comm_event__members,
156 	.tp_repr	= (reprfunc)pyrf_comm_event__repr,
157 };
158 
159 static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
160 
161 static PyMemberDef pyrf_throttle_event__members[] = {
162 	sample_members
163 	member_def(perf_event_header, type, T_UINT, "event type"),
164 	member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
165 	member_def(throttle_event, id, T_ULONGLONG, "event id"),
166 	member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
167 	{ .name = NULL, },
168 };
169 
170 static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
171 {
172 	struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
173 
174 	return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
175 				   ", stream_id: %" PRIu64 " }",
176 				   pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
177 				   te->time, te->id, te->stream_id);
178 }
179 
180 static PyTypeObject pyrf_throttle_event__type = {
181 	PyVarObject_HEAD_INIT(NULL, 0)
182 	.tp_name	= "perf.throttle_event",
183 	.tp_basicsize	= sizeof(struct pyrf_event),
184 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
185 	.tp_doc		= pyrf_throttle_event__doc,
186 	.tp_members	= pyrf_throttle_event__members,
187 	.tp_repr	= (reprfunc)pyrf_throttle_event__repr,
188 };
189 
190 static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
191 
192 static PyMemberDef pyrf_lost_event__members[] = {
193 	sample_members
194 	member_def(lost_event, id, T_ULONGLONG, "event id"),
195 	member_def(lost_event, lost, T_ULONGLONG, "number of lost events"),
196 	{ .name = NULL, },
197 };
198 
199 static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent)
200 {
201 	PyObject *ret;
202 	char *s;
203 
204 	if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", "
205 			 "lost: %#" PRIx64 " }",
206 		     pevent->event.lost.id, pevent->event.lost.lost) < 0) {
207 		ret = PyErr_NoMemory();
208 	} else {
209 		ret = PyString_FromString(s);
210 		free(s);
211 	}
212 	return ret;
213 }
214 
215 static PyTypeObject pyrf_lost_event__type = {
216 	PyVarObject_HEAD_INIT(NULL, 0)
217 	.tp_name	= "perf.lost_event",
218 	.tp_basicsize	= sizeof(struct pyrf_event),
219 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
220 	.tp_doc		= pyrf_lost_event__doc,
221 	.tp_members	= pyrf_lost_event__members,
222 	.tp_repr	= (reprfunc)pyrf_lost_event__repr,
223 };
224 
225 static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
226 
227 static PyMemberDef pyrf_read_event__members[] = {
228 	sample_members
229 	member_def(read_event, pid, T_UINT, "event pid"),
230 	member_def(read_event, tid, T_UINT, "event tid"),
231 	{ .name = NULL, },
232 };
233 
234 static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent)
235 {
236 	return PyString_FromFormat("{ type: read, pid: %u, tid: %u }",
237 				   pevent->event.read.pid,
238 				   pevent->event.read.tid);
239 	/*
240  	 * FIXME: return the array of read values,
241  	 * making this method useful ;-)
242  	 */
243 }
244 
245 static PyTypeObject pyrf_read_event__type = {
246 	PyVarObject_HEAD_INIT(NULL, 0)
247 	.tp_name	= "perf.read_event",
248 	.tp_basicsize	= sizeof(struct pyrf_event),
249 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
250 	.tp_doc		= pyrf_read_event__doc,
251 	.tp_members	= pyrf_read_event__members,
252 	.tp_repr	= (reprfunc)pyrf_read_event__repr,
253 };
254 
255 static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
256 
257 static PyMemberDef pyrf_sample_event__members[] = {
258 	sample_members
259 	member_def(perf_event_header, type, T_UINT, "event type"),
260 	{ .name = NULL, },
261 };
262 
263 static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
264 {
265 	PyObject *ret;
266 	char *s;
267 
268 	if (asprintf(&s, "{ type: sample }") < 0) {
269 		ret = PyErr_NoMemory();
270 	} else {
271 		ret = PyString_FromString(s);
272 		free(s);
273 	}
274 	return ret;
275 }
276 
277 static PyTypeObject pyrf_sample_event__type = {
278 	PyVarObject_HEAD_INIT(NULL, 0)
279 	.tp_name	= "perf.sample_event",
280 	.tp_basicsize	= sizeof(struct pyrf_event),
281 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
282 	.tp_doc		= pyrf_sample_event__doc,
283 	.tp_members	= pyrf_sample_event__members,
284 	.tp_repr	= (reprfunc)pyrf_sample_event__repr,
285 };
286 
287 static int pyrf_event__setup_types(void)
288 {
289 	int err;
290 	pyrf_mmap_event__type.tp_new =
291 	pyrf_task_event__type.tp_new =
292 	pyrf_comm_event__type.tp_new =
293 	pyrf_lost_event__type.tp_new =
294 	pyrf_read_event__type.tp_new =
295 	pyrf_sample_event__type.tp_new =
296 	pyrf_throttle_event__type.tp_new = PyType_GenericNew;
297 	err = PyType_Ready(&pyrf_mmap_event__type);
298 	if (err < 0)
299 		goto out;
300 	err = PyType_Ready(&pyrf_lost_event__type);
301 	if (err < 0)
302 		goto out;
303 	err = PyType_Ready(&pyrf_task_event__type);
304 	if (err < 0)
305 		goto out;
306 	err = PyType_Ready(&pyrf_comm_event__type);
307 	if (err < 0)
308 		goto out;
309 	err = PyType_Ready(&pyrf_throttle_event__type);
310 	if (err < 0)
311 		goto out;
312 	err = PyType_Ready(&pyrf_read_event__type);
313 	if (err < 0)
314 		goto out;
315 	err = PyType_Ready(&pyrf_sample_event__type);
316 	if (err < 0)
317 		goto out;
318 out:
319 	return err;
320 }
321 
322 static PyTypeObject *pyrf_event__type[] = {
323 	[PERF_RECORD_MMAP]	 = &pyrf_mmap_event__type,
324 	[PERF_RECORD_LOST]	 = &pyrf_lost_event__type,
325 	[PERF_RECORD_COMM]	 = &pyrf_comm_event__type,
326 	[PERF_RECORD_EXIT]	 = &pyrf_task_event__type,
327 	[PERF_RECORD_THROTTLE]	 = &pyrf_throttle_event__type,
328 	[PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
329 	[PERF_RECORD_FORK]	 = &pyrf_task_event__type,
330 	[PERF_RECORD_READ]	 = &pyrf_read_event__type,
331 	[PERF_RECORD_SAMPLE]	 = &pyrf_sample_event__type,
332 };
333 
334 static PyObject *pyrf_event__new(union perf_event *event)
335 {
336 	struct pyrf_event *pevent;
337 	PyTypeObject *ptype;
338 
339 	if (event->header.type < PERF_RECORD_MMAP ||
340 	    event->header.type > PERF_RECORD_SAMPLE)
341 		return NULL;
342 
343 	ptype = pyrf_event__type[event->header.type];
344 	pevent = PyObject_New(struct pyrf_event, ptype);
345 	if (pevent != NULL)
346 		memcpy(&pevent->event, event, event->header.size);
347 	return (PyObject *)pevent;
348 }
349 
350 struct pyrf_cpu_map {
351 	PyObject_HEAD
352 
353 	struct cpu_map *cpus;
354 };
355 
356 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
357 			      PyObject *args, PyObject *kwargs)
358 {
359 	static char *kwlist[] = { "cpustr", NULL };
360 	char *cpustr = NULL;
361 
362 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
363 					 kwlist, &cpustr))
364 		return -1;
365 
366 	pcpus->cpus = cpu_map__new(cpustr);
367 	if (pcpus->cpus == NULL)
368 		return -1;
369 	return 0;
370 }
371 
372 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
373 {
374 	cpu_map__delete(pcpus->cpus);
375 	pcpus->ob_type->tp_free((PyObject*)pcpus);
376 }
377 
378 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
379 {
380 	struct pyrf_cpu_map *pcpus = (void *)obj;
381 
382 	return pcpus->cpus->nr;
383 }
384 
385 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
386 {
387 	struct pyrf_cpu_map *pcpus = (void *)obj;
388 
389 	if (i >= pcpus->cpus->nr)
390 		return NULL;
391 
392 	return Py_BuildValue("i", pcpus->cpus->map[i]);
393 }
394 
395 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
396 	.sq_length = pyrf_cpu_map__length,
397 	.sq_item   = pyrf_cpu_map__item,
398 };
399 
400 static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
401 
402 static PyTypeObject pyrf_cpu_map__type = {
403 	PyVarObject_HEAD_INIT(NULL, 0)
404 	.tp_name	= "perf.cpu_map",
405 	.tp_basicsize	= sizeof(struct pyrf_cpu_map),
406 	.tp_dealloc	= (destructor)pyrf_cpu_map__delete,
407 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
408 	.tp_doc		= pyrf_cpu_map__doc,
409 	.tp_as_sequence	= &pyrf_cpu_map__sequence_methods,
410 	.tp_init	= (initproc)pyrf_cpu_map__init,
411 };
412 
413 static int pyrf_cpu_map__setup_types(void)
414 {
415 	pyrf_cpu_map__type.tp_new = PyType_GenericNew;
416 	return PyType_Ready(&pyrf_cpu_map__type);
417 }
418 
419 struct pyrf_thread_map {
420 	PyObject_HEAD
421 
422 	struct thread_map *threads;
423 };
424 
425 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
426 				 PyObject *args, PyObject *kwargs)
427 {
428 	static char *kwlist[] = { "pid", "tid", "uid", NULL };
429 	int pid = -1, tid = -1, uid = UINT_MAX;
430 
431 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
432 					 kwlist, &pid, &tid, &uid))
433 		return -1;
434 
435 	pthreads->threads = thread_map__new(pid, tid, uid);
436 	if (pthreads->threads == NULL)
437 		return -1;
438 	return 0;
439 }
440 
441 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
442 {
443 	thread_map__delete(pthreads->threads);
444 	pthreads->ob_type->tp_free((PyObject*)pthreads);
445 }
446 
447 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
448 {
449 	struct pyrf_thread_map *pthreads = (void *)obj;
450 
451 	return pthreads->threads->nr;
452 }
453 
454 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
455 {
456 	struct pyrf_thread_map *pthreads = (void *)obj;
457 
458 	if (i >= pthreads->threads->nr)
459 		return NULL;
460 
461 	return Py_BuildValue("i", pthreads->threads->map[i]);
462 }
463 
464 static PySequenceMethods pyrf_thread_map__sequence_methods = {
465 	.sq_length = pyrf_thread_map__length,
466 	.sq_item   = pyrf_thread_map__item,
467 };
468 
469 static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
470 
471 static PyTypeObject pyrf_thread_map__type = {
472 	PyVarObject_HEAD_INIT(NULL, 0)
473 	.tp_name	= "perf.thread_map",
474 	.tp_basicsize	= sizeof(struct pyrf_thread_map),
475 	.tp_dealloc	= (destructor)pyrf_thread_map__delete,
476 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
477 	.tp_doc		= pyrf_thread_map__doc,
478 	.tp_as_sequence	= &pyrf_thread_map__sequence_methods,
479 	.tp_init	= (initproc)pyrf_thread_map__init,
480 };
481 
482 static int pyrf_thread_map__setup_types(void)
483 {
484 	pyrf_thread_map__type.tp_new = PyType_GenericNew;
485 	return PyType_Ready(&pyrf_thread_map__type);
486 }
487 
488 struct pyrf_evsel {
489 	PyObject_HEAD
490 
491 	struct perf_evsel evsel;
492 };
493 
494 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
495 			    PyObject *args, PyObject *kwargs)
496 {
497 	struct perf_event_attr attr = {
498 		.type = PERF_TYPE_HARDWARE,
499 		.config = PERF_COUNT_HW_CPU_CYCLES,
500 		.sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
501 	};
502 	static char *kwlist[] = {
503 		"type",
504 		"config",
505 		"sample_freq",
506 		"sample_period",
507 		"sample_type",
508 		"read_format",
509 		"disabled",
510 		"inherit",
511 		"pinned",
512 		"exclusive",
513 		"exclude_user",
514 		"exclude_kernel",
515 		"exclude_hv",
516 		"exclude_idle",
517 		"mmap",
518 		"comm",
519 		"freq",
520 		"inherit_stat",
521 		"enable_on_exec",
522 		"task",
523 		"watermark",
524 		"precise_ip",
525 		"mmap_data",
526 		"sample_id_all",
527 		"wakeup_events",
528 		"bp_type",
529 		"bp_addr",
530 		"bp_len",
531 		 NULL
532 	};
533 	u64 sample_period = 0;
534 	u32 disabled = 0,
535 	    inherit = 0,
536 	    pinned = 0,
537 	    exclusive = 0,
538 	    exclude_user = 0,
539 	    exclude_kernel = 0,
540 	    exclude_hv = 0,
541 	    exclude_idle = 0,
542 	    mmap = 0,
543 	    comm = 0,
544 	    freq = 1,
545 	    inherit_stat = 0,
546 	    enable_on_exec = 0,
547 	    task = 0,
548 	    watermark = 0,
549 	    precise_ip = 0,
550 	    mmap_data = 0,
551 	    sample_id_all = 1;
552 	int idx = 0;
553 
554 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
555 					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
556 					 &attr.type, &attr.config, &attr.sample_freq,
557 					 &sample_period, &attr.sample_type,
558 					 &attr.read_format, &disabled, &inherit,
559 					 &pinned, &exclusive, &exclude_user,
560 					 &exclude_kernel, &exclude_hv, &exclude_idle,
561 					 &mmap, &comm, &freq, &inherit_stat,
562 					 &enable_on_exec, &task, &watermark,
563 					 &precise_ip, &mmap_data, &sample_id_all,
564 					 &attr.wakeup_events, &attr.bp_type,
565 					 &attr.bp_addr, &attr.bp_len, &idx))
566 		return -1;
567 
568 	/* union... */
569 	if (sample_period != 0) {
570 		if (attr.sample_freq != 0)
571 			return -1; /* FIXME: throw right exception */
572 		attr.sample_period = sample_period;
573 	}
574 
575 	/* Bitfields */
576 	attr.disabled	    = disabled;
577 	attr.inherit	    = inherit;
578 	attr.pinned	    = pinned;
579 	attr.exclusive	    = exclusive;
580 	attr.exclude_user   = exclude_user;
581 	attr.exclude_kernel = exclude_kernel;
582 	attr.exclude_hv	    = exclude_hv;
583 	attr.exclude_idle   = exclude_idle;
584 	attr.mmap	    = mmap;
585 	attr.comm	    = comm;
586 	attr.freq	    = freq;
587 	attr.inherit_stat   = inherit_stat;
588 	attr.enable_on_exec = enable_on_exec;
589 	attr.task	    = task;
590 	attr.watermark	    = watermark;
591 	attr.precise_ip	    = precise_ip;
592 	attr.mmap_data	    = mmap_data;
593 	attr.sample_id_all  = sample_id_all;
594 
595 	perf_evsel__init(&pevsel->evsel, &attr, idx);
596 	return 0;
597 }
598 
599 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
600 {
601 	perf_evsel__exit(&pevsel->evsel);
602 	pevsel->ob_type->tp_free((PyObject*)pevsel);
603 }
604 
605 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
606 				  PyObject *args, PyObject *kwargs)
607 {
608 	struct perf_evsel *evsel = &pevsel->evsel;
609 	struct cpu_map *cpus = NULL;
610 	struct thread_map *threads = NULL;
611 	PyObject *pcpus = NULL, *pthreads = NULL;
612 	int group = 0, inherit = 0;
613 	static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
614 
615 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
616 					 &pcpus, &pthreads, &group, &inherit))
617 		return NULL;
618 
619 	if (pthreads != NULL)
620 		threads = ((struct pyrf_thread_map *)pthreads)->threads;
621 
622 	if (pcpus != NULL)
623 		cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
624 
625 	evsel->attr.inherit = inherit;
626 	/*
627 	 * This will group just the fds for this single evsel, to group
628 	 * multiple events, use evlist.open().
629 	 */
630 	if (perf_evsel__open(evsel, cpus, threads) < 0) {
631 		PyErr_SetFromErrno(PyExc_OSError);
632 		return NULL;
633 	}
634 
635 	Py_INCREF(Py_None);
636 	return Py_None;
637 }
638 
639 static PyMethodDef pyrf_evsel__methods[] = {
640 	{
641 		.ml_name  = "open",
642 		.ml_meth  = (PyCFunction)pyrf_evsel__open,
643 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
644 		.ml_doc	  = PyDoc_STR("open the event selector file descriptor table.")
645 	},
646 	{ .ml_name = NULL, }
647 };
648 
649 static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
650 
651 static PyTypeObject pyrf_evsel__type = {
652 	PyVarObject_HEAD_INIT(NULL, 0)
653 	.tp_name	= "perf.evsel",
654 	.tp_basicsize	= sizeof(struct pyrf_evsel),
655 	.tp_dealloc	= (destructor)pyrf_evsel__delete,
656 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
657 	.tp_doc		= pyrf_evsel__doc,
658 	.tp_methods	= pyrf_evsel__methods,
659 	.tp_init	= (initproc)pyrf_evsel__init,
660 };
661 
662 static int pyrf_evsel__setup_types(void)
663 {
664 	pyrf_evsel__type.tp_new = PyType_GenericNew;
665 	return PyType_Ready(&pyrf_evsel__type);
666 }
667 
668 struct pyrf_evlist {
669 	PyObject_HEAD
670 
671 	struct perf_evlist evlist;
672 };
673 
674 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
675 			     PyObject *args, PyObject *kwargs __maybe_unused)
676 {
677 	PyObject *pcpus = NULL, *pthreads = NULL;
678 	struct cpu_map *cpus;
679 	struct thread_map *threads;
680 
681 	if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
682 		return -1;
683 
684 	threads = ((struct pyrf_thread_map *)pthreads)->threads;
685 	cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
686 	perf_evlist__init(&pevlist->evlist, cpus, threads);
687 	return 0;
688 }
689 
690 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
691 {
692 	perf_evlist__exit(&pevlist->evlist);
693 	pevlist->ob_type->tp_free((PyObject*)pevlist);
694 }
695 
696 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
697 				   PyObject *args, PyObject *kwargs)
698 {
699 	struct perf_evlist *evlist = &pevlist->evlist;
700 	static char *kwlist[] = { "pages", "overwrite", NULL };
701 	int pages = 128, overwrite = false;
702 
703 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
704 					 &pages, &overwrite))
705 		return NULL;
706 
707 	if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
708 		PyErr_SetFromErrno(PyExc_OSError);
709 		return NULL;
710 	}
711 
712 	Py_INCREF(Py_None);
713 	return Py_None;
714 }
715 
716 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
717 				   PyObject *args, PyObject *kwargs)
718 {
719 	struct perf_evlist *evlist = &pevlist->evlist;
720 	static char *kwlist[] = { "timeout", NULL };
721 	int timeout = -1, n;
722 
723 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
724 		return NULL;
725 
726 	n = poll(evlist->pollfd, evlist->nr_fds, timeout);
727 	if (n < 0) {
728 		PyErr_SetFromErrno(PyExc_OSError);
729 		return NULL;
730 	}
731 
732 	return Py_BuildValue("i", n);
733 }
734 
735 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
736 					 PyObject *args __maybe_unused,
737 					 PyObject *kwargs __maybe_unused)
738 {
739 	struct perf_evlist *evlist = &pevlist->evlist;
740         PyObject *list = PyList_New(0);
741 	int i;
742 
743 	for (i = 0; i < evlist->nr_fds; ++i) {
744 		PyObject *file;
745 		FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
746 
747 		if (fp == NULL)
748 			goto free_list;
749 
750 		file = PyFile_FromFile(fp, "perf", "r", NULL);
751 		if (file == NULL)
752 			goto free_list;
753 
754 		if (PyList_Append(list, file) != 0) {
755 			Py_DECREF(file);
756 			goto free_list;
757 		}
758 
759 		Py_DECREF(file);
760 	}
761 
762 	return list;
763 free_list:
764 	return PyErr_NoMemory();
765 }
766 
767 
768 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
769 				  PyObject *args,
770 				  PyObject *kwargs __maybe_unused)
771 {
772 	struct perf_evlist *evlist = &pevlist->evlist;
773 	PyObject *pevsel;
774 	struct perf_evsel *evsel;
775 
776 	if (!PyArg_ParseTuple(args, "O", &pevsel))
777 		return NULL;
778 
779 	Py_INCREF(pevsel);
780 	evsel = &((struct pyrf_evsel *)pevsel)->evsel;
781 	evsel->idx = evlist->nr_entries;
782 	perf_evlist__add(evlist, evsel);
783 
784 	return Py_BuildValue("i", evlist->nr_entries);
785 }
786 
787 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
788 					  PyObject *args, PyObject *kwargs)
789 {
790 	struct perf_evlist *evlist = &pevlist->evlist;
791 	union perf_event *event;
792 	int sample_id_all = 1, cpu;
793 	static char *kwlist[] = { "cpu", "sample_id_all", NULL };
794 	int err;
795 
796 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
797 					 &cpu, &sample_id_all))
798 		return NULL;
799 
800 	event = perf_evlist__mmap_read(evlist, cpu);
801 	if (event != NULL) {
802 		PyObject *pyevent = pyrf_event__new(event);
803 		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
804 
805 		if (pyevent == NULL)
806 			return PyErr_NoMemory();
807 
808 		err = perf_evlist__parse_sample(evlist, event, &pevent->sample);
809 		if (err)
810 			return PyErr_Format(PyExc_OSError,
811 					    "perf: can't parse sample, err=%d", err);
812 		return pyevent;
813 	}
814 
815 	Py_INCREF(Py_None);
816 	return Py_None;
817 }
818 
819 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
820 				   PyObject *args, PyObject *kwargs)
821 {
822 	struct perf_evlist *evlist = &pevlist->evlist;
823 	int group = 0;
824 	static char *kwlist[] = { "group", NULL };
825 
826 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group))
827 		return NULL;
828 
829 	if (group)
830 		perf_evlist__set_leader(evlist);
831 
832 	if (perf_evlist__open(evlist) < 0) {
833 		PyErr_SetFromErrno(PyExc_OSError);
834 		return NULL;
835 	}
836 
837 	Py_INCREF(Py_None);
838 	return Py_None;
839 }
840 
841 static PyMethodDef pyrf_evlist__methods[] = {
842 	{
843 		.ml_name  = "mmap",
844 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
845 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
846 		.ml_doc	  = PyDoc_STR("mmap the file descriptor table.")
847 	},
848 	{
849 		.ml_name  = "open",
850 		.ml_meth  = (PyCFunction)pyrf_evlist__open,
851 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
852 		.ml_doc	  = PyDoc_STR("open the file descriptors.")
853 	},
854 	{
855 		.ml_name  = "poll",
856 		.ml_meth  = (PyCFunction)pyrf_evlist__poll,
857 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
858 		.ml_doc	  = PyDoc_STR("poll the file descriptor table.")
859 	},
860 	{
861 		.ml_name  = "get_pollfd",
862 		.ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
863 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
864 		.ml_doc	  = PyDoc_STR("get the poll file descriptor table.")
865 	},
866 	{
867 		.ml_name  = "add",
868 		.ml_meth  = (PyCFunction)pyrf_evlist__add,
869 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
870 		.ml_doc	  = PyDoc_STR("adds an event selector to the list.")
871 	},
872 	{
873 		.ml_name  = "read_on_cpu",
874 		.ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
875 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
876 		.ml_doc	  = PyDoc_STR("reads an event.")
877 	},
878 	{ .ml_name = NULL, }
879 };
880 
881 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
882 {
883 	struct pyrf_evlist *pevlist = (void *)obj;
884 
885 	return pevlist->evlist.nr_entries;
886 }
887 
888 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
889 {
890 	struct pyrf_evlist *pevlist = (void *)obj;
891 	struct perf_evsel *pos;
892 
893 	if (i >= pevlist->evlist.nr_entries)
894 		return NULL;
895 
896 	list_for_each_entry(pos, &pevlist->evlist.entries, node)
897 		if (i-- == 0)
898 			break;
899 
900 	return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
901 }
902 
903 static PySequenceMethods pyrf_evlist__sequence_methods = {
904 	.sq_length = pyrf_evlist__length,
905 	.sq_item   = pyrf_evlist__item,
906 };
907 
908 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
909 
910 static PyTypeObject pyrf_evlist__type = {
911 	PyVarObject_HEAD_INIT(NULL, 0)
912 	.tp_name	= "perf.evlist",
913 	.tp_basicsize	= sizeof(struct pyrf_evlist),
914 	.tp_dealloc	= (destructor)pyrf_evlist__delete,
915 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
916 	.tp_as_sequence	= &pyrf_evlist__sequence_methods,
917 	.tp_doc		= pyrf_evlist__doc,
918 	.tp_methods	= pyrf_evlist__methods,
919 	.tp_init	= (initproc)pyrf_evlist__init,
920 };
921 
922 static int pyrf_evlist__setup_types(void)
923 {
924 	pyrf_evlist__type.tp_new = PyType_GenericNew;
925 	return PyType_Ready(&pyrf_evlist__type);
926 }
927 
928 static struct {
929 	const char *name;
930 	int	    value;
931 } perf__constants[] = {
932 	{ "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
933 	{ "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
934 	{ "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
935 	{ "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
936 	{ "TYPE_RAW",	     PERF_TYPE_RAW },
937 	{ "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
938 
939 	{ "COUNT_HW_CPU_CYCLES",	  PERF_COUNT_HW_CPU_CYCLES },
940 	{ "COUNT_HW_INSTRUCTIONS",	  PERF_COUNT_HW_INSTRUCTIONS },
941 	{ "COUNT_HW_CACHE_REFERENCES",	  PERF_COUNT_HW_CACHE_REFERENCES },
942 	{ "COUNT_HW_CACHE_MISSES",	  PERF_COUNT_HW_CACHE_MISSES },
943 	{ "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
944 	{ "COUNT_HW_BRANCH_MISSES",	  PERF_COUNT_HW_BRANCH_MISSES },
945 	{ "COUNT_HW_BUS_CYCLES",	  PERF_COUNT_HW_BUS_CYCLES },
946 	{ "COUNT_HW_CACHE_L1D",		  PERF_COUNT_HW_CACHE_L1D },
947 	{ "COUNT_HW_CACHE_L1I",		  PERF_COUNT_HW_CACHE_L1I },
948 	{ "COUNT_HW_CACHE_LL",	  	  PERF_COUNT_HW_CACHE_LL },
949 	{ "COUNT_HW_CACHE_DTLB",	  PERF_COUNT_HW_CACHE_DTLB },
950 	{ "COUNT_HW_CACHE_ITLB",	  PERF_COUNT_HW_CACHE_ITLB },
951 	{ "COUNT_HW_CACHE_BPU",		  PERF_COUNT_HW_CACHE_BPU },
952 	{ "COUNT_HW_CACHE_OP_READ",	  PERF_COUNT_HW_CACHE_OP_READ },
953 	{ "COUNT_HW_CACHE_OP_WRITE",	  PERF_COUNT_HW_CACHE_OP_WRITE },
954 	{ "COUNT_HW_CACHE_OP_PREFETCH",	  PERF_COUNT_HW_CACHE_OP_PREFETCH },
955 	{ "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
956 	{ "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
957 
958 	{ "COUNT_HW_STALLED_CYCLES_FRONTEND",	  PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
959 	{ "COUNT_HW_STALLED_CYCLES_BACKEND",	  PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
960 
961 	{ "COUNT_SW_CPU_CLOCK",	       PERF_COUNT_SW_CPU_CLOCK },
962 	{ "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
963 	{ "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
964 	{ "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
965 	{ "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
966 	{ "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
967 	{ "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
968 	{ "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
969 	{ "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
970 
971 	{ "SAMPLE_IP",	      PERF_SAMPLE_IP },
972 	{ "SAMPLE_TID",	      PERF_SAMPLE_TID },
973 	{ "SAMPLE_TIME",      PERF_SAMPLE_TIME },
974 	{ "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
975 	{ "SAMPLE_READ",      PERF_SAMPLE_READ },
976 	{ "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
977 	{ "SAMPLE_ID",	      PERF_SAMPLE_ID },
978 	{ "SAMPLE_CPU",	      PERF_SAMPLE_CPU },
979 	{ "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
980 	{ "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
981 	{ "SAMPLE_RAW",	      PERF_SAMPLE_RAW },
982 
983 	{ "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
984 	{ "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
985 	{ "FORMAT_ID",		       PERF_FORMAT_ID },
986 	{ "FORMAT_GROUP",	       PERF_FORMAT_GROUP },
987 
988 	{ "RECORD_MMAP",       PERF_RECORD_MMAP },
989 	{ "RECORD_LOST",       PERF_RECORD_LOST },
990 	{ "RECORD_COMM",       PERF_RECORD_COMM },
991 	{ "RECORD_EXIT",       PERF_RECORD_EXIT },
992 	{ "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
993 	{ "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
994 	{ "RECORD_FORK",       PERF_RECORD_FORK },
995 	{ "RECORD_READ",       PERF_RECORD_READ },
996 	{ "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
997 	{ .name = NULL, },
998 };
999 
1000 static PyMethodDef perf__methods[] = {
1001 	{ .ml_name = NULL, }
1002 };
1003 
1004 PyMODINIT_FUNC initperf(void)
1005 {
1006 	PyObject *obj;
1007 	int i;
1008 	PyObject *dict, *module = Py_InitModule("perf", perf__methods);
1009 
1010 	if (module == NULL ||
1011 	    pyrf_event__setup_types() < 0 ||
1012 	    pyrf_evlist__setup_types() < 0 ||
1013 	    pyrf_evsel__setup_types() < 0 ||
1014 	    pyrf_thread_map__setup_types() < 0 ||
1015 	    pyrf_cpu_map__setup_types() < 0)
1016 		return;
1017 
1018 	page_size = sysconf(_SC_PAGE_SIZE);
1019 
1020 	Py_INCREF(&pyrf_evlist__type);
1021 	PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
1022 
1023 	Py_INCREF(&pyrf_evsel__type);
1024 	PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
1025 
1026 	Py_INCREF(&pyrf_thread_map__type);
1027 	PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
1028 
1029 	Py_INCREF(&pyrf_cpu_map__type);
1030 	PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
1031 
1032 	dict = PyModule_GetDict(module);
1033 	if (dict == NULL)
1034 		goto error;
1035 
1036 	for (i = 0; perf__constants[i].name != NULL; i++) {
1037 		obj = PyInt_FromLong(perf__constants[i].value);
1038 		if (obj == NULL)
1039 			goto error;
1040 		PyDict_SetItemString(dict, perf__constants[i].name, obj);
1041 		Py_DECREF(obj);
1042 	}
1043 
1044 error:
1045 	if (PyErr_Occurred())
1046 		PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
1047 }
1048