xref: /linux/tools/perf/util/python.c (revision ec714e371f22f716a04e6ecb2a24988c92b26911)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <Python.h>
3 #include <structmember.h>
4 #include <inttypes.h>
5 #include <poll.h>
6 #include <linux/err.h>
7 #include <perf/cpumap.h>
8 #ifdef HAVE_LIBTRACEEVENT
9 #include <event-parse.h>
10 #endif
11 #include <perf/mmap.h>
12 #include "callchain.h"
13 #include "counts.h"
14 #include "evlist.h"
15 #include "evsel.h"
16 #include "event.h"
17 #include "expr.h"
18 #include "print_binary.h"
19 #include "record.h"
20 #include "strbuf.h"
21 #include "thread_map.h"
22 #include "tp_pmu.h"
23 #include "trace-event.h"
24 #include "metricgroup.h"
25 #include "mmap.h"
26 #include "util/sample.h"
27 #include <internal/lib.h>
28 
29 PyMODINIT_FUNC PyInit_perf(void);
30 
31 #define member_def(type, member, ptype, help) \
32 	{ #member, ptype, \
33 	  offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
34 	  0, help }
35 
36 #define sample_member_def(name, member, ptype, help) \
37 	{ #name, ptype, \
38 	  offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
39 	  0, help }
40 
41 struct pyrf_event {
42 	PyObject_HEAD
43 	struct evsel *evsel;
44 	struct perf_sample sample;
45 	union perf_event   event;
46 };
47 
48 #define sample_members \
49 	sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"),			 \
50 	sample_member_def(sample_pid, pid, T_INT, "event pid"),			 \
51 	sample_member_def(sample_tid, tid, T_INT, "event tid"),			 \
52 	sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),		 \
53 	sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),		 \
54 	sample_member_def(sample_id, id, T_ULONGLONG, "event id"),			 \
55 	sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
56 	sample_member_def(sample_period, period, T_ULONGLONG, "event period"),		 \
57 	sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
58 
59 static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
60 
61 static PyMemberDef pyrf_mmap_event__members[] = {
62 	sample_members
63 	member_def(perf_event_header, type, T_UINT, "event type"),
64 	member_def(perf_event_header, misc, T_UINT, "event misc"),
65 	member_def(perf_record_mmap, pid, T_UINT, "event pid"),
66 	member_def(perf_record_mmap, tid, T_UINT, "event tid"),
67 	member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"),
68 	member_def(perf_record_mmap, len, T_ULONGLONG, "map length"),
69 	member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"),
70 	member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"),
71 	{ .name = NULL, },
72 };
73 
pyrf_mmap_event__repr(const struct pyrf_event * pevent)74 static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent)
75 {
76 	PyObject *ret;
77 	char *s;
78 
79 	if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", "
80 			 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", "
81 			 "filename: %s }",
82 		     pevent->event.mmap.pid, pevent->event.mmap.tid,
83 		     pevent->event.mmap.start, pevent->event.mmap.len,
84 		     pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
85 		ret = PyErr_NoMemory();
86 	} else {
87 		ret = PyUnicode_FromString(s);
88 		free(s);
89 	}
90 	return ret;
91 }
92 
93 static PyTypeObject pyrf_mmap_event__type = {
94 	PyVarObject_HEAD_INIT(NULL, 0)
95 	.tp_name	= "perf.mmap_event",
96 	.tp_basicsize	= sizeof(struct pyrf_event),
97 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
98 	.tp_doc		= pyrf_mmap_event__doc,
99 	.tp_members	= pyrf_mmap_event__members,
100 	.tp_repr	= (reprfunc)pyrf_mmap_event__repr,
101 };
102 
103 static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
104 
105 static PyMemberDef pyrf_task_event__members[] = {
106 	sample_members
107 	member_def(perf_event_header, type, T_UINT, "event type"),
108 	member_def(perf_record_fork, pid, T_UINT, "event pid"),
109 	member_def(perf_record_fork, ppid, T_UINT, "event ppid"),
110 	member_def(perf_record_fork, tid, T_UINT, "event tid"),
111 	member_def(perf_record_fork, ptid, T_UINT, "event ptid"),
112 	member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"),
113 	{ .name = NULL, },
114 };
115 
pyrf_task_event__repr(const struct pyrf_event * pevent)116 static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent)
117 {
118 	return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
119 				   "ptid: %u, time: %" PRI_lu64 "}",
120 				   pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
121 				   pevent->event.fork.pid,
122 				   pevent->event.fork.ppid,
123 				   pevent->event.fork.tid,
124 				   pevent->event.fork.ptid,
125 				   pevent->event.fork.time);
126 }
127 
128 static PyTypeObject pyrf_task_event__type = {
129 	PyVarObject_HEAD_INIT(NULL, 0)
130 	.tp_name	= "perf.task_event",
131 	.tp_basicsize	= sizeof(struct pyrf_event),
132 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
133 	.tp_doc		= pyrf_task_event__doc,
134 	.tp_members	= pyrf_task_event__members,
135 	.tp_repr	= (reprfunc)pyrf_task_event__repr,
136 };
137 
138 static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
139 
140 static PyMemberDef pyrf_comm_event__members[] = {
141 	sample_members
142 	member_def(perf_event_header, type, T_UINT, "event type"),
143 	member_def(perf_record_comm, pid, T_UINT, "event pid"),
144 	member_def(perf_record_comm, tid, T_UINT, "event tid"),
145 	member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"),
146 	{ .name = NULL, },
147 };
148 
pyrf_comm_event__repr(const struct pyrf_event * pevent)149 static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent)
150 {
151 	return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
152 				   pevent->event.comm.pid,
153 				   pevent->event.comm.tid,
154 				   pevent->event.comm.comm);
155 }
156 
157 static PyTypeObject pyrf_comm_event__type = {
158 	PyVarObject_HEAD_INIT(NULL, 0)
159 	.tp_name	= "perf.comm_event",
160 	.tp_basicsize	= sizeof(struct pyrf_event),
161 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
162 	.tp_doc		= pyrf_comm_event__doc,
163 	.tp_members	= pyrf_comm_event__members,
164 	.tp_repr	= (reprfunc)pyrf_comm_event__repr,
165 };
166 
167 static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
168 
169 static PyMemberDef pyrf_throttle_event__members[] = {
170 	sample_members
171 	member_def(perf_event_header, type, T_UINT, "event type"),
172 	member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"),
173 	member_def(perf_record_throttle, id, T_ULONGLONG, "event id"),
174 	member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"),
175 	{ .name = NULL, },
176 };
177 
pyrf_throttle_event__repr(const struct pyrf_event * pevent)178 static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent)
179 {
180 	const struct perf_record_throttle *te = (const struct perf_record_throttle *)
181 		(&pevent->event.header + 1);
182 
183 	return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64
184 				   ", stream_id: %" PRI_lu64 " }",
185 				   pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
186 				   te->time, te->id, te->stream_id);
187 }
188 
189 static PyTypeObject pyrf_throttle_event__type = {
190 	PyVarObject_HEAD_INIT(NULL, 0)
191 	.tp_name	= "perf.throttle_event",
192 	.tp_basicsize	= sizeof(struct pyrf_event),
193 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
194 	.tp_doc		= pyrf_throttle_event__doc,
195 	.tp_members	= pyrf_throttle_event__members,
196 	.tp_repr	= (reprfunc)pyrf_throttle_event__repr,
197 };
198 
199 static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object.");
200 
201 static PyMemberDef pyrf_lost_event__members[] = {
202 	sample_members
203 	member_def(perf_record_lost, id, T_ULONGLONG, "event id"),
204 	member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"),
205 	{ .name = NULL, },
206 };
207 
pyrf_lost_event__repr(const struct pyrf_event * pevent)208 static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent)
209 {
210 	PyObject *ret;
211 	char *s;
212 
213 	if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", "
214 			 "lost: %#" PRI_lx64 " }",
215 		     pevent->event.lost.id, pevent->event.lost.lost) < 0) {
216 		ret = PyErr_NoMemory();
217 	} else {
218 		ret = PyUnicode_FromString(s);
219 		free(s);
220 	}
221 	return ret;
222 }
223 
224 static PyTypeObject pyrf_lost_event__type = {
225 	PyVarObject_HEAD_INIT(NULL, 0)
226 	.tp_name	= "perf.lost_event",
227 	.tp_basicsize	= sizeof(struct pyrf_event),
228 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
229 	.tp_doc		= pyrf_lost_event__doc,
230 	.tp_members	= pyrf_lost_event__members,
231 	.tp_repr	= (reprfunc)pyrf_lost_event__repr,
232 };
233 
234 static const char pyrf_read_event__doc[] = PyDoc_STR("perf read event object.");
235 
236 static PyMemberDef pyrf_read_event__members[] = {
237 	sample_members
238 	member_def(perf_record_read, pid, T_UINT, "event pid"),
239 	member_def(perf_record_read, tid, T_UINT, "event tid"),
240 	{ .name = NULL, },
241 };
242 
pyrf_read_event__repr(const struct pyrf_event * pevent)243 static PyObject *pyrf_read_event__repr(const struct pyrf_event *pevent)
244 {
245 	return PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
246 				   pevent->event.read.pid,
247 				   pevent->event.read.tid);
248 	/*
249  	 * FIXME: return the array of read values,
250  	 * making this method useful ;-)
251  	 */
252 }
253 
254 static PyTypeObject pyrf_read_event__type = {
255 	PyVarObject_HEAD_INIT(NULL, 0)
256 	.tp_name	= "perf.read_event",
257 	.tp_basicsize	= sizeof(struct pyrf_event),
258 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
259 	.tp_doc		= pyrf_read_event__doc,
260 	.tp_members	= pyrf_read_event__members,
261 	.tp_repr	= (reprfunc)pyrf_read_event__repr,
262 };
263 
264 static const char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object.");
265 
266 static PyMemberDef pyrf_sample_event__members[] = {
267 	sample_members
268 	member_def(perf_event_header, type, T_UINT, "event type"),
269 	{ .name = NULL, },
270 };
271 
pyrf_sample_event__delete(struct pyrf_event * pevent)272 static void pyrf_sample_event__delete(struct pyrf_event *pevent)
273 {
274 	perf_sample__exit(&pevent->sample);
275 	Py_TYPE(pevent)->tp_free((PyObject*)pevent);
276 }
277 
pyrf_sample_event__repr(const struct pyrf_event * pevent)278 static PyObject *pyrf_sample_event__repr(const struct pyrf_event *pevent)
279 {
280 	PyObject *ret;
281 	char *s;
282 
283 	if (asprintf(&s, "{ type: sample }") < 0) {
284 		ret = PyErr_NoMemory();
285 	} else {
286 		ret = PyUnicode_FromString(s);
287 		free(s);
288 	}
289 	return ret;
290 }
291 
292 #ifdef HAVE_LIBTRACEEVENT
is_tracepoint(const struct pyrf_event * pevent)293 static bool is_tracepoint(const struct pyrf_event *pevent)
294 {
295 	return pevent->evsel->core.attr.type == PERF_TYPE_TRACEPOINT;
296 }
297 
298 static PyObject*
tracepoint_field(const struct pyrf_event * pe,struct tep_format_field * field)299 tracepoint_field(const struct pyrf_event *pe, struct tep_format_field *field)
300 {
301 	struct tep_handle *pevent = field->event->tep;
302 	void *data = pe->sample.raw_data;
303 	PyObject *ret = NULL;
304 	unsigned long long val;
305 	unsigned int offset, len;
306 
307 	if (field->flags & TEP_FIELD_IS_ARRAY) {
308 		offset = field->offset;
309 		len    = field->size;
310 		if (field->flags & TEP_FIELD_IS_DYNAMIC) {
311 			val     = tep_read_number(pevent, data + offset, len);
312 			offset  = val;
313 			len     = offset >> 16;
314 			offset &= 0xffff;
315 			if (tep_field_is_relative(field->flags))
316 				offset += field->offset + field->size;
317 		}
318 		if (field->flags & TEP_FIELD_IS_STRING &&
319 		    is_printable_array(data + offset, len)) {
320 			ret = PyUnicode_FromString((char *)data + offset);
321 		} else {
322 			ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
323 			field->flags &= ~TEP_FIELD_IS_STRING;
324 		}
325 	} else {
326 		val = tep_read_number(pevent, data + field->offset,
327 				      field->size);
328 		if (field->flags & TEP_FIELD_IS_POINTER)
329 			ret = PyLong_FromUnsignedLong((unsigned long) val);
330 		else if (field->flags & TEP_FIELD_IS_SIGNED)
331 			ret = PyLong_FromLong((long) val);
332 		else
333 			ret = PyLong_FromUnsignedLong((unsigned long) val);
334 	}
335 
336 	return ret;
337 }
338 
339 static PyObject*
get_tracepoint_field(struct pyrf_event * pevent,PyObject * attr_name)340 get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
341 {
342 	struct evsel *evsel = pevent->evsel;
343 	struct tep_event *tp_format = evsel__tp_format(evsel);
344 	struct tep_format_field *field;
345 
346 	if (IS_ERR_OR_NULL(tp_format))
347 		return NULL;
348 
349 	PyObject *obj = PyObject_Str(attr_name);
350 	if (obj == NULL)
351 		return NULL;
352 
353 	const char *str = PyUnicode_AsUTF8(obj);
354 	if (str == NULL) {
355 		Py_DECREF(obj);
356 		return NULL;
357 	}
358 
359 	field = tep_find_any_field(tp_format, str);
360 	Py_DECREF(obj);
361 	return field ? tracepoint_field(pevent, field) : NULL;
362 }
363 #endif /* HAVE_LIBTRACEEVENT */
364 
365 static PyObject*
pyrf_sample_event__getattro(struct pyrf_event * pevent,PyObject * attr_name)366 pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
367 {
368 	PyObject *obj = NULL;
369 
370 #ifdef HAVE_LIBTRACEEVENT
371 	if (is_tracepoint(pevent))
372 		obj = get_tracepoint_field(pevent, attr_name);
373 #endif
374 
375 	return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
376 }
377 
378 static PyTypeObject pyrf_sample_event__type = {
379 	PyVarObject_HEAD_INIT(NULL, 0)
380 	.tp_name	= "perf.sample_event",
381 	.tp_basicsize	= sizeof(struct pyrf_event),
382 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
383 	.tp_doc		= pyrf_sample_event__doc,
384 	.tp_members	= pyrf_sample_event__members,
385 	.tp_repr	= (reprfunc)pyrf_sample_event__repr,
386 	.tp_getattro	= (getattrofunc) pyrf_sample_event__getattro,
387 };
388 
389 static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
390 
391 static PyMemberDef pyrf_context_switch_event__members[] = {
392 	sample_members
393 	member_def(perf_event_header, type, T_UINT, "event type"),
394 	member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"),
395 	member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"),
396 	{ .name = NULL, },
397 };
398 
pyrf_context_switch_event__repr(const struct pyrf_event * pevent)399 static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent)
400 {
401 	PyObject *ret;
402 	char *s;
403 
404 	if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
405 		     pevent->event.context_switch.next_prev_pid,
406 		     pevent->event.context_switch.next_prev_tid,
407 		     !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
408 		ret = PyErr_NoMemory();
409 	} else {
410 		ret = PyUnicode_FromString(s);
411 		free(s);
412 	}
413 	return ret;
414 }
415 
416 static PyTypeObject pyrf_context_switch_event__type = {
417 	PyVarObject_HEAD_INIT(NULL, 0)
418 	.tp_name	= "perf.context_switch_event",
419 	.tp_basicsize	= sizeof(struct pyrf_event),
420 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
421 	.tp_doc		= pyrf_context_switch_event__doc,
422 	.tp_members	= pyrf_context_switch_event__members,
423 	.tp_repr	= (reprfunc)pyrf_context_switch_event__repr,
424 };
425 
pyrf_event__setup_types(void)426 static int pyrf_event__setup_types(void)
427 {
428 	int err;
429 	pyrf_mmap_event__type.tp_new =
430 	pyrf_task_event__type.tp_new =
431 	pyrf_comm_event__type.tp_new =
432 	pyrf_lost_event__type.tp_new =
433 	pyrf_read_event__type.tp_new =
434 	pyrf_sample_event__type.tp_new =
435 	pyrf_context_switch_event__type.tp_new =
436 	pyrf_throttle_event__type.tp_new = PyType_GenericNew;
437 
438 	pyrf_sample_event__type.tp_dealloc = (destructor)pyrf_sample_event__delete,
439 
440 	err = PyType_Ready(&pyrf_mmap_event__type);
441 	if (err < 0)
442 		goto out;
443 	err = PyType_Ready(&pyrf_lost_event__type);
444 	if (err < 0)
445 		goto out;
446 	err = PyType_Ready(&pyrf_task_event__type);
447 	if (err < 0)
448 		goto out;
449 	err = PyType_Ready(&pyrf_comm_event__type);
450 	if (err < 0)
451 		goto out;
452 	err = PyType_Ready(&pyrf_throttle_event__type);
453 	if (err < 0)
454 		goto out;
455 	err = PyType_Ready(&pyrf_read_event__type);
456 	if (err < 0)
457 		goto out;
458 	err = PyType_Ready(&pyrf_sample_event__type);
459 	if (err < 0)
460 		goto out;
461 	err = PyType_Ready(&pyrf_context_switch_event__type);
462 	if (err < 0)
463 		goto out;
464 out:
465 	return err;
466 }
467 
468 static PyTypeObject *pyrf_event__type[] = {
469 	[PERF_RECORD_MMAP]	 = &pyrf_mmap_event__type,
470 	[PERF_RECORD_LOST]	 = &pyrf_lost_event__type,
471 	[PERF_RECORD_COMM]	 = &pyrf_comm_event__type,
472 	[PERF_RECORD_EXIT]	 = &pyrf_task_event__type,
473 	[PERF_RECORD_THROTTLE]	 = &pyrf_throttle_event__type,
474 	[PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
475 	[PERF_RECORD_FORK]	 = &pyrf_task_event__type,
476 	[PERF_RECORD_READ]	 = &pyrf_read_event__type,
477 	[PERF_RECORD_SAMPLE]	 = &pyrf_sample_event__type,
478 	[PERF_RECORD_SWITCH]	 = &pyrf_context_switch_event__type,
479 	[PERF_RECORD_SWITCH_CPU_WIDE]  = &pyrf_context_switch_event__type,
480 };
481 
pyrf_event__new(const union perf_event * event)482 static PyObject *pyrf_event__new(const union perf_event *event)
483 {
484 	struct pyrf_event *pevent;
485 	PyTypeObject *ptype;
486 
487 	if ((event->header.type < PERF_RECORD_MMAP ||
488 	     event->header.type > PERF_RECORD_SAMPLE) &&
489 	    !(event->header.type == PERF_RECORD_SWITCH ||
490 	      event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) {
491 		PyErr_Format(PyExc_TypeError, "Unexpected header type %u",
492 			     event->header.type);
493 		return NULL;
494 	}
495 
496 	// FIXME this better be dynamic or we need to parse everything
497 	// before calling perf_mmap__consume(), including tracepoint fields.
498 	if (sizeof(pevent->event) < event->header.size) {
499 		PyErr_Format(PyExc_TypeError, "Unexpected event size: %zd < %u",
500 			     sizeof(pevent->event), event->header.size);
501 		return NULL;
502 	}
503 
504 	ptype = pyrf_event__type[event->header.type];
505 	pevent = PyObject_New(struct pyrf_event, ptype);
506 	if (pevent != NULL)
507 		memcpy(&pevent->event, event, event->header.size);
508 	return (PyObject *)pevent;
509 }
510 
511 struct pyrf_cpu_map {
512 	PyObject_HEAD
513 
514 	struct perf_cpu_map *cpus;
515 };
516 
pyrf_cpu_map__init(struct pyrf_cpu_map * pcpus,PyObject * args,PyObject * kwargs)517 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
518 			      PyObject *args, PyObject *kwargs)
519 {
520 	static char *kwlist[] = { "cpustr", NULL };
521 	char *cpustr = NULL;
522 
523 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
524 					 kwlist, &cpustr))
525 		return -1;
526 
527 	pcpus->cpus = perf_cpu_map__new(cpustr);
528 	if (pcpus->cpus == NULL)
529 		return -1;
530 	return 0;
531 }
532 
pyrf_cpu_map__delete(struct pyrf_cpu_map * pcpus)533 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
534 {
535 	perf_cpu_map__put(pcpus->cpus);
536 	Py_TYPE(pcpus)->tp_free((PyObject*)pcpus);
537 }
538 
pyrf_cpu_map__length(PyObject * obj)539 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
540 {
541 	struct pyrf_cpu_map *pcpus = (void *)obj;
542 
543 	return perf_cpu_map__nr(pcpus->cpus);
544 }
545 
pyrf_cpu_map__item(PyObject * obj,Py_ssize_t i)546 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
547 {
548 	struct pyrf_cpu_map *pcpus = (void *)obj;
549 
550 	if (i >= perf_cpu_map__nr(pcpus->cpus)) {
551 		PyErr_SetString(PyExc_IndexError, "Index out of range");
552 		return NULL;
553 	}
554 
555 	return Py_BuildValue("i", perf_cpu_map__cpu(pcpus->cpus, i).cpu);
556 }
557 
558 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
559 	.sq_length = pyrf_cpu_map__length,
560 	.sq_item   = pyrf_cpu_map__item,
561 };
562 
563 static const char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
564 
565 static PyTypeObject pyrf_cpu_map__type = {
566 	PyVarObject_HEAD_INIT(NULL, 0)
567 	.tp_name	= "perf.cpu_map",
568 	.tp_basicsize	= sizeof(struct pyrf_cpu_map),
569 	.tp_dealloc	= (destructor)pyrf_cpu_map__delete,
570 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
571 	.tp_doc		= pyrf_cpu_map__doc,
572 	.tp_as_sequence	= &pyrf_cpu_map__sequence_methods,
573 	.tp_init	= (initproc)pyrf_cpu_map__init,
574 };
575 
pyrf_cpu_map__setup_types(void)576 static int pyrf_cpu_map__setup_types(void)
577 {
578 	pyrf_cpu_map__type.tp_new = PyType_GenericNew;
579 	return PyType_Ready(&pyrf_cpu_map__type);
580 }
581 
582 struct pyrf_thread_map {
583 	PyObject_HEAD
584 
585 	struct perf_thread_map *threads;
586 };
587 
pyrf_thread_map__init(struct pyrf_thread_map * pthreads,PyObject * args,PyObject * kwargs)588 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
589 				 PyObject *args, PyObject *kwargs)
590 {
591 	static char *kwlist[] = { "pid", "tid", NULL };
592 	int pid = -1, tid = -1;
593 
594 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
595 					 kwlist, &pid, &tid))
596 		return -1;
597 
598 	pthreads->threads = thread_map__new(pid, tid);
599 	if (pthreads->threads == NULL)
600 		return -1;
601 	return 0;
602 }
603 
pyrf_thread_map__delete(struct pyrf_thread_map * pthreads)604 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
605 {
606 	perf_thread_map__put(pthreads->threads);
607 	Py_TYPE(pthreads)->tp_free((PyObject*)pthreads);
608 }
609 
pyrf_thread_map__length(PyObject * obj)610 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
611 {
612 	struct pyrf_thread_map *pthreads = (void *)obj;
613 
614 	return perf_thread_map__nr(pthreads->threads);
615 }
616 
pyrf_thread_map__item(PyObject * obj,Py_ssize_t i)617 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
618 {
619 	struct pyrf_thread_map *pthreads = (void *)obj;
620 
621 	if (i >= perf_thread_map__nr(pthreads->threads)) {
622 		PyErr_SetString(PyExc_IndexError, "Index out of range");
623 		return NULL;
624 	}
625 
626 	return Py_BuildValue("i", perf_thread_map__pid(pthreads->threads, i));
627 }
628 
629 static PySequenceMethods pyrf_thread_map__sequence_methods = {
630 	.sq_length = pyrf_thread_map__length,
631 	.sq_item   = pyrf_thread_map__item,
632 };
633 
634 static const char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
635 
636 static PyTypeObject pyrf_thread_map__type = {
637 	PyVarObject_HEAD_INIT(NULL, 0)
638 	.tp_name	= "perf.thread_map",
639 	.tp_basicsize	= sizeof(struct pyrf_thread_map),
640 	.tp_dealloc	= (destructor)pyrf_thread_map__delete,
641 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
642 	.tp_doc		= pyrf_thread_map__doc,
643 	.tp_as_sequence	= &pyrf_thread_map__sequence_methods,
644 	.tp_init	= (initproc)pyrf_thread_map__init,
645 };
646 
pyrf_thread_map__setup_types(void)647 static int pyrf_thread_map__setup_types(void)
648 {
649 	pyrf_thread_map__type.tp_new = PyType_GenericNew;
650 	return PyType_Ready(&pyrf_thread_map__type);
651 }
652 
653 /**
654  * A python wrapper for perf_pmus that are globally owned by the pmus.c code.
655  */
656 struct pyrf_pmu {
657 	PyObject_HEAD
658 
659 	struct perf_pmu *pmu;
660 };
661 
pyrf_pmu__delete(struct pyrf_pmu * ppmu)662 static void pyrf_pmu__delete(struct pyrf_pmu *ppmu)
663 {
664 	Py_TYPE(ppmu)->tp_free((PyObject *)ppmu);
665 }
666 
pyrf_pmu__name(PyObject * self)667 static PyObject *pyrf_pmu__name(PyObject *self)
668 {
669 	struct pyrf_pmu *ppmu = (void *)self;
670 
671 	return PyUnicode_FromString(ppmu->pmu->name);
672 }
673 
add_to_dict(PyObject * dict,const char * key,const char * value)674 static bool add_to_dict(PyObject *dict, const char *key, const char *value)
675 {
676 	PyObject *pkey, *pvalue;
677 	bool ret;
678 
679 	if (value == NULL)
680 		return true;
681 
682 	pkey = PyUnicode_FromString(key);
683 	pvalue = PyUnicode_FromString(value);
684 
685 	ret = pkey && pvalue && PyDict_SetItem(dict, pkey, pvalue) == 0;
686 	Py_XDECREF(pkey);
687 	Py_XDECREF(pvalue);
688 	return ret;
689 }
690 
pyrf_pmu__events_cb(void * state,struct pmu_event_info * info)691 static int pyrf_pmu__events_cb(void *state, struct pmu_event_info *info)
692 {
693 	PyObject *py_list = state;
694 	PyObject *dict = PyDict_New();
695 
696 	if (!dict)
697 		return -ENOMEM;
698 
699 	if (!add_to_dict(dict, "name", info->name) ||
700 	    !add_to_dict(dict, "alias", info->alias) ||
701 	    !add_to_dict(dict, "scale_unit", info->scale_unit) ||
702 	    !add_to_dict(dict, "desc", info->desc) ||
703 	    !add_to_dict(dict, "long_desc", info->long_desc) ||
704 	    !add_to_dict(dict, "encoding_desc", info->encoding_desc) ||
705 	    !add_to_dict(dict, "topic", info->topic) ||
706 	    !add_to_dict(dict, "event_type_desc", info->event_type_desc) ||
707 	    !add_to_dict(dict, "str", info->str) ||
708 	    !add_to_dict(dict, "deprecated", info->deprecated ? "deprecated" : NULL) ||
709 	    PyList_Append(py_list, dict) != 0) {
710 		Py_DECREF(dict);
711 		return -ENOMEM;
712 	}
713 	Py_DECREF(dict);
714 	return 0;
715 }
716 
pyrf_pmu__events(PyObject * self)717 static PyObject *pyrf_pmu__events(PyObject *self)
718 {
719 	struct pyrf_pmu *ppmu = (void *)self;
720 	PyObject *py_list = PyList_New(0);
721 	int ret;
722 
723 	if (!py_list)
724 		return NULL;
725 
726 	ret = perf_pmu__for_each_event(ppmu->pmu,
727 				       /*skip_duplicate_pmus=*/false,
728 				       py_list,
729 				       pyrf_pmu__events_cb);
730 	if (ret) {
731 		Py_DECREF(py_list);
732 		errno = -ret;
733 		PyErr_SetFromErrno(PyExc_OSError);
734 		return NULL;
735 	}
736 	return py_list;
737 }
738 
pyrf_pmu__repr(PyObject * self)739 static PyObject *pyrf_pmu__repr(PyObject *self)
740 {
741 	struct pyrf_pmu *ppmu = (void *)self;
742 
743 	return PyUnicode_FromFormat("pmu(%s)", ppmu->pmu->name);
744 }
745 
746 static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object.");
747 
748 static PyMethodDef pyrf_pmu__methods[] = {
749 	{
750 		.ml_name  = "events",
751 		.ml_meth  = (PyCFunction)pyrf_pmu__events,
752 		.ml_flags = METH_NOARGS,
753 		.ml_doc	  = PyDoc_STR("Returns a sequence of events encoded as a dictionaries.")
754 	},
755 	{
756 		.ml_name  = "name",
757 		.ml_meth  = (PyCFunction)pyrf_pmu__name,
758 		.ml_flags = METH_NOARGS,
759 		.ml_doc	  = PyDoc_STR("Name of the PMU including suffixes.")
760 	},
761 	{ .ml_name = NULL, }
762 };
763 
764 /** The python type for a perf.pmu. */
765 static PyTypeObject pyrf_pmu__type = {
766 	PyVarObject_HEAD_INIT(NULL, 0)
767 	.tp_name	= "perf.pmu",
768 	.tp_basicsize	= sizeof(struct pyrf_pmu),
769 	.tp_dealloc	= (destructor)pyrf_pmu__delete,
770 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
771 	.tp_doc		= pyrf_pmu__doc,
772 	.tp_methods	= pyrf_pmu__methods,
773 	.tp_str         = pyrf_pmu__name,
774 	.tp_repr        = pyrf_pmu__repr,
775 };
776 
pyrf_pmu__setup_types(void)777 static int pyrf_pmu__setup_types(void)
778 {
779 	pyrf_pmu__type.tp_new = PyType_GenericNew;
780 	return PyType_Ready(&pyrf_pmu__type);
781 }
782 
783 
784 /** A python iterator for pmus that has no equivalent in the C code. */
785 struct pyrf_pmu_iterator {
786 	PyObject_HEAD
787 	struct perf_pmu *pmu;
788 };
789 
pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator * self)790 static void pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator *self)
791 {
792 	Py_TYPE(self)->tp_free((PyObject *) self);
793 }
794 
pyrf_pmu_iterator__new(PyTypeObject * type,PyObject * args __maybe_unused,PyObject * kwds __maybe_unused)795 static PyObject *pyrf_pmu_iterator__new(PyTypeObject *type, PyObject *args __maybe_unused,
796 					PyObject *kwds __maybe_unused)
797 {
798 	struct pyrf_pmu_iterator *itr = (void *)type->tp_alloc(type, 0);
799 
800 	if (itr != NULL)
801 		itr->pmu = perf_pmus__scan(/*pmu=*/NULL);
802 
803 	return (PyObject *) itr;
804 }
805 
pyrf_pmu_iterator__iter(PyObject * self)806 static PyObject *pyrf_pmu_iterator__iter(PyObject *self)
807 {
808 	Py_INCREF(self);
809 	return self;
810 }
811 
pyrf_pmu_iterator__iternext(PyObject * self)812 static PyObject *pyrf_pmu_iterator__iternext(PyObject *self)
813 {
814 	struct pyrf_pmu_iterator *itr = (void *)self;
815 	struct pyrf_pmu *ppmu;
816 
817 	if (itr->pmu == NULL) {
818 		PyErr_SetNone(PyExc_StopIteration);
819 		return NULL;
820 	}
821 	// Create object to return.
822 	ppmu = PyObject_New(struct pyrf_pmu, &pyrf_pmu__type);
823 	if (ppmu) {
824 		ppmu->pmu = itr->pmu;
825 		// Advance iterator.
826 		itr->pmu = perf_pmus__scan(itr->pmu);
827 	}
828 	return (PyObject *)ppmu;
829 }
830 
831 /** The python type for the PMU iterator. */
832 static PyTypeObject pyrf_pmu_iterator__type = {
833 	PyVarObject_HEAD_INIT(NULL, 0)
834 	.tp_name = "pmus.iterator",
835 	.tp_doc = "Iterator for the pmus string sequence.",
836 	.tp_basicsize = sizeof(struct pyrf_pmu_iterator),
837 	.tp_itemsize = 0,
838 	.tp_flags = Py_TPFLAGS_DEFAULT,
839 	.tp_new = pyrf_pmu_iterator__new,
840 	.tp_dealloc = (destructor) pyrf_pmu_iterator__dealloc,
841 	.tp_iter = pyrf_pmu_iterator__iter,
842 	.tp_iternext = pyrf_pmu_iterator__iternext,
843 };
844 
pyrf_pmu_iterator__setup_types(void)845 static int pyrf_pmu_iterator__setup_types(void)
846 {
847 	return PyType_Ready(&pyrf_pmu_iterator__type);
848 }
849 
pyrf__pmus(PyObject * self,PyObject * args)850 static PyObject *pyrf__pmus(PyObject *self, PyObject *args)
851 {
852 	// Calling the class creates an instance of the iterator.
853 	return PyObject_CallObject((PyObject *) &pyrf_pmu_iterator__type, /*args=*/NULL);
854 }
855 
856 struct pyrf_counts_values {
857 	PyObject_HEAD
858 
859 	struct perf_counts_values values;
860 };
861 
862 static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object.");
863 
pyrf_counts_values__delete(struct pyrf_counts_values * pcounts_values)864 static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values)
865 {
866 	Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values);
867 }
868 
869 #define counts_values_member_def(member, ptype, help) \
870 	{ #member, ptype, \
871 	  offsetof(struct pyrf_counts_values, values.member), \
872 	  0, help }
873 
874 static PyMemberDef pyrf_counts_values_members[] = {
875 	counts_values_member_def(val, T_ULONG, "Value of event"),
876 	counts_values_member_def(ena, T_ULONG, "Time for which enabled"),
877 	counts_values_member_def(run, T_ULONG, "Time for which running"),
878 	counts_values_member_def(id, T_ULONG, "Unique ID for an event"),
879 	counts_values_member_def(lost, T_ULONG, "Num of lost samples"),
880 	{ .name = NULL, },
881 };
882 
pyrf_counts_values_get_values(struct pyrf_counts_values * self,void * closure)883 static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure)
884 {
885 	PyObject *vals = PyList_New(5);
886 
887 	if (!vals)
888 		return NULL;
889 	for (int i = 0; i < 5; i++)
890 		PyList_SetItem(vals, i, PyLong_FromLong(self->values.values[i]));
891 
892 	return vals;
893 }
894 
pyrf_counts_values_set_values(struct pyrf_counts_values * self,PyObject * list,void * closure)895 static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list,
896 					 void *closure)
897 {
898 	Py_ssize_t size;
899 	PyObject *item = NULL;
900 
901 	if (!PyList_Check(list)) {
902 		PyErr_SetString(PyExc_TypeError, "Value assigned must be a list");
903 		return -1;
904 	}
905 
906 	size = PyList_Size(list);
907 	for (Py_ssize_t i = 0; i < size; i++) {
908 		item = PyList_GetItem(list, i);
909 		if (!PyLong_Check(item)) {
910 			PyErr_SetString(PyExc_TypeError, "List members should be numbers");
911 			return -1;
912 		}
913 		self->values.values[i] = PyLong_AsLong(item);
914 	}
915 
916 	return 0;
917 }
918 
919 static PyGetSetDef pyrf_counts_values_getset[] = {
920 	{"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values,
921 		"Name field", NULL},
922 	{ .name = NULL, },
923 };
924 
925 static PyTypeObject pyrf_counts_values__type = {
926 	PyVarObject_HEAD_INIT(NULL, 0)
927 	.tp_name	= "perf.counts_values",
928 	.tp_basicsize	= sizeof(struct pyrf_counts_values),
929 	.tp_dealloc	= (destructor)pyrf_counts_values__delete,
930 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
931 	.tp_doc		= pyrf_counts_values__doc,
932 	.tp_members	= pyrf_counts_values_members,
933 	.tp_getset	= pyrf_counts_values_getset,
934 };
935 
pyrf_counts_values__setup_types(void)936 static int pyrf_counts_values__setup_types(void)
937 {
938 	pyrf_counts_values__type.tp_new = PyType_GenericNew;
939 	return PyType_Ready(&pyrf_counts_values__type);
940 }
941 
942 struct pyrf_evsel {
943 	PyObject_HEAD
944 
945 	struct evsel evsel;
946 };
947 
pyrf_evsel__init(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)948 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
949 			    PyObject *args, PyObject *kwargs)
950 {
951 	struct perf_event_attr attr = {
952 		.type = PERF_TYPE_HARDWARE,
953 		.config = PERF_COUNT_HW_CPU_CYCLES,
954 		.sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
955 	};
956 	static char *kwlist[] = {
957 		"type",
958 		"config",
959 		"sample_freq",
960 		"sample_period",
961 		"sample_type",
962 		"read_format",
963 		"disabled",
964 		"inherit",
965 		"pinned",
966 		"exclusive",
967 		"exclude_user",
968 		"exclude_kernel",
969 		"exclude_hv",
970 		"exclude_idle",
971 		"mmap",
972 		"context_switch",
973 		"comm",
974 		"freq",
975 		"inherit_stat",
976 		"enable_on_exec",
977 		"task",
978 		"watermark",
979 		"precise_ip",
980 		"mmap_data",
981 		"sample_id_all",
982 		"wakeup_events",
983 		"bp_type",
984 		"bp_addr",
985 		"bp_len",
986 		 NULL
987 	};
988 	u64 sample_period = 0;
989 	u32 disabled = 0,
990 	    inherit = 0,
991 	    pinned = 0,
992 	    exclusive = 0,
993 	    exclude_user = 0,
994 	    exclude_kernel = 0,
995 	    exclude_hv = 0,
996 	    exclude_idle = 0,
997 	    mmap = 0,
998 	    context_switch = 0,
999 	    comm = 0,
1000 	    freq = 1,
1001 	    inherit_stat = 0,
1002 	    enable_on_exec = 0,
1003 	    task = 0,
1004 	    watermark = 0,
1005 	    precise_ip = 0,
1006 	    mmap_data = 0,
1007 	    sample_id_all = 1;
1008 	int idx = 0;
1009 
1010 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
1011 					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
1012 					 &attr.type, &attr.config, &attr.sample_freq,
1013 					 &sample_period, &attr.sample_type,
1014 					 &attr.read_format, &disabled, &inherit,
1015 					 &pinned, &exclusive, &exclude_user,
1016 					 &exclude_kernel, &exclude_hv, &exclude_idle,
1017 					 &mmap, &context_switch, &comm, &freq, &inherit_stat,
1018 					 &enable_on_exec, &task, &watermark,
1019 					 &precise_ip, &mmap_data, &sample_id_all,
1020 					 &attr.wakeup_events, &attr.bp_type,
1021 					 &attr.bp_addr, &attr.bp_len, &idx))
1022 		return -1;
1023 
1024 	/* union... */
1025 	if (sample_period != 0) {
1026 		if (attr.sample_freq != 0)
1027 			return -1; /* FIXME: throw right exception */
1028 		attr.sample_period = sample_period;
1029 	}
1030 
1031 	/* Bitfields */
1032 	attr.disabled	    = disabled;
1033 	attr.inherit	    = inherit;
1034 	attr.pinned	    = pinned;
1035 	attr.exclusive	    = exclusive;
1036 	attr.exclude_user   = exclude_user;
1037 	attr.exclude_kernel = exclude_kernel;
1038 	attr.exclude_hv	    = exclude_hv;
1039 	attr.exclude_idle   = exclude_idle;
1040 	attr.mmap	    = mmap;
1041 	attr.context_switch = context_switch;
1042 	attr.comm	    = comm;
1043 	attr.freq	    = freq;
1044 	attr.inherit_stat   = inherit_stat;
1045 	attr.enable_on_exec = enable_on_exec;
1046 	attr.task	    = task;
1047 	attr.watermark	    = watermark;
1048 	attr.precise_ip	    = precise_ip;
1049 	attr.mmap_data	    = mmap_data;
1050 	attr.sample_id_all  = sample_id_all;
1051 	attr.size	    = sizeof(attr);
1052 
1053 	evsel__init(&pevsel->evsel, &attr, idx);
1054 	return 0;
1055 }
1056 
pyrf_evsel__delete(struct pyrf_evsel * pevsel)1057 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
1058 {
1059 	evsel__exit(&pevsel->evsel);
1060 	Py_TYPE(pevsel)->tp_free((PyObject*)pevsel);
1061 }
1062 
pyrf_evsel__open(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)1063 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
1064 				  PyObject *args, PyObject *kwargs)
1065 {
1066 	struct evsel *evsel = &pevsel->evsel;
1067 	struct perf_cpu_map *cpus = NULL;
1068 	struct perf_thread_map *threads = NULL;
1069 	PyObject *pcpus = NULL, *pthreads = NULL;
1070 	int group = 0, inherit = 0;
1071 	static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
1072 
1073 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
1074 					 &pcpus, &pthreads, &group, &inherit))
1075 		return NULL;
1076 
1077 	if (pthreads != NULL)
1078 		threads = ((struct pyrf_thread_map *)pthreads)->threads;
1079 
1080 	if (pcpus != NULL)
1081 		cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
1082 
1083 	evsel->core.attr.inherit = inherit;
1084 	/*
1085 	 * This will group just the fds for this single evsel, to group
1086 	 * multiple events, use evlist.open().
1087 	 */
1088 	if (evsel__open(evsel, cpus, threads) < 0) {
1089 		PyErr_SetFromErrno(PyExc_OSError);
1090 		return NULL;
1091 	}
1092 
1093 	Py_INCREF(Py_None);
1094 	return Py_None;
1095 }
1096 
pyrf_evsel__cpus(struct pyrf_evsel * pevsel)1097 static PyObject *pyrf_evsel__cpus(struct pyrf_evsel *pevsel)
1098 {
1099 	struct pyrf_cpu_map *pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type);
1100 
1101 	if (pcpu_map)
1102 		pcpu_map->cpus = perf_cpu_map__get(pevsel->evsel.core.cpus);
1103 
1104 	return (PyObject *)pcpu_map;
1105 }
1106 
pyrf_evsel__threads(struct pyrf_evsel * pevsel)1107 static PyObject *pyrf_evsel__threads(struct pyrf_evsel *pevsel)
1108 {
1109 	struct pyrf_thread_map *pthread_map =
1110 		PyObject_New(struct pyrf_thread_map, &pyrf_thread_map__type);
1111 
1112 	if (pthread_map)
1113 		pthread_map->threads = perf_thread_map__get(pevsel->evsel.core.threads);
1114 
1115 	return (PyObject *)pthread_map;
1116 }
1117 
1118 /*
1119  * Ensure evsel's counts and prev_raw_counts are allocated, the latter
1120  * used by tool PMUs to compute the cumulative count as expected by
1121  * stat's process_counter_values.
1122  */
evsel__ensure_counts(struct evsel * evsel)1123 static int evsel__ensure_counts(struct evsel *evsel)
1124 {
1125 	int nthreads, ncpus;
1126 
1127 	if (evsel->counts != NULL)
1128 		return 0;
1129 
1130 	nthreads = perf_thread_map__nr(evsel->core.threads);
1131 	ncpus = perf_cpu_map__nr(evsel->core.cpus);
1132 
1133 	evsel->counts = perf_counts__new(ncpus, nthreads);
1134 	if (evsel->counts == NULL)
1135 		return -ENOMEM;
1136 
1137 	evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads);
1138 	if (evsel->prev_raw_counts == NULL)
1139 		return -ENOMEM;
1140 
1141 	return 0;
1142 }
1143 
pyrf_evsel__read(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)1144 static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel,
1145 				  PyObject *args, PyObject *kwargs)
1146 {
1147 	struct evsel *evsel = &pevsel->evsel;
1148 	int cpu = 0, cpu_idx, thread = 0, thread_idx;
1149 	struct perf_counts_values *old_count, *new_count;
1150 	struct pyrf_counts_values *count_values = PyObject_New(struct pyrf_counts_values,
1151 							       &pyrf_counts_values__type);
1152 
1153 	if (!count_values)
1154 		return NULL;
1155 
1156 	if (!PyArg_ParseTuple(args, "ii", &cpu, &thread))
1157 		return NULL;
1158 
1159 	cpu_idx = perf_cpu_map__idx(evsel->core.cpus, (struct perf_cpu){.cpu = cpu});
1160 	if (cpu_idx < 0) {
1161 		PyErr_Format(PyExc_TypeError, "CPU %d is not part of evsel's CPUs", cpu);
1162 		return NULL;
1163 	}
1164 	thread_idx = perf_thread_map__idx(evsel->core.threads, thread);
1165 	if (thread_idx < 0) {
1166 		PyErr_Format(PyExc_TypeError, "Thread %d is not part of evsel's threads",
1167 			     thread);
1168 		return NULL;
1169 	}
1170 
1171 	if (evsel__ensure_counts(evsel))
1172 		return PyErr_NoMemory();
1173 
1174 	/* Set up pointers to the old and newly read counter values. */
1175 	old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx);
1176 	new_count = perf_counts(evsel->counts, cpu_idx, thread_idx);
1177 	/* Update the value in evsel->counts. */
1178 	evsel__read_counter(evsel, cpu_idx, thread_idx);
1179 	/* Copy the value and turn it into the delta from old_count. */
1180 	count_values->values = *new_count;
1181 	count_values->values.val -= old_count->val;
1182 	count_values->values.ena -= old_count->ena;
1183 	count_values->values.run -= old_count->run;
1184 	/* Save the new count over the old_count for the next read. */
1185 	*old_count = *new_count;
1186 	return (PyObject *)count_values;
1187 }
1188 
pyrf_evsel__str(PyObject * self)1189 static PyObject *pyrf_evsel__str(PyObject *self)
1190 {
1191 	struct pyrf_evsel *pevsel = (void *)self;
1192 	struct evsel *evsel = &pevsel->evsel;
1193 
1194 	return PyUnicode_FromFormat("evsel(%s/%s/)", evsel__pmu_name(evsel), evsel__name(evsel));
1195 }
1196 
1197 static PyMethodDef pyrf_evsel__methods[] = {
1198 	{
1199 		.ml_name  = "open",
1200 		.ml_meth  = (PyCFunction)pyrf_evsel__open,
1201 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1202 		.ml_doc	  = PyDoc_STR("open the event selector file descriptor table.")
1203 	},
1204 	{
1205 		.ml_name  = "cpus",
1206 		.ml_meth  = (PyCFunction)pyrf_evsel__cpus,
1207 		.ml_flags = METH_NOARGS,
1208 		.ml_doc	  = PyDoc_STR("CPUs the event is to be used with.")
1209 	},
1210 	{
1211 		.ml_name  = "threads",
1212 		.ml_meth  = (PyCFunction)pyrf_evsel__threads,
1213 		.ml_flags = METH_NOARGS,
1214 		.ml_doc	  = PyDoc_STR("threads the event is to be used with.")
1215 	},
1216 	{
1217 		.ml_name  = "read",
1218 		.ml_meth  = (PyCFunction)pyrf_evsel__read,
1219 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1220 		.ml_doc	  = PyDoc_STR("read counters")
1221 	},
1222 	{ .ml_name = NULL, }
1223 };
1224 
1225 #define evsel_member_def(member, ptype, help) \
1226 	{ #member, ptype, \
1227 	  offsetof(struct pyrf_evsel, evsel.member), \
1228 	  0, help }
1229 
1230 #define evsel_attr_member_def(member, ptype, help) \
1231 	{ #member, ptype, \
1232 	  offsetof(struct pyrf_evsel, evsel.core.attr.member), \
1233 	  0, help }
1234 
1235 static PyMemberDef pyrf_evsel__members[] = {
1236 	evsel_member_def(tracking, T_BOOL, "tracking event."),
1237 	evsel_attr_member_def(type, T_UINT, "attribute type."),
1238 	evsel_attr_member_def(size, T_UINT, "attribute size."),
1239 	evsel_attr_member_def(config, T_ULONGLONG, "attribute config."),
1240 	evsel_attr_member_def(sample_period, T_ULONGLONG, "attribute sample_period."),
1241 	evsel_attr_member_def(sample_type, T_ULONGLONG, "attribute sample_type."),
1242 	evsel_attr_member_def(read_format, T_ULONGLONG, "attribute read_format."),
1243 	evsel_attr_member_def(wakeup_events, T_UINT, "attribute wakeup_events."),
1244 	{ .name = NULL, },
1245 };
1246 
1247 static const char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
1248 
1249 static PyTypeObject pyrf_evsel__type = {
1250 	PyVarObject_HEAD_INIT(NULL, 0)
1251 	.tp_name	= "perf.evsel",
1252 	.tp_basicsize	= sizeof(struct pyrf_evsel),
1253 	.tp_dealloc	= (destructor)pyrf_evsel__delete,
1254 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1255 	.tp_doc		= pyrf_evsel__doc,
1256 	.tp_members	= pyrf_evsel__members,
1257 	.tp_methods	= pyrf_evsel__methods,
1258 	.tp_init	= (initproc)pyrf_evsel__init,
1259 	.tp_str         = pyrf_evsel__str,
1260 	.tp_repr        = pyrf_evsel__str,
1261 };
1262 
pyrf_evsel__setup_types(void)1263 static int pyrf_evsel__setup_types(void)
1264 {
1265 	pyrf_evsel__type.tp_new = PyType_GenericNew;
1266 	return PyType_Ready(&pyrf_evsel__type);
1267 }
1268 
1269 struct pyrf_evlist {
1270 	PyObject_HEAD
1271 
1272 	struct evlist evlist;
1273 };
1274 
pyrf_evlist__init(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __maybe_unused)1275 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
1276 			     PyObject *args, PyObject *kwargs __maybe_unused)
1277 {
1278 	PyObject *pcpus = NULL, *pthreads = NULL;
1279 	struct perf_cpu_map *cpus;
1280 	struct perf_thread_map *threads;
1281 
1282 	if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
1283 		return -1;
1284 
1285 	threads = ((struct pyrf_thread_map *)pthreads)->threads;
1286 	cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
1287 	evlist__init(&pevlist->evlist, cpus, threads);
1288 	return 0;
1289 }
1290 
pyrf_evlist__delete(struct pyrf_evlist * pevlist)1291 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
1292 {
1293 	evlist__exit(&pevlist->evlist);
1294 	Py_TYPE(pevlist)->tp_free((PyObject*)pevlist);
1295 }
1296 
pyrf_evlist__all_cpus(struct pyrf_evlist * pevlist)1297 static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist)
1298 {
1299 	struct pyrf_cpu_map *pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type);
1300 
1301 	if (pcpu_map)
1302 		pcpu_map->cpus = perf_cpu_map__get(pevlist->evlist.core.all_cpus);
1303 
1304 	return (PyObject *)pcpu_map;
1305 }
1306 
pyrf_evlist__metrics(struct pyrf_evlist * pevlist)1307 static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist)
1308 {
1309 	PyObject *list = PyList_New(/*len=*/0);
1310 	struct rb_node *node;
1311 
1312 	if (!list)
1313 		return NULL;
1314 
1315 	for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
1316 	     node = rb_next(node)) {
1317 		struct metric_event *me = container_of(node, struct metric_event, nd);
1318 		struct list_head *pos;
1319 
1320 		list_for_each(pos, &me->head) {
1321 			struct metric_expr *expr = container_of(pos, struct metric_expr, nd);
1322 			PyObject *str = PyUnicode_FromString(expr->metric_name);
1323 
1324 			if (!str || PyList_Append(list, str) != 0) {
1325 				Py_DECREF(list);
1326 				return NULL;
1327 			}
1328 			Py_DECREF(str);
1329 		}
1330 	}
1331 	return list;
1332 }
1333 
prepare_metric(const struct metric_expr * mexp,const struct evsel * evsel,struct expr_parse_ctx * pctx,int cpu_idx,int thread_idx)1334 static int prepare_metric(const struct metric_expr *mexp,
1335 			  const struct evsel *evsel,
1336 			  struct expr_parse_ctx *pctx,
1337 			  int cpu_idx, int thread_idx)
1338 {
1339 	struct evsel * const *metric_events = mexp->metric_events;
1340 	struct metric_ref *metric_refs = mexp->metric_refs;
1341 
1342 	for (int i = 0; metric_events[i]; i++) {
1343 		char *n = strdup(evsel__metric_id(metric_events[i]));
1344 		double val, ena, run;
1345 		int source_count = evsel__source_count(metric_events[i]);
1346 		int ret;
1347 		struct perf_counts_values *old_count, *new_count;
1348 
1349 		if (!n)
1350 			return -ENOMEM;
1351 
1352 		if (source_count == 0)
1353 			source_count = 1;
1354 
1355 		ret = evsel__ensure_counts(metric_events[i]);
1356 		if (ret)
1357 			return ret;
1358 
1359 		/* Set up pointers to the old and newly read counter values. */
1360 		old_count = perf_counts(metric_events[i]->prev_raw_counts, cpu_idx, thread_idx);
1361 		new_count = perf_counts(metric_events[i]->counts, cpu_idx, thread_idx);
1362 		/* Update the value in metric_events[i]->counts. */
1363 		evsel__read_counter(metric_events[i], cpu_idx, thread_idx);
1364 
1365 		val = new_count->val - old_count->val;
1366 		ena = new_count->ena - old_count->ena;
1367 		run = new_count->run - old_count->run;
1368 
1369 		if (ena != run && run != 0)
1370 			val = val * ena / run;
1371 		ret = expr__add_id_val_source_count(pctx, n, val, source_count);
1372 		if (ret)
1373 			return ret;
1374 	}
1375 
1376 	for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) {
1377 		int ret = expr__add_ref(pctx, &metric_refs[i]);
1378 
1379 		if (ret)
1380 			return ret;
1381 	}
1382 
1383 	return 0;
1384 }
1385 
pyrf_evlist__compute_metric(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1386 static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist,
1387 					     PyObject *args, PyObject *kwargs)
1388 {
1389 	int ret, cpu = 0, cpu_idx = 0, thread = 0, thread_idx = 0;
1390 	const char *metric;
1391 	struct rb_node *node;
1392 	struct metric_expr *mexp = NULL;
1393 	struct expr_parse_ctx *pctx;
1394 	double result = 0;
1395 
1396 	if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread))
1397 		return NULL;
1398 
1399 	for (node = rb_first_cached(&pevlist->evlist.metric_events.entries);
1400 	     mexp == NULL && node;
1401 	     node = rb_next(node)) {
1402 		struct metric_event *me = container_of(node, struct metric_event, nd);
1403 		struct list_head *pos;
1404 
1405 		list_for_each(pos, &me->head) {
1406 			struct metric_expr *e = container_of(pos, struct metric_expr, nd);
1407 
1408 			if (strcmp(e->metric_name, metric))
1409 				continue;
1410 
1411 			if (e->metric_events[0] == NULL)
1412 				continue;
1413 
1414 			cpu_idx = perf_cpu_map__idx(e->metric_events[0]->core.cpus,
1415 						    (struct perf_cpu){.cpu = cpu});
1416 			if (cpu_idx < 0)
1417 				continue;
1418 
1419 			thread_idx = perf_thread_map__idx(e->metric_events[0]->core.threads,
1420 							  thread);
1421 			if (thread_idx < 0)
1422 				continue;
1423 
1424 			mexp = e;
1425 			break;
1426 		}
1427 	}
1428 	if (!mexp) {
1429 		PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'",
1430 			     metric, cpu, thread);
1431 		return NULL;
1432 	}
1433 
1434 	pctx = expr__ctx_new();
1435 	if (!pctx)
1436 		return PyErr_NoMemory();
1437 
1438 	ret = prepare_metric(mexp, mexp->metric_events[0], pctx, cpu_idx, thread_idx);
1439 	if (ret) {
1440 		expr__ctx_free(pctx);
1441 		errno = -ret;
1442 		PyErr_SetFromErrno(PyExc_OSError);
1443 		return NULL;
1444 	}
1445 	if (expr__parse(&result, pctx, mexp->metric_expr))
1446 		result = 0.0;
1447 
1448 	expr__ctx_free(pctx);
1449 	return PyFloat_FromDouble(result);
1450 }
1451 
pyrf_evlist__mmap(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1452 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
1453 				   PyObject *args, PyObject *kwargs)
1454 {
1455 	struct evlist *evlist = &pevlist->evlist;
1456 	static char *kwlist[] = { "pages", "overwrite", NULL };
1457 	int pages = 128, overwrite = false;
1458 
1459 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
1460 					 &pages, &overwrite))
1461 		return NULL;
1462 
1463 	if (evlist__mmap(evlist, pages) < 0) {
1464 		PyErr_SetFromErrno(PyExc_OSError);
1465 		return NULL;
1466 	}
1467 
1468 	Py_INCREF(Py_None);
1469 	return Py_None;
1470 }
1471 
pyrf_evlist__poll(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1472 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
1473 				   PyObject *args, PyObject *kwargs)
1474 {
1475 	struct evlist *evlist = &pevlist->evlist;
1476 	static char *kwlist[] = { "timeout", NULL };
1477 	int timeout = -1, n;
1478 
1479 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
1480 		return NULL;
1481 
1482 	n = evlist__poll(evlist, timeout);
1483 	if (n < 0) {
1484 		PyErr_SetFromErrno(PyExc_OSError);
1485 		return NULL;
1486 	}
1487 
1488 	return Py_BuildValue("i", n);
1489 }
1490 
pyrf_evlist__get_pollfd(struct pyrf_evlist * pevlist,PyObject * args __maybe_unused,PyObject * kwargs __maybe_unused)1491 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
1492 					 PyObject *args __maybe_unused,
1493 					 PyObject *kwargs __maybe_unused)
1494 {
1495 	struct evlist *evlist = &pevlist->evlist;
1496         PyObject *list = PyList_New(0);
1497 	int i;
1498 
1499 	for (i = 0; i < evlist->core.pollfd.nr; ++i) {
1500 		PyObject *file;
1501 		file = PyFile_FromFd(evlist->core.pollfd.entries[i].fd, "perf", "r", -1,
1502 				     NULL, NULL, NULL, 0);
1503 		if (file == NULL)
1504 			goto free_list;
1505 
1506 		if (PyList_Append(list, file) != 0) {
1507 			Py_DECREF(file);
1508 			goto free_list;
1509 		}
1510 
1511 		Py_DECREF(file);
1512 	}
1513 
1514 	return list;
1515 free_list:
1516 	return PyErr_NoMemory();
1517 }
1518 
1519 
pyrf_evlist__add(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __maybe_unused)1520 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
1521 				  PyObject *args,
1522 				  PyObject *kwargs __maybe_unused)
1523 {
1524 	struct evlist *evlist = &pevlist->evlist;
1525 	PyObject *pevsel;
1526 	struct evsel *evsel;
1527 
1528 	if (!PyArg_ParseTuple(args, "O", &pevsel))
1529 		return NULL;
1530 
1531 	Py_INCREF(pevsel);
1532 	evsel = &((struct pyrf_evsel *)pevsel)->evsel;
1533 	evsel->core.idx = evlist->core.nr_entries;
1534 	evlist__add(evlist, evsel);
1535 
1536 	return Py_BuildValue("i", evlist->core.nr_entries);
1537 }
1538 
get_md(struct evlist * evlist,int cpu)1539 static struct mmap *get_md(struct evlist *evlist, int cpu)
1540 {
1541 	int i;
1542 
1543 	for (i = 0; i < evlist->core.nr_mmaps; i++) {
1544 		struct mmap *md = &evlist->mmap[i];
1545 
1546 		if (md->core.cpu.cpu == cpu)
1547 			return md;
1548 	}
1549 
1550 	return NULL;
1551 }
1552 
pyrf_evlist__read_on_cpu(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1553 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
1554 					  PyObject *args, PyObject *kwargs)
1555 {
1556 	struct evlist *evlist = &pevlist->evlist;
1557 	union perf_event *event;
1558 	int sample_id_all = 1, cpu;
1559 	static char *kwlist[] = { "cpu", "sample_id_all", NULL };
1560 	struct mmap *md;
1561 	int err;
1562 
1563 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
1564 					 &cpu, &sample_id_all))
1565 		return NULL;
1566 
1567 	md = get_md(evlist, cpu);
1568 	if (!md) {
1569 		PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu);
1570 		return NULL;
1571 	}
1572 
1573 	if (perf_mmap__read_init(&md->core) < 0)
1574 		goto end;
1575 
1576 	event = perf_mmap__read_event(&md->core);
1577 	if (event != NULL) {
1578 		PyObject *pyevent = pyrf_event__new(event);
1579 		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
1580 		struct evsel *evsel;
1581 
1582 		if (pyevent == NULL)
1583 			return PyErr_NoMemory();
1584 
1585 		evsel = evlist__event2evsel(evlist, event);
1586 		if (!evsel) {
1587 			Py_DECREF(pyevent);
1588 			Py_INCREF(Py_None);
1589 			return Py_None;
1590 		}
1591 
1592 		pevent->evsel = evsel;
1593 
1594 		perf_mmap__consume(&md->core);
1595 
1596 		err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample);
1597 		if (err) {
1598 			Py_DECREF(pyevent);
1599 			return PyErr_Format(PyExc_OSError,
1600 					    "perf: can't parse sample, err=%d", err);
1601 		}
1602 
1603 		return pyevent;
1604 	}
1605 end:
1606 	Py_INCREF(Py_None);
1607 	return Py_None;
1608 }
1609 
pyrf_evlist__open(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)1610 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist,
1611 				   PyObject *args, PyObject *kwargs)
1612 {
1613 	struct evlist *evlist = &pevlist->evlist;
1614 
1615 	if (evlist__open(evlist) < 0) {
1616 		PyErr_SetFromErrno(PyExc_OSError);
1617 		return NULL;
1618 	}
1619 
1620 	Py_INCREF(Py_None);
1621 	return Py_None;
1622 }
1623 
pyrf_evlist__close(struct pyrf_evlist * pevlist)1624 static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist)
1625 {
1626 	struct evlist *evlist = &pevlist->evlist;
1627 
1628 	evlist__close(evlist);
1629 
1630 	Py_INCREF(Py_None);
1631 	return Py_None;
1632 }
1633 
pyrf_evlist__config(struct pyrf_evlist * pevlist)1634 static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist)
1635 {
1636 	struct record_opts opts = {
1637 		.sample_time	     = true,
1638 		.mmap_pages	     = UINT_MAX,
1639 		.user_freq	     = UINT_MAX,
1640 		.user_interval	     = ULLONG_MAX,
1641 		.freq		     = 4000,
1642 		.target		     = {
1643 			.uses_mmap   = true,
1644 			.default_per_cpu = true,
1645 		},
1646 		.nr_threads_synthesize = 1,
1647 		.ctl_fd              = -1,
1648 		.ctl_fd_ack          = -1,
1649 		.no_buffering        = true,
1650 		.no_inherit          = true,
1651 	};
1652 	struct evlist *evlist = &pevlist->evlist;
1653 
1654 	evlist__config(evlist, &opts, &callchain_param);
1655 	Py_INCREF(Py_None);
1656 	return Py_None;
1657 }
1658 
pyrf_evlist__disable(struct pyrf_evlist * pevlist)1659 static PyObject *pyrf_evlist__disable(struct pyrf_evlist *pevlist)
1660 {
1661 	evlist__disable(&pevlist->evlist);
1662 	Py_INCREF(Py_None);
1663 	return Py_None;
1664 }
1665 
pyrf_evlist__enable(struct pyrf_evlist * pevlist)1666 static PyObject *pyrf_evlist__enable(struct pyrf_evlist *pevlist)
1667 {
1668 	evlist__enable(&pevlist->evlist);
1669 	Py_INCREF(Py_None);
1670 	return Py_None;
1671 }
1672 
1673 static PyMethodDef pyrf_evlist__methods[] = {
1674 	{
1675 		.ml_name  = "all_cpus",
1676 		.ml_meth  = (PyCFunction)pyrf_evlist__all_cpus,
1677 		.ml_flags = METH_NOARGS,
1678 		.ml_doc	  = PyDoc_STR("CPU map union of all evsel CPU maps.")
1679 	},
1680 	{
1681 		.ml_name  = "metrics",
1682 		.ml_meth  = (PyCFunction)pyrf_evlist__metrics,
1683 		.ml_flags = METH_NOARGS,
1684 		.ml_doc	  = PyDoc_STR("List of metric names within the evlist.")
1685 	},
1686 	{
1687 		.ml_name  = "compute_metric",
1688 		.ml_meth  = (PyCFunction)pyrf_evlist__compute_metric,
1689 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1690 		.ml_doc	  = PyDoc_STR("compute metric for given name, cpu and thread")
1691 	},
1692 	{
1693 		.ml_name  = "mmap",
1694 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
1695 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1696 		.ml_doc	  = PyDoc_STR("mmap the file descriptor table.")
1697 	},
1698 	{
1699 		.ml_name  = "open",
1700 		.ml_meth  = (PyCFunction)pyrf_evlist__open,
1701 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1702 		.ml_doc	  = PyDoc_STR("open the file descriptors.")
1703 	},
1704 	{
1705 		.ml_name  = "close",
1706 		.ml_meth  = (PyCFunction)pyrf_evlist__close,
1707 		.ml_flags = METH_NOARGS,
1708 		.ml_doc	  = PyDoc_STR("close the file descriptors.")
1709 	},
1710 	{
1711 		.ml_name  = "poll",
1712 		.ml_meth  = (PyCFunction)pyrf_evlist__poll,
1713 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1714 		.ml_doc	  = PyDoc_STR("poll the file descriptor table.")
1715 	},
1716 	{
1717 		.ml_name  = "get_pollfd",
1718 		.ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
1719 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1720 		.ml_doc	  = PyDoc_STR("get the poll file descriptor table.")
1721 	},
1722 	{
1723 		.ml_name  = "add",
1724 		.ml_meth  = (PyCFunction)pyrf_evlist__add,
1725 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1726 		.ml_doc	  = PyDoc_STR("adds an event selector to the list.")
1727 	},
1728 	{
1729 		.ml_name  = "read_on_cpu",
1730 		.ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
1731 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
1732 		.ml_doc	  = PyDoc_STR("reads an event.")
1733 	},
1734 	{
1735 		.ml_name  = "config",
1736 		.ml_meth  = (PyCFunction)pyrf_evlist__config,
1737 		.ml_flags = METH_NOARGS,
1738 		.ml_doc	  = PyDoc_STR("Apply default record options to the evlist.")
1739 	},
1740 	{
1741 		.ml_name  = "disable",
1742 		.ml_meth  = (PyCFunction)pyrf_evlist__disable,
1743 		.ml_flags = METH_NOARGS,
1744 		.ml_doc	  = PyDoc_STR("Disable the evsels in the evlist.")
1745 	},
1746 	{
1747 		.ml_name  = "enable",
1748 		.ml_meth  = (PyCFunction)pyrf_evlist__enable,
1749 		.ml_flags = METH_NOARGS,
1750 		.ml_doc	  = PyDoc_STR("Enable the evsels in the evlist.")
1751 	},
1752 	{ .ml_name = NULL, }
1753 };
1754 
pyrf_evlist__length(PyObject * obj)1755 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
1756 {
1757 	struct pyrf_evlist *pevlist = (void *)obj;
1758 
1759 	return pevlist->evlist.core.nr_entries;
1760 }
1761 
pyrf_evlist__item(PyObject * obj,Py_ssize_t i)1762 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
1763 {
1764 	struct pyrf_evlist *pevlist = (void *)obj;
1765 	struct evsel *pos;
1766 
1767 	if (i >= pevlist->evlist.core.nr_entries) {
1768 		PyErr_SetString(PyExc_IndexError, "Index out of range");
1769 		return NULL;
1770 	}
1771 
1772 	evlist__for_each_entry(&pevlist->evlist, pos) {
1773 		if (i-- == 0)
1774 			break;
1775 	}
1776 
1777 	return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
1778 }
1779 
pyrf_evlist__str(PyObject * self)1780 static PyObject *pyrf_evlist__str(PyObject *self)
1781 {
1782 	struct pyrf_evlist *pevlist = (void *)self;
1783 	struct evsel *pos;
1784 	struct strbuf sb = STRBUF_INIT;
1785 	bool first = true;
1786 	PyObject *result;
1787 
1788 	strbuf_addstr(&sb, "evlist([");
1789 	evlist__for_each_entry(&pevlist->evlist, pos) {
1790 		if (!first)
1791 			strbuf_addch(&sb, ',');
1792 		if (!pos->pmu)
1793 			strbuf_addstr(&sb, evsel__name(pos));
1794 		else
1795 			strbuf_addf(&sb, "%s/%s/", pos->pmu->name, evsel__name(pos));
1796 		first = false;
1797 	}
1798 	strbuf_addstr(&sb, "])");
1799 	result = PyUnicode_FromString(sb.buf);
1800 	strbuf_release(&sb);
1801 	return result;
1802 }
1803 
1804 static PySequenceMethods pyrf_evlist__sequence_methods = {
1805 	.sq_length = pyrf_evlist__length,
1806 	.sq_item   = pyrf_evlist__item,
1807 };
1808 
1809 static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
1810 
1811 static PyTypeObject pyrf_evlist__type = {
1812 	PyVarObject_HEAD_INIT(NULL, 0)
1813 	.tp_name	= "perf.evlist",
1814 	.tp_basicsize	= sizeof(struct pyrf_evlist),
1815 	.tp_dealloc	= (destructor)pyrf_evlist__delete,
1816 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1817 	.tp_as_sequence	= &pyrf_evlist__sequence_methods,
1818 	.tp_doc		= pyrf_evlist__doc,
1819 	.tp_methods	= pyrf_evlist__methods,
1820 	.tp_init	= (initproc)pyrf_evlist__init,
1821 	.tp_repr        = pyrf_evlist__str,
1822 	.tp_str         = pyrf_evlist__str,
1823 };
1824 
pyrf_evlist__setup_types(void)1825 static int pyrf_evlist__setup_types(void)
1826 {
1827 	pyrf_evlist__type.tp_new = PyType_GenericNew;
1828 	return PyType_Ready(&pyrf_evlist__type);
1829 }
1830 
1831 #define PERF_CONST(name) { #name, PERF_##name }
1832 
1833 struct perf_constant {
1834 	const char *name;
1835 	int	    value;
1836 };
1837 
1838 static const struct perf_constant perf__constants[] = {
1839 	PERF_CONST(TYPE_HARDWARE),
1840 	PERF_CONST(TYPE_SOFTWARE),
1841 	PERF_CONST(TYPE_TRACEPOINT),
1842 	PERF_CONST(TYPE_HW_CACHE),
1843 	PERF_CONST(TYPE_RAW),
1844 	PERF_CONST(TYPE_BREAKPOINT),
1845 
1846 	PERF_CONST(COUNT_HW_CPU_CYCLES),
1847 	PERF_CONST(COUNT_HW_INSTRUCTIONS),
1848 	PERF_CONST(COUNT_HW_CACHE_REFERENCES),
1849 	PERF_CONST(COUNT_HW_CACHE_MISSES),
1850 	PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS),
1851 	PERF_CONST(COUNT_HW_BRANCH_MISSES),
1852 	PERF_CONST(COUNT_HW_BUS_CYCLES),
1853 	PERF_CONST(COUNT_HW_CACHE_L1D),
1854 	PERF_CONST(COUNT_HW_CACHE_L1I),
1855 	PERF_CONST(COUNT_HW_CACHE_LL),
1856 	PERF_CONST(COUNT_HW_CACHE_DTLB),
1857 	PERF_CONST(COUNT_HW_CACHE_ITLB),
1858 	PERF_CONST(COUNT_HW_CACHE_BPU),
1859 	PERF_CONST(COUNT_HW_CACHE_OP_READ),
1860 	PERF_CONST(COUNT_HW_CACHE_OP_WRITE),
1861 	PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH),
1862 	PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS),
1863 	PERF_CONST(COUNT_HW_CACHE_RESULT_MISS),
1864 
1865 	PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND),
1866 	PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND),
1867 
1868 	PERF_CONST(COUNT_SW_CPU_CLOCK),
1869 	PERF_CONST(COUNT_SW_TASK_CLOCK),
1870 	PERF_CONST(COUNT_SW_PAGE_FAULTS),
1871 	PERF_CONST(COUNT_SW_CONTEXT_SWITCHES),
1872 	PERF_CONST(COUNT_SW_CPU_MIGRATIONS),
1873 	PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN),
1874 	PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ),
1875 	PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS),
1876 	PERF_CONST(COUNT_SW_EMULATION_FAULTS),
1877 	PERF_CONST(COUNT_SW_DUMMY),
1878 
1879 	PERF_CONST(SAMPLE_IP),
1880 	PERF_CONST(SAMPLE_TID),
1881 	PERF_CONST(SAMPLE_TIME),
1882 	PERF_CONST(SAMPLE_ADDR),
1883 	PERF_CONST(SAMPLE_READ),
1884 	PERF_CONST(SAMPLE_CALLCHAIN),
1885 	PERF_CONST(SAMPLE_ID),
1886 	PERF_CONST(SAMPLE_CPU),
1887 	PERF_CONST(SAMPLE_PERIOD),
1888 	PERF_CONST(SAMPLE_STREAM_ID),
1889 	PERF_CONST(SAMPLE_RAW),
1890 
1891 	PERF_CONST(FORMAT_TOTAL_TIME_ENABLED),
1892 	PERF_CONST(FORMAT_TOTAL_TIME_RUNNING),
1893 	PERF_CONST(FORMAT_ID),
1894 	PERF_CONST(FORMAT_GROUP),
1895 
1896 	PERF_CONST(RECORD_MMAP),
1897 	PERF_CONST(RECORD_LOST),
1898 	PERF_CONST(RECORD_COMM),
1899 	PERF_CONST(RECORD_EXIT),
1900 	PERF_CONST(RECORD_THROTTLE),
1901 	PERF_CONST(RECORD_UNTHROTTLE),
1902 	PERF_CONST(RECORD_FORK),
1903 	PERF_CONST(RECORD_READ),
1904 	PERF_CONST(RECORD_SAMPLE),
1905 	PERF_CONST(RECORD_MMAP2),
1906 	PERF_CONST(RECORD_AUX),
1907 	PERF_CONST(RECORD_ITRACE_START),
1908 	PERF_CONST(RECORD_LOST_SAMPLES),
1909 	PERF_CONST(RECORD_SWITCH),
1910 	PERF_CONST(RECORD_SWITCH_CPU_WIDE),
1911 
1912 	PERF_CONST(RECORD_MISC_SWITCH_OUT),
1913 	{ .name = NULL, },
1914 };
1915 
pyrf__tracepoint(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)1916 static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1917 				  PyObject *args, PyObject *kwargs)
1918 {
1919 	static char *kwlist[] = { "sys", "name", NULL };
1920 	char *sys  = NULL;
1921 	char *name = NULL;
1922 
1923 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist,
1924 					 &sys, &name))
1925 		return NULL;
1926 
1927 	return PyLong_FromLong(tp_pmu__id(sys, name));
1928 }
1929 
pyrf_evsel__from_evsel(struct evsel * evsel)1930 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel)
1931 {
1932 	struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type);
1933 
1934 	if (!pevsel)
1935 		return NULL;
1936 
1937 	memset(&pevsel->evsel, 0, sizeof(pevsel->evsel));
1938 	evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx);
1939 
1940 	evsel__clone(&pevsel->evsel, evsel);
1941 	if (evsel__is_group_leader(evsel))
1942 		evsel__set_leader(&pevsel->evsel, &pevsel->evsel);
1943 	return (PyObject *)pevsel;
1944 }
1945 
evlist__pos(struct evlist * evlist,struct evsel * evsel)1946 static int evlist__pos(struct evlist *evlist, struct evsel *evsel)
1947 {
1948 	struct evsel *pos;
1949 	int idx = 0;
1950 
1951 	evlist__for_each_entry(evlist, pos) {
1952 		if (evsel == pos)
1953 			return idx;
1954 		idx++;
1955 	}
1956 	return -1;
1957 }
1958 
evlist__at(struct evlist * evlist,int idx)1959 static struct evsel *evlist__at(struct evlist *evlist, int idx)
1960 {
1961 	struct evsel *pos;
1962 	int idx2 = 0;
1963 
1964 	evlist__for_each_entry(evlist, pos) {
1965 		if (idx == idx2)
1966 			return pos;
1967 		idx2++;
1968 	}
1969 	return NULL;
1970 }
1971 
pyrf_evlist__from_evlist(struct evlist * evlist)1972 static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist)
1973 {
1974 	struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type);
1975 	struct evsel *pos;
1976 	struct rb_node *node;
1977 
1978 	if (!pevlist)
1979 		return NULL;
1980 
1981 	memset(&pevlist->evlist, 0, sizeof(pevlist->evlist));
1982 	evlist__init(&pevlist->evlist, evlist->core.all_cpus, evlist->core.threads);
1983 	evlist__for_each_entry(evlist, pos) {
1984 		struct pyrf_evsel *pevsel = (void *)pyrf_evsel__from_evsel(pos);
1985 
1986 		evlist__add(&pevlist->evlist, &pevsel->evsel);
1987 	}
1988 	evlist__for_each_entry(&pevlist->evlist, pos) {
1989 		struct evsel *leader = evsel__leader(pos);
1990 
1991 		if (pos != leader) {
1992 			int idx = evlist__pos(evlist, leader);
1993 
1994 			if (idx >= 0)
1995 				evsel__set_leader(pos, evlist__at(&pevlist->evlist, idx));
1996 			else if (leader == NULL)
1997 				evsel__set_leader(pos, pos);
1998 		}
1999 	}
2000 	metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL,
2001 					&pevlist->evlist.metric_events,
2002 					&evlist->metric_events);
2003 	for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node;
2004 	     node = rb_next(node)) {
2005 		struct metric_event *me = container_of(node, struct metric_event, nd);
2006 		struct list_head *mpos;
2007 		int idx = evlist__pos(evlist, me->evsel);
2008 
2009 		if (idx >= 0)
2010 			me->evsel = evlist__at(&pevlist->evlist, idx);
2011 		list_for_each(mpos, &me->head) {
2012 			struct metric_expr *e = container_of(mpos, struct metric_expr, nd);
2013 
2014 			for (int j = 0; e->metric_events[j]; j++) {
2015 				idx = evlist__pos(evlist, e->metric_events[j]);
2016 				if (idx >= 0)
2017 					e->metric_events[j] = evlist__at(&pevlist->evlist, idx);
2018 			}
2019 		}
2020 	}
2021 	return (PyObject *)pevlist;
2022 }
2023 
pyrf__parse_events(PyObject * self,PyObject * args)2024 static PyObject *pyrf__parse_events(PyObject *self, PyObject *args)
2025 {
2026 	const char *input;
2027 	struct evlist evlist = {};
2028 	struct parse_events_error err;
2029 	PyObject *result;
2030 	PyObject *pcpus = NULL, *pthreads = NULL;
2031 	struct perf_cpu_map *cpus;
2032 	struct perf_thread_map *threads;
2033 
2034 	if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads))
2035 		return NULL;
2036 
2037 	threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL;
2038 	cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
2039 
2040 	parse_events_error__init(&err);
2041 	evlist__init(&evlist, cpus, threads);
2042 	if (parse_events(&evlist, input, &err)) {
2043 		parse_events_error__print(&err, input);
2044 		PyErr_SetFromErrno(PyExc_OSError);
2045 		return NULL;
2046 	}
2047 	result = pyrf_evlist__from_evlist(&evlist);
2048 	evlist__exit(&evlist);
2049 	return result;
2050 }
2051 
pyrf__parse_metrics(PyObject * self,PyObject * args)2052 static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args)
2053 {
2054 	const char *input;
2055 	struct evlist evlist = {};
2056 	PyObject *result;
2057 	PyObject *pcpus = NULL, *pthreads = NULL;
2058 	struct perf_cpu_map *cpus;
2059 	struct perf_thread_map *threads;
2060 	int ret;
2061 
2062 	if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads))
2063 		return NULL;
2064 
2065 	threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL;
2066 	cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL;
2067 
2068 	evlist__init(&evlist, cpus, threads);
2069 	ret = metricgroup__parse_groups(&evlist, /*pmu=*/"all", input,
2070 					/*metric_no_group=*/ false,
2071 					/*metric_no_merge=*/ false,
2072 					/*metric_no_threshold=*/ true,
2073 					/*user_requested_cpu_list=*/ NULL,
2074 					/*system_wide=*/true,
2075 					/*hardware_aware_grouping=*/ false);
2076 	if (ret) {
2077 		errno = -ret;
2078 		PyErr_SetFromErrno(PyExc_OSError);
2079 		return NULL;
2080 	}
2081 	result = pyrf_evlist__from_evlist(&evlist);
2082 	evlist__exit(&evlist);
2083 	return result;
2084 }
2085 
pyrf__metrics_groups(const struct pmu_metric * pm)2086 static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm)
2087 {
2088 	PyObject *groups = PyList_New(/*len=*/0);
2089 	const char *mg = pm->metric_group;
2090 
2091 	if (!groups)
2092 		return NULL;
2093 
2094 	while (mg) {
2095 		PyObject *val = NULL;
2096 		const char *sep = strchr(mg, ';');
2097 		size_t len = sep ? (size_t)(sep - mg) : strlen(mg);
2098 
2099 		if (len > 0) {
2100 			val = PyUnicode_FromStringAndSize(mg, len);
2101 			if (val)
2102 				PyList_Append(groups, val);
2103 
2104 			Py_XDECREF(val);
2105 		}
2106 		mg = sep ? sep + 1 : NULL;
2107 	}
2108 	return groups;
2109 }
2110 
pyrf__metrics_cb(const struct pmu_metric * pm,const struct pmu_metrics_table * table __maybe_unused,void * vdata)2111 static int pyrf__metrics_cb(const struct pmu_metric *pm,
2112 			    const struct pmu_metrics_table *table __maybe_unused,
2113 			    void *vdata)
2114 {
2115 	PyObject *py_list = vdata;
2116 	PyObject *dict = PyDict_New();
2117 	PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL;
2118 	PyObject *value = key ? pyrf__metrics_groups(pm) : NULL;
2119 
2120 	if (!value || PyDict_SetItem(dict, key, value) != 0) {
2121 		Py_XDECREF(key);
2122 		Py_XDECREF(value);
2123 		Py_XDECREF(dict);
2124 		return -ENOMEM;
2125 	}
2126 
2127 	if (!add_to_dict(dict, "MetricName", pm->metric_name) ||
2128 	    !add_to_dict(dict, "PMU", pm->pmu) ||
2129 	    !add_to_dict(dict, "MetricExpr", pm->metric_expr) ||
2130 	    !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) ||
2131 	    !add_to_dict(dict, "ScaleUnit", pm->unit) ||
2132 	    !add_to_dict(dict, "Compat", pm->compat) ||
2133 	    !add_to_dict(dict, "BriefDescription", pm->desc) ||
2134 	    !add_to_dict(dict, "PublicDescription", pm->long_desc) ||
2135 	    PyList_Append(py_list, dict) != 0) {
2136 		Py_DECREF(dict);
2137 		return -ENOMEM;
2138 	}
2139 	Py_DECREF(dict);
2140 	return 0;
2141 }
2142 
pyrf__metrics(PyObject * self,PyObject * args)2143 static PyObject *pyrf__metrics(PyObject *self, PyObject *args)
2144 {
2145 	const struct pmu_metrics_table *table = pmu_metrics_table__find();
2146 	PyObject *list = PyList_New(/*len=*/0);
2147 	int ret;
2148 
2149 	if (!list)
2150 		return NULL;
2151 
2152 	ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list);
2153 	if (!ret)
2154 		ret = pmu_for_each_sys_metric(pyrf__metrics_cb, list);
2155 
2156 	if (ret) {
2157 		Py_DECREF(list);
2158 		errno = -ret;
2159 		PyErr_SetFromErrno(PyExc_OSError);
2160 		return NULL;
2161 	}
2162 	return list;
2163 }
2164 
2165 static PyMethodDef perf__methods[] = {
2166 	{
2167 		.ml_name  = "metrics",
2168 		.ml_meth  = (PyCFunction) pyrf__metrics,
2169 		.ml_flags = METH_NOARGS,
2170 		.ml_doc	  = PyDoc_STR(
2171 			"Returns a list of metrics represented as string values in dictionaries.")
2172 	},
2173 	{
2174 		.ml_name  = "tracepoint",
2175 		.ml_meth  = (PyCFunction) pyrf__tracepoint,
2176 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
2177 		.ml_doc	  = PyDoc_STR("Get tracepoint config.")
2178 	},
2179 	{
2180 		.ml_name  = "parse_events",
2181 		.ml_meth  = (PyCFunction) pyrf__parse_events,
2182 		.ml_flags = METH_VARARGS,
2183 		.ml_doc	  = PyDoc_STR("Parse a string of events and return an evlist.")
2184 	},
2185 	{
2186 		.ml_name  = "parse_metrics",
2187 		.ml_meth  = (PyCFunction) pyrf__parse_metrics,
2188 		.ml_flags = METH_VARARGS,
2189 		.ml_doc	  = PyDoc_STR(
2190 			"Parse a string of metrics or metric groups and return an evlist.")
2191 	},
2192 	{
2193 		.ml_name  = "pmus",
2194 		.ml_meth  = (PyCFunction) pyrf__pmus,
2195 		.ml_flags = METH_NOARGS,
2196 		.ml_doc	  = PyDoc_STR("Returns a sequence of pmus.")
2197 	},
2198 	{ .ml_name = NULL, }
2199 };
2200 
PyInit_perf(void)2201 PyMODINIT_FUNC PyInit_perf(void)
2202 {
2203 	PyObject *obj;
2204 	int i;
2205 	PyObject *dict;
2206 	static struct PyModuleDef moduledef = {
2207 		PyModuleDef_HEAD_INIT,
2208 		"perf",			/* m_name */
2209 		"",			/* m_doc */
2210 		-1,			/* m_size */
2211 		perf__methods,		/* m_methods */
2212 		NULL,			/* m_reload */
2213 		NULL,			/* m_traverse */
2214 		NULL,			/* m_clear */
2215 		NULL,			/* m_free */
2216 	};
2217 	PyObject *module = PyModule_Create(&moduledef);
2218 
2219 	if (module == NULL ||
2220 	    pyrf_event__setup_types() < 0 ||
2221 	    pyrf_evlist__setup_types() < 0 ||
2222 	    pyrf_evsel__setup_types() < 0 ||
2223 	    pyrf_thread_map__setup_types() < 0 ||
2224 	    pyrf_cpu_map__setup_types() < 0 ||
2225 	    pyrf_pmu_iterator__setup_types() < 0 ||
2226 	    pyrf_pmu__setup_types() < 0 ||
2227 	    pyrf_counts_values__setup_types() < 0)
2228 		return module;
2229 
2230 	/* The page_size is placed in util object. */
2231 	page_size = sysconf(_SC_PAGE_SIZE);
2232 
2233 	Py_INCREF(&pyrf_evlist__type);
2234 	PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
2235 
2236 	Py_INCREF(&pyrf_evsel__type);
2237 	PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
2238 
2239 	Py_INCREF(&pyrf_mmap_event__type);
2240 	PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type);
2241 
2242 	Py_INCREF(&pyrf_lost_event__type);
2243 	PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type);
2244 
2245 	Py_INCREF(&pyrf_comm_event__type);
2246 	PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type);
2247 
2248 	Py_INCREF(&pyrf_task_event__type);
2249 	PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
2250 
2251 	Py_INCREF(&pyrf_throttle_event__type);
2252 	PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type);
2253 
2254 	Py_INCREF(&pyrf_task_event__type);
2255 	PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
2256 
2257 	Py_INCREF(&pyrf_read_event__type);
2258 	PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type);
2259 
2260 	Py_INCREF(&pyrf_sample_event__type);
2261 	PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type);
2262 
2263 	Py_INCREF(&pyrf_context_switch_event__type);
2264 	PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type);
2265 
2266 	Py_INCREF(&pyrf_thread_map__type);
2267 	PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
2268 
2269 	Py_INCREF(&pyrf_cpu_map__type);
2270 	PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
2271 
2272 	Py_INCREF(&pyrf_counts_values__type);
2273 	PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type);
2274 
2275 	dict = PyModule_GetDict(module);
2276 	if (dict == NULL)
2277 		goto error;
2278 
2279 	for (i = 0; perf__constants[i].name != NULL; i++) {
2280 		obj = PyLong_FromLong(perf__constants[i].value);
2281 		if (obj == NULL)
2282 			goto error;
2283 		PyDict_SetItemString(dict, perf__constants[i].name, obj);
2284 		Py_DECREF(obj);
2285 	}
2286 
2287 error:
2288 	if (PyErr_Occurred())
2289 		PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
2290 	return module;
2291 }
2292