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 
pyrf_mmap_event__repr(struct pyrf_event * pevent)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 
pyrf_task_event__repr(struct pyrf_event * pevent)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 
pyrf_comm_event__repr(struct pyrf_event * pevent)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 
pyrf_throttle_event__repr(struct pyrf_event * pevent)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 
pyrf_event__setup_types(void)190 static int pyrf_event__setup_types(void)
191 {
192 	int err;
193 	pyrf_mmap_event__type.tp_new =
194 	pyrf_task_event__type.tp_new =
195 	pyrf_comm_event__type.tp_new =
196 	pyrf_throttle_event__type.tp_new = PyType_GenericNew;
197 	err = PyType_Ready(&pyrf_mmap_event__type);
198 	if (err < 0)
199 		goto out;
200 	err = PyType_Ready(&pyrf_task_event__type);
201 	if (err < 0)
202 		goto out;
203 	err = PyType_Ready(&pyrf_comm_event__type);
204 	if (err < 0)
205 		goto out;
206 	err = PyType_Ready(&pyrf_throttle_event__type);
207 	if (err < 0)
208 		goto out;
209 out:
210 	return err;
211 }
212 
213 static PyTypeObject *pyrf_event__type[] = {
214 	[PERF_RECORD_MMAP]	 = &pyrf_mmap_event__type,
215 	[PERF_RECORD_LOST]	 = &pyrf_mmap_event__type,
216 	[PERF_RECORD_COMM]	 = &pyrf_comm_event__type,
217 	[PERF_RECORD_EXIT]	 = &pyrf_task_event__type,
218 	[PERF_RECORD_THROTTLE]	 = &pyrf_throttle_event__type,
219 	[PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type,
220 	[PERF_RECORD_FORK]	 = &pyrf_task_event__type,
221 	[PERF_RECORD_READ]	 = &pyrf_mmap_event__type,
222 	[PERF_RECORD_SAMPLE]	 = &pyrf_mmap_event__type,
223 };
224 
pyrf_event__new(union perf_event * event)225 static PyObject *pyrf_event__new(union perf_event *event)
226 {
227 	struct pyrf_event *pevent;
228 	PyTypeObject *ptype;
229 
230 	if (event->header.type < PERF_RECORD_MMAP ||
231 	    event->header.type > PERF_RECORD_SAMPLE)
232 		return NULL;
233 
234 	ptype = pyrf_event__type[event->header.type];
235 	pevent = PyObject_New(struct pyrf_event, ptype);
236 	if (pevent != NULL)
237 		memcpy(&pevent->event, event, event->header.size);
238 	return (PyObject *)pevent;
239 }
240 
241 struct pyrf_cpu_map {
242 	PyObject_HEAD
243 
244 	struct cpu_map *cpus;
245 };
246 
pyrf_cpu_map__init(struct pyrf_cpu_map * pcpus,PyObject * args,PyObject * kwargs)247 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
248 			      PyObject *args, PyObject *kwargs)
249 {
250 	static char *kwlist[] = { "cpustr", NULL, NULL, };
251 	char *cpustr = NULL;
252 
253 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
254 					 kwlist, &cpustr))
255 		return -1;
256 
257 	pcpus->cpus = cpu_map__new(cpustr);
258 	if (pcpus->cpus == NULL)
259 		return -1;
260 	return 0;
261 }
262 
pyrf_cpu_map__delete(struct pyrf_cpu_map * pcpus)263 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
264 {
265 	cpu_map__delete(pcpus->cpus);
266 	pcpus->ob_type->tp_free((PyObject*)pcpus);
267 }
268 
pyrf_cpu_map__length(PyObject * obj)269 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj)
270 {
271 	struct pyrf_cpu_map *pcpus = (void *)obj;
272 
273 	return pcpus->cpus->nr;
274 }
275 
pyrf_cpu_map__item(PyObject * obj,Py_ssize_t i)276 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i)
277 {
278 	struct pyrf_cpu_map *pcpus = (void *)obj;
279 
280 	if (i >= pcpus->cpus->nr)
281 		return NULL;
282 
283 	return Py_BuildValue("i", pcpus->cpus->map[i]);
284 }
285 
286 static PySequenceMethods pyrf_cpu_map__sequence_methods = {
287 	.sq_length = pyrf_cpu_map__length,
288 	.sq_item   = pyrf_cpu_map__item,
289 };
290 
291 static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object.");
292 
293 static PyTypeObject pyrf_cpu_map__type = {
294 	PyVarObject_HEAD_INIT(NULL, 0)
295 	.tp_name	= "perf.cpu_map",
296 	.tp_basicsize	= sizeof(struct pyrf_cpu_map),
297 	.tp_dealloc	= (destructor)pyrf_cpu_map__delete,
298 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
299 	.tp_doc		= pyrf_cpu_map__doc,
300 	.tp_as_sequence	= &pyrf_cpu_map__sequence_methods,
301 	.tp_init	= (initproc)pyrf_cpu_map__init,
302 };
303 
pyrf_cpu_map__setup_types(void)304 static int pyrf_cpu_map__setup_types(void)
305 {
306 	pyrf_cpu_map__type.tp_new = PyType_GenericNew;
307 	return PyType_Ready(&pyrf_cpu_map__type);
308 }
309 
310 struct pyrf_thread_map {
311 	PyObject_HEAD
312 
313 	struct thread_map *threads;
314 };
315 
pyrf_thread_map__init(struct pyrf_thread_map * pthreads,PyObject * args,PyObject * kwargs)316 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
317 				 PyObject *args, PyObject *kwargs)
318 {
319 	static char *kwlist[] = { "pid", "tid", NULL, NULL, };
320 	int pid = -1, tid = -1;
321 
322 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
323 					 kwlist, &pid, &tid))
324 		return -1;
325 
326 	pthreads->threads = thread_map__new(pid, tid);
327 	if (pthreads->threads == NULL)
328 		return -1;
329 	return 0;
330 }
331 
pyrf_thread_map__delete(struct pyrf_thread_map * pthreads)332 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
333 {
334 	thread_map__delete(pthreads->threads);
335 	pthreads->ob_type->tp_free((PyObject*)pthreads);
336 }
337 
pyrf_thread_map__length(PyObject * obj)338 static Py_ssize_t pyrf_thread_map__length(PyObject *obj)
339 {
340 	struct pyrf_thread_map *pthreads = (void *)obj;
341 
342 	return pthreads->threads->nr;
343 }
344 
pyrf_thread_map__item(PyObject * obj,Py_ssize_t i)345 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i)
346 {
347 	struct pyrf_thread_map *pthreads = (void *)obj;
348 
349 	if (i >= pthreads->threads->nr)
350 		return NULL;
351 
352 	return Py_BuildValue("i", pthreads->threads->map[i]);
353 }
354 
355 static PySequenceMethods pyrf_thread_map__sequence_methods = {
356 	.sq_length = pyrf_thread_map__length,
357 	.sq_item   = pyrf_thread_map__item,
358 };
359 
360 static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object.");
361 
362 static PyTypeObject pyrf_thread_map__type = {
363 	PyVarObject_HEAD_INIT(NULL, 0)
364 	.tp_name	= "perf.thread_map",
365 	.tp_basicsize	= sizeof(struct pyrf_thread_map),
366 	.tp_dealloc	= (destructor)pyrf_thread_map__delete,
367 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
368 	.tp_doc		= pyrf_thread_map__doc,
369 	.tp_as_sequence	= &pyrf_thread_map__sequence_methods,
370 	.tp_init	= (initproc)pyrf_thread_map__init,
371 };
372 
pyrf_thread_map__setup_types(void)373 static int pyrf_thread_map__setup_types(void)
374 {
375 	pyrf_thread_map__type.tp_new = PyType_GenericNew;
376 	return PyType_Ready(&pyrf_thread_map__type);
377 }
378 
379 struct pyrf_evsel {
380 	PyObject_HEAD
381 
382 	struct perf_evsel evsel;
383 };
384 
pyrf_evsel__init(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)385 static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
386 			    PyObject *args, PyObject *kwargs)
387 {
388 	struct perf_event_attr attr = {
389 		.type = PERF_TYPE_HARDWARE,
390 		.config = PERF_COUNT_HW_CPU_CYCLES,
391 		.sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,
392 	};
393 	static char *kwlist[] = {
394 		"type",
395 		"config",
396 		"sample_freq",
397 		"sample_period",
398 		"sample_type",
399 		"read_format",
400 		"disabled",
401 		"inherit",
402 		"pinned",
403 		"exclusive",
404 		"exclude_user",
405 		"exclude_kernel",
406 		"exclude_hv",
407 		"exclude_idle",
408 		"mmap",
409 		"comm",
410 		"freq",
411 		"inherit_stat",
412 		"enable_on_exec",
413 		"task",
414 		"watermark",
415 		"precise_ip",
416 		"mmap_data",
417 		"sample_id_all",
418 		"wakeup_events",
419 		"bp_type",
420 		"bp_addr",
421 		"bp_len", NULL, NULL, };
422 	u64 sample_period = 0;
423 	u32 disabled = 0,
424 	    inherit = 0,
425 	    pinned = 0,
426 	    exclusive = 0,
427 	    exclude_user = 0,
428 	    exclude_kernel = 0,
429 	    exclude_hv = 0,
430 	    exclude_idle = 0,
431 	    mmap = 0,
432 	    comm = 0,
433 	    freq = 1,
434 	    inherit_stat = 0,
435 	    enable_on_exec = 0,
436 	    task = 0,
437 	    watermark = 0,
438 	    precise_ip = 0,
439 	    mmap_data = 0,
440 	    sample_id_all = 1;
441 	int idx = 0;
442 
443 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,
444 					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,
445 					 &attr.type, &attr.config, &attr.sample_freq,
446 					 &sample_period, &attr.sample_type,
447 					 &attr.read_format, &disabled, &inherit,
448 					 &pinned, &exclusive, &exclude_user,
449 					 &exclude_kernel, &exclude_hv, &exclude_idle,
450 					 &mmap, &comm, &freq, &inherit_stat,
451 					 &enable_on_exec, &task, &watermark,
452 					 &precise_ip, &mmap_data, &sample_id_all,
453 					 &attr.wakeup_events, &attr.bp_type,
454 					 &attr.bp_addr, &attr.bp_len, &idx))
455 		return -1;
456 
457 	/* union... */
458 	if (sample_period != 0) {
459 		if (attr.sample_freq != 0)
460 			return -1; /* FIXME: throw right exception */
461 		attr.sample_period = sample_period;
462 	}
463 
464 	/* Bitfields */
465 	attr.disabled	    = disabled;
466 	attr.inherit	    = inherit;
467 	attr.pinned	    = pinned;
468 	attr.exclusive	    = exclusive;
469 	attr.exclude_user   = exclude_user;
470 	attr.exclude_kernel = exclude_kernel;
471 	attr.exclude_hv	    = exclude_hv;
472 	attr.exclude_idle   = exclude_idle;
473 	attr.mmap	    = mmap;
474 	attr.comm	    = comm;
475 	attr.freq	    = freq;
476 	attr.inherit_stat   = inherit_stat;
477 	attr.enable_on_exec = enable_on_exec;
478 	attr.task	    = task;
479 	attr.watermark	    = watermark;
480 	attr.precise_ip	    = precise_ip;
481 	attr.mmap_data	    = mmap_data;
482 	attr.sample_id_all  = sample_id_all;
483 
484 	perf_evsel__init(&pevsel->evsel, &attr, idx);
485 	return 0;
486 }
487 
pyrf_evsel__delete(struct pyrf_evsel * pevsel)488 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel)
489 {
490 	perf_evsel__exit(&pevsel->evsel);
491 	pevsel->ob_type->tp_free((PyObject*)pevsel);
492 }
493 
pyrf_evsel__open(struct pyrf_evsel * pevsel,PyObject * args,PyObject * kwargs)494 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
495 				  PyObject *args, PyObject *kwargs)
496 {
497 	struct perf_evsel *evsel = &pevsel->evsel;
498 	struct cpu_map *cpus = NULL;
499 	struct thread_map *threads = NULL;
500 	PyObject *pcpus = NULL, *pthreads = NULL;
501 	int group = 0, inherit = 0;
502 	static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
503 
504 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
505 					 &pcpus, &pthreads, &group, &inherit))
506 		return NULL;
507 
508 	if (pthreads != NULL)
509 		threads = ((struct pyrf_thread_map *)pthreads)->threads;
510 
511 	if (pcpus != NULL)
512 		cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
513 
514 	evsel->attr.inherit = inherit;
515 	if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
516 		PyErr_SetFromErrno(PyExc_OSError);
517 		return NULL;
518 	}
519 
520 	Py_INCREF(Py_None);
521 	return Py_None;
522 }
523 
524 static PyMethodDef pyrf_evsel__methods[] = {
525 	{
526 		.ml_name  = "open",
527 		.ml_meth  = (PyCFunction)pyrf_evsel__open,
528 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
529 		.ml_doc	  = PyDoc_STR("open the event selector file descriptor table.")
530 	},
531 	{ .ml_name = NULL, }
532 };
533 
534 static char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object.");
535 
536 static PyTypeObject pyrf_evsel__type = {
537 	PyVarObject_HEAD_INIT(NULL, 0)
538 	.tp_name	= "perf.evsel",
539 	.tp_basicsize	= sizeof(struct pyrf_evsel),
540 	.tp_dealloc	= (destructor)pyrf_evsel__delete,
541 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
542 	.tp_doc		= pyrf_evsel__doc,
543 	.tp_methods	= pyrf_evsel__methods,
544 	.tp_init	= (initproc)pyrf_evsel__init,
545 };
546 
pyrf_evsel__setup_types(void)547 static int pyrf_evsel__setup_types(void)
548 {
549 	pyrf_evsel__type.tp_new = PyType_GenericNew;
550 	return PyType_Ready(&pyrf_evsel__type);
551 }
552 
553 struct pyrf_evlist {
554 	PyObject_HEAD
555 
556 	struct perf_evlist evlist;
557 };
558 
pyrf_evlist__init(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __used)559 static int pyrf_evlist__init(struct pyrf_evlist *pevlist,
560 			     PyObject *args, PyObject *kwargs __used)
561 {
562 	PyObject *pcpus = NULL, *pthreads = NULL;
563 	struct cpu_map *cpus;
564 	struct thread_map *threads;
565 
566 	if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads))
567 		return -1;
568 
569 	threads = ((struct pyrf_thread_map *)pthreads)->threads;
570 	cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
571 	perf_evlist__init(&pevlist->evlist, cpus, threads);
572 	return 0;
573 }
574 
pyrf_evlist__delete(struct pyrf_evlist * pevlist)575 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist)
576 {
577 	perf_evlist__exit(&pevlist->evlist);
578 	pevlist->ob_type->tp_free((PyObject*)pevlist);
579 }
580 
pyrf_evlist__mmap(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)581 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
582 				   PyObject *args, PyObject *kwargs)
583 {
584 	struct perf_evlist *evlist = &pevlist->evlist;
585 	static char *kwlist[] = {"pages", "overwrite",
586 				  NULL, NULL};
587 	int pages = 128, overwrite = false;
588 
589 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
590 					 &pages, &overwrite))
591 		return NULL;
592 
593 	if (perf_evlist__mmap(evlist, pages, overwrite) < 0) {
594 		PyErr_SetFromErrno(PyExc_OSError);
595 		return NULL;
596 	}
597 
598 	Py_INCREF(Py_None);
599 	return Py_None;
600 }
601 
pyrf_evlist__poll(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)602 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
603 				   PyObject *args, PyObject *kwargs)
604 {
605 	struct perf_evlist *evlist = &pevlist->evlist;
606 	static char *kwlist[] = {"timeout", NULL, NULL};
607 	int timeout = -1, n;
608 
609 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
610 		return NULL;
611 
612 	n = poll(evlist->pollfd, evlist->nr_fds, timeout);
613 	if (n < 0) {
614 		PyErr_SetFromErrno(PyExc_OSError);
615 		return NULL;
616 	}
617 
618 	return Py_BuildValue("i", n);
619 }
620 
pyrf_evlist__get_pollfd(struct pyrf_evlist * pevlist,PyObject * args __used,PyObject * kwargs __used)621 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist,
622 					 PyObject *args __used, PyObject *kwargs __used)
623 {
624 	struct perf_evlist *evlist = &pevlist->evlist;
625         PyObject *list = PyList_New(0);
626 	int i;
627 
628 	for (i = 0; i < evlist->nr_fds; ++i) {
629 		PyObject *file;
630 		FILE *fp = fdopen(evlist->pollfd[i].fd, "r");
631 
632 		if (fp == NULL)
633 			goto free_list;
634 
635 		file = PyFile_FromFile(fp, "perf", "r", NULL);
636 		if (file == NULL)
637 			goto free_list;
638 
639 		if (PyList_Append(list, file) != 0) {
640 			Py_DECREF(file);
641 			goto free_list;
642 		}
643 
644 		Py_DECREF(file);
645 	}
646 
647 	return list;
648 free_list:
649 	return PyErr_NoMemory();
650 }
651 
652 
pyrf_evlist__add(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs __used)653 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist,
654 				  PyObject *args, PyObject *kwargs __used)
655 {
656 	struct perf_evlist *evlist = &pevlist->evlist;
657 	PyObject *pevsel;
658 	struct perf_evsel *evsel;
659 
660 	if (!PyArg_ParseTuple(args, "O", &pevsel))
661 		return NULL;
662 
663 	Py_INCREF(pevsel);
664 	evsel = &((struct pyrf_evsel *)pevsel)->evsel;
665 	evsel->idx = evlist->nr_entries;
666 	perf_evlist__add(evlist, evsel);
667 
668 	return Py_BuildValue("i", evlist->nr_entries);
669 }
670 
pyrf_evlist__read_on_cpu(struct pyrf_evlist * pevlist,PyObject * args,PyObject * kwargs)671 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
672 					  PyObject *args, PyObject *kwargs)
673 {
674 	struct perf_evlist *evlist = &pevlist->evlist;
675 	union perf_event *event;
676 	int sample_id_all = 1, cpu;
677 	static char *kwlist[] = {"sample_id_all", NULL, NULL};
678 
679 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
680 					 &cpu, &sample_id_all))
681 		return NULL;
682 
683 	event = perf_evlist__mmap_read(evlist, cpu);
684 	if (event != NULL) {
685 		struct perf_evsel *first;
686 		PyObject *pyevent = pyrf_event__new(event);
687 		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
688 
689 		if (pyevent == NULL)
690 			return PyErr_NoMemory();
691 
692 		first = list_entry(evlist->entries.next, struct perf_evsel, node);
693 		perf_event__parse_sample(event, first->attr.sample_type, sample_id_all,
694 					 &pevent->sample);
695 		return pyevent;
696 	}
697 
698 	Py_INCREF(Py_None);
699 	return Py_None;
700 }
701 
702 static PyMethodDef pyrf_evlist__methods[] = {
703 	{
704 		.ml_name  = "mmap",
705 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
706 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
707 		.ml_doc	  = PyDoc_STR("mmap the file descriptor table.")
708 	},
709 	{
710 		.ml_name  = "poll",
711 		.ml_meth  = (PyCFunction)pyrf_evlist__poll,
712 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
713 		.ml_doc	  = PyDoc_STR("poll the file descriptor table.")
714 	},
715 	{
716 		.ml_name  = "get_pollfd",
717 		.ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
718 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
719 		.ml_doc	  = PyDoc_STR("get the poll file descriptor table.")
720 	},
721 	{
722 		.ml_name  = "add",
723 		.ml_meth  = (PyCFunction)pyrf_evlist__add,
724 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
725 		.ml_doc	  = PyDoc_STR("adds an event selector to the list.")
726 	},
727 	{
728 		.ml_name  = "read_on_cpu",
729 		.ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
730 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
731 		.ml_doc	  = PyDoc_STR("reads an event.")
732 	},
733 	{ .ml_name = NULL, }
734 };
735 
pyrf_evlist__length(PyObject * obj)736 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
737 {
738 	struct pyrf_evlist *pevlist = (void *)obj;
739 
740 	return pevlist->evlist.nr_entries;
741 }
742 
pyrf_evlist__item(PyObject * obj,Py_ssize_t i)743 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
744 {
745 	struct pyrf_evlist *pevlist = (void *)obj;
746 	struct perf_evsel *pos;
747 
748 	if (i >= pevlist->evlist.nr_entries)
749 		return NULL;
750 
751 	list_for_each_entry(pos, &pevlist->evlist.entries, node)
752 		if (i-- == 0)
753 			break;
754 
755 	return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
756 }
757 
758 static PySequenceMethods pyrf_evlist__sequence_methods = {
759 	.sq_length = pyrf_evlist__length,
760 	.sq_item   = pyrf_evlist__item,
761 };
762 
763 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
764 
765 static PyTypeObject pyrf_evlist__type = {
766 	PyVarObject_HEAD_INIT(NULL, 0)
767 	.tp_name	= "perf.evlist",
768 	.tp_basicsize	= sizeof(struct pyrf_evlist),
769 	.tp_dealloc	= (destructor)pyrf_evlist__delete,
770 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
771 	.tp_as_sequence	= &pyrf_evlist__sequence_methods,
772 	.tp_doc		= pyrf_evlist__doc,
773 	.tp_methods	= pyrf_evlist__methods,
774 	.tp_init	= (initproc)pyrf_evlist__init,
775 };
776 
pyrf_evlist__setup_types(void)777 static int pyrf_evlist__setup_types(void)
778 {
779 	pyrf_evlist__type.tp_new = PyType_GenericNew;
780 	return PyType_Ready(&pyrf_evlist__type);
781 }
782 
783 static struct {
784 	const char *name;
785 	int	    value;
786 } perf__constants[] = {
787 	{ "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
788 	{ "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
789 	{ "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
790 	{ "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
791 	{ "TYPE_RAW",	     PERF_TYPE_RAW },
792 	{ "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
793 
794 	{ "COUNT_HW_CPU_CYCLES",	  PERF_COUNT_HW_CPU_CYCLES },
795 	{ "COUNT_HW_INSTRUCTIONS",	  PERF_COUNT_HW_INSTRUCTIONS },
796 	{ "COUNT_HW_CACHE_REFERENCES",	  PERF_COUNT_HW_CACHE_REFERENCES },
797 	{ "COUNT_HW_CACHE_MISSES",	  PERF_COUNT_HW_CACHE_MISSES },
798 	{ "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
799 	{ "COUNT_HW_BRANCH_MISSES",	  PERF_COUNT_HW_BRANCH_MISSES },
800 	{ "COUNT_HW_BUS_CYCLES",	  PERF_COUNT_HW_BUS_CYCLES },
801 	{ "COUNT_HW_CACHE_L1D",		  PERF_COUNT_HW_CACHE_L1D },
802 	{ "COUNT_HW_CACHE_L1I",		  PERF_COUNT_HW_CACHE_L1I },
803 	{ "COUNT_HW_CACHE_LL",	  	  PERF_COUNT_HW_CACHE_LL },
804 	{ "COUNT_HW_CACHE_DTLB",	  PERF_COUNT_HW_CACHE_DTLB },
805 	{ "COUNT_HW_CACHE_ITLB",	  PERF_COUNT_HW_CACHE_ITLB },
806 	{ "COUNT_HW_CACHE_BPU",		  PERF_COUNT_HW_CACHE_BPU },
807 	{ "COUNT_HW_CACHE_OP_READ",	  PERF_COUNT_HW_CACHE_OP_READ },
808 	{ "COUNT_HW_CACHE_OP_WRITE",	  PERF_COUNT_HW_CACHE_OP_WRITE },
809 	{ "COUNT_HW_CACHE_OP_PREFETCH",	  PERF_COUNT_HW_CACHE_OP_PREFETCH },
810 	{ "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
811 	{ "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
812 
813 	{ "COUNT_SW_CPU_CLOCK",	       PERF_COUNT_SW_CPU_CLOCK },
814 	{ "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
815 	{ "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
816 	{ "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
817 	{ "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
818 	{ "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
819 	{ "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
820 	{ "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
821 	{ "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
822 
823 	{ "SAMPLE_IP",	      PERF_SAMPLE_IP },
824 	{ "SAMPLE_TID",	      PERF_SAMPLE_TID },
825 	{ "SAMPLE_TIME",      PERF_SAMPLE_TIME },
826 	{ "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
827 	{ "SAMPLE_READ",      PERF_SAMPLE_READ },
828 	{ "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
829 	{ "SAMPLE_ID",	      PERF_SAMPLE_ID },
830 	{ "SAMPLE_CPU",	      PERF_SAMPLE_CPU },
831 	{ "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
832 	{ "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
833 	{ "SAMPLE_RAW",	      PERF_SAMPLE_RAW },
834 
835 	{ "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
836 	{ "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
837 	{ "FORMAT_ID",		       PERF_FORMAT_ID },
838 	{ "FORMAT_GROUP",	       PERF_FORMAT_GROUP },
839 
840 	{ "RECORD_MMAP",       PERF_RECORD_MMAP },
841 	{ "RECORD_LOST",       PERF_RECORD_LOST },
842 	{ "RECORD_COMM",       PERF_RECORD_COMM },
843 	{ "RECORD_EXIT",       PERF_RECORD_EXIT },
844 	{ "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
845 	{ "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
846 	{ "RECORD_FORK",       PERF_RECORD_FORK },
847 	{ "RECORD_READ",       PERF_RECORD_READ },
848 	{ "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
849 	{ .name = NULL, },
850 };
851 
852 static PyMethodDef perf__methods[] = {
853 	{ .ml_name = NULL, }
854 };
855 
initperf(void)856 PyMODINIT_FUNC initperf(void)
857 {
858 	PyObject *obj;
859 	int i;
860 	PyObject *dict, *module = Py_InitModule("perf", perf__methods);
861 
862 	if (module == NULL ||
863 	    pyrf_event__setup_types() < 0 ||
864 	    pyrf_evlist__setup_types() < 0 ||
865 	    pyrf_evsel__setup_types() < 0 ||
866 	    pyrf_thread_map__setup_types() < 0 ||
867 	    pyrf_cpu_map__setup_types() < 0)
868 		return;
869 
870 	Py_INCREF(&pyrf_evlist__type);
871 	PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
872 
873 	Py_INCREF(&pyrf_evsel__type);
874 	PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
875 
876 	Py_INCREF(&pyrf_thread_map__type);
877 	PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
878 
879 	Py_INCREF(&pyrf_cpu_map__type);
880 	PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
881 
882 	dict = PyModule_GetDict(module);
883 	if (dict == NULL)
884 		goto error;
885 
886 	for (i = 0; perf__constants[i].name != NULL; i++) {
887 		obj = PyInt_FromLong(perf__constants[i].value);
888 		if (obj == NULL)
889 			goto error;
890 		PyDict_SetItemString(dict, perf__constants[i].name, obj);
891 		Py_DECREF(obj);
892 	}
893 
894 error:
895 	if (PyErr_Occurred())
896 		PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
897 }
898