Home | History | Annotate | Download | only in util
      1 #include <Python.h>
      2 #include <structmember.h>
      3 #include <inttypes.h>
      4 #include <poll.h>
      5 #include "evlist.h"
      6 #include "evsel.h"
      7 #include "event.h"
      8 #include "cpumap.h"
      9 #include "thread_map.h"
     10 
     11 /* Define PyVarObject_HEAD_INIT for python 2.5 */
     12 #ifndef PyVarObject_HEAD_INIT
     13 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
     14 #endif
     15 
     16 struct throttle_event {
     17 	struct perf_event_header header;
     18 	u64			 time;
     19 	u64			 id;
     20 	u64			 stream_id;
     21 };
     22 
     23 PyMODINIT_FUNC initperf(void);
     24 
     25 #define member_def(type, member, ptype, help) \
     26 	{ #member, ptype, \
     27 	  offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
     28 	  0, help }
     29 
     30 #define sample_member_def(name, member, ptype, help) \
     31 	{ #name, ptype, \
     32 	  offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
     33 	  0, help }
     34 
     35 struct pyrf_event {
     36 	PyObject_HEAD
     37 	struct perf_sample sample;
     38 	union perf_event   event;
     39 };
     40 
     41 #define sample_members \
     42 	sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"),			 \
     43 	sample_member_def(sample_pid, pid, T_INT, "event pid"),			 \
     44 	sample_member_def(sample_tid, tid, T_INT, "event tid"),			 \
     45 	sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"),		 \
     46 	sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"),		 \
     47 	sample_member_def(sample_id, id, T_ULONGLONG, "event id"),			 \
     48 	sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
     49 	sample_member_def(sample_period, period, T_ULONGLONG, "event period"),		 \
     50 	sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
     51 
     52 static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object.");
     53 
     54 static PyMemberDef pyrf_mmap_event__members[] = {
     55 	sample_members
     56 	member_def(perf_event_header, type, T_UINT, "event type"),
     57 	member_def(mmap_event, pid, T_UINT, "event pid"),
     58 	member_def(mmap_event, tid, T_UINT, "event tid"),
     59 	member_def(mmap_event, start, T_ULONGLONG, "start of the map"),
     60 	member_def(mmap_event, len, T_ULONGLONG, "map length"),
     61 	member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"),
     62 	member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"),
     63 	{ .name = NULL, },
     64 };
     65 
     66 static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent)
     67 {
     68 	PyObject *ret;
     69 	char *s;
     70 
     71 	if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", "
     72 			 "length: %#" PRIx64 ", offset: %#" PRIx64 ", "
     73 			 "filename: %s }",
     74 		     pevent->event.mmap.pid, pevent->event.mmap.tid,
     75 		     pevent->event.mmap.start, pevent->event.mmap.len,
     76 		     pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) {
     77 		ret = PyErr_NoMemory();
     78 	} else {
     79 		ret = PyString_FromString(s);
     80 		free(s);
     81 	}
     82 	return ret;
     83 }
     84 
     85 static PyTypeObject pyrf_mmap_event__type = {
     86 	PyVarObject_HEAD_INIT(NULL, 0)
     87 	.tp_name	= "perf.mmap_event",
     88 	.tp_basicsize	= sizeof(struct pyrf_event),
     89 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     90 	.tp_doc		= pyrf_mmap_event__doc,
     91 	.tp_members	= pyrf_mmap_event__members,
     92 	.tp_repr	= (reprfunc)pyrf_mmap_event__repr,
     93 };
     94 
     95 static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object.");
     96 
     97 static PyMemberDef pyrf_task_event__members[] = {
     98 	sample_members
     99 	member_def(perf_event_header, type, T_UINT, "event type"),
    100 	member_def(fork_event, pid, T_UINT, "event pid"),
    101 	member_def(fork_event, ppid, T_UINT, "event ppid"),
    102 	member_def(fork_event, tid, T_UINT, "event tid"),
    103 	member_def(fork_event, ptid, T_UINT, "event ptid"),
    104 	member_def(fork_event, time, T_ULONGLONG, "timestamp"),
    105 	{ .name = NULL, },
    106 };
    107 
    108 static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent)
    109 {
    110 	return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
    111 				   "ptid: %u, time: %" PRIu64 "}",
    112 				   pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit",
    113 				   pevent->event.fork.pid,
    114 				   pevent->event.fork.ppid,
    115 				   pevent->event.fork.tid,
    116 				   pevent->event.fork.ptid,
    117 				   pevent->event.fork.time);
    118 }
    119 
    120 static PyTypeObject pyrf_task_event__type = {
    121 	PyVarObject_HEAD_INIT(NULL, 0)
    122 	.tp_name	= "perf.task_event",
    123 	.tp_basicsize	= sizeof(struct pyrf_event),
    124 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    125 	.tp_doc		= pyrf_task_event__doc,
    126 	.tp_members	= pyrf_task_event__members,
    127 	.tp_repr	= (reprfunc)pyrf_task_event__repr,
    128 };
    129 
    130 static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object.");
    131 
    132 static PyMemberDef pyrf_comm_event__members[] = {
    133 	sample_members
    134 	member_def(perf_event_header, type, T_UINT, "event type"),
    135 	member_def(comm_event, pid, T_UINT, "event pid"),
    136 	member_def(comm_event, tid, T_UINT, "event tid"),
    137 	member_def(comm_event, comm, T_STRING_INPLACE, "process name"),
    138 	{ .name = NULL, },
    139 };
    140 
    141 static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent)
    142 {
    143 	return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
    144 				   pevent->event.comm.pid,
    145 				   pevent->event.comm.tid,
    146 				   pevent->event.comm.comm);
    147 }
    148 
    149 static PyTypeObject pyrf_comm_event__type = {
    150 	PyVarObject_HEAD_INIT(NULL, 0)
    151 	.tp_name	= "perf.comm_event",
    152 	.tp_basicsize	= sizeof(struct pyrf_event),
    153 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    154 	.tp_doc		= pyrf_comm_event__doc,
    155 	.tp_members	= pyrf_comm_event__members,
    156 	.tp_repr	= (reprfunc)pyrf_comm_event__repr,
    157 };
    158 
    159 static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object.");
    160 
    161 static PyMemberDef pyrf_throttle_event__members[] = {
    162 	sample_members
    163 	member_def(perf_event_header, type, T_UINT, "event type"),
    164 	member_def(throttle_event, time, T_ULONGLONG, "timestamp"),
    165 	member_def(throttle_event, id, T_ULONGLONG, "event id"),
    166 	member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"),
    167 	{ .name = NULL, },
    168 };
    169 
    170 static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent)
    171 {
    172 	struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1);
    173 
    174 	return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64
    175 				   ", stream_id: %" PRIu64 " }",
    176 				   pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un",
    177 				   te->time, te->id, te->stream_id);
    178 }
    179 
    180 static PyTypeObject pyrf_throttle_event__type = {
    181 	PyVarObject_HEAD_INIT(NULL, 0)
    182 	.tp_name	= "perf.throttle_event",
    183 	.tp_basicsize	= sizeof(struct pyrf_event),
    184 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    185 	.tp_doc		= pyrf_throttle_event__doc,
    186 	.tp_members	= pyrf_throttle_event__members,
    187 	.tp_repr	= (reprfunc)pyrf_throttle_event__repr,
    188 };
    189 
    190 static 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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[] = {"cpu", "sample_id_all", NULL, NULL};
    678 	int err;
    679 
    680 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
    681 					 &cpu, &sample_id_all))
    682 		return NULL;
    683 
    684 	event = perf_evlist__mmap_read(evlist, cpu);
    685 	if (event != NULL) {
    686 		struct perf_evsel *first;
    687 		PyObject *pyevent = pyrf_event__new(event);
    688 		struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
    689 
    690 		if (pyevent == NULL)
    691 			return PyErr_NoMemory();
    692 
    693 		first = list_entry(evlist->entries.next, struct perf_evsel, node);
    694 		err = perf_event__parse_sample(event, first->attr.sample_type,
    695 					       perf_evsel__sample_size(first),
    696 					       sample_id_all, &pevent->sample);
    697 		if (err)
    698 			return PyErr_Format(PyExc_OSError,
    699 					    "perf: can't parse sample, err=%d", err);
    700 		return pyevent;
    701 	}
    702 
    703 	Py_INCREF(Py_None);
    704 	return Py_None;
    705 }
    706 
    707 static PyMethodDef pyrf_evlist__methods[] = {
    708 	{
    709 		.ml_name  = "mmap",
    710 		.ml_meth  = (PyCFunction)pyrf_evlist__mmap,
    711 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
    712 		.ml_doc	  = PyDoc_STR("mmap the file descriptor table.")
    713 	},
    714 	{
    715 		.ml_name  = "poll",
    716 		.ml_meth  = (PyCFunction)pyrf_evlist__poll,
    717 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
    718 		.ml_doc	  = PyDoc_STR("poll the file descriptor table.")
    719 	},
    720 	{
    721 		.ml_name  = "get_pollfd",
    722 		.ml_meth  = (PyCFunction)pyrf_evlist__get_pollfd,
    723 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
    724 		.ml_doc	  = PyDoc_STR("get the poll file descriptor table.")
    725 	},
    726 	{
    727 		.ml_name  = "add",
    728 		.ml_meth  = (PyCFunction)pyrf_evlist__add,
    729 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
    730 		.ml_doc	  = PyDoc_STR("adds an event selector to the list.")
    731 	},
    732 	{
    733 		.ml_name  = "read_on_cpu",
    734 		.ml_meth  = (PyCFunction)pyrf_evlist__read_on_cpu,
    735 		.ml_flags = METH_VARARGS | METH_KEYWORDS,
    736 		.ml_doc	  = PyDoc_STR("reads an event.")
    737 	},
    738 	{ .ml_name = NULL, }
    739 };
    740 
    741 static Py_ssize_t pyrf_evlist__length(PyObject *obj)
    742 {
    743 	struct pyrf_evlist *pevlist = (void *)obj;
    744 
    745 	return pevlist->evlist.nr_entries;
    746 }
    747 
    748 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
    749 {
    750 	struct pyrf_evlist *pevlist = (void *)obj;
    751 	struct perf_evsel *pos;
    752 
    753 	if (i >= pevlist->evlist.nr_entries)
    754 		return NULL;
    755 
    756 	list_for_each_entry(pos, &pevlist->evlist.entries, node)
    757 		if (i-- == 0)
    758 			break;
    759 
    760 	return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel));
    761 }
    762 
    763 static PySequenceMethods pyrf_evlist__sequence_methods = {
    764 	.sq_length = pyrf_evlist__length,
    765 	.sq_item   = pyrf_evlist__item,
    766 };
    767 
    768 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object.");
    769 
    770 static PyTypeObject pyrf_evlist__type = {
    771 	PyVarObject_HEAD_INIT(NULL, 0)
    772 	.tp_name	= "perf.evlist",
    773 	.tp_basicsize	= sizeof(struct pyrf_evlist),
    774 	.tp_dealloc	= (destructor)pyrf_evlist__delete,
    775 	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    776 	.tp_as_sequence	= &pyrf_evlist__sequence_methods,
    777 	.tp_doc		= pyrf_evlist__doc,
    778 	.tp_methods	= pyrf_evlist__methods,
    779 	.tp_init	= (initproc)pyrf_evlist__init,
    780 };
    781 
    782 static int pyrf_evlist__setup_types(void)
    783 {
    784 	pyrf_evlist__type.tp_new = PyType_GenericNew;
    785 	return PyType_Ready(&pyrf_evlist__type);
    786 }
    787 
    788 static struct {
    789 	const char *name;
    790 	int	    value;
    791 } perf__constants[] = {
    792 	{ "TYPE_HARDWARE",   PERF_TYPE_HARDWARE },
    793 	{ "TYPE_SOFTWARE",   PERF_TYPE_SOFTWARE },
    794 	{ "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT },
    795 	{ "TYPE_HW_CACHE",   PERF_TYPE_HW_CACHE },
    796 	{ "TYPE_RAW",	     PERF_TYPE_RAW },
    797 	{ "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT },
    798 
    799 	{ "COUNT_HW_CPU_CYCLES",	  PERF_COUNT_HW_CPU_CYCLES },
    800 	{ "COUNT_HW_INSTRUCTIONS",	  PERF_COUNT_HW_INSTRUCTIONS },
    801 	{ "COUNT_HW_CACHE_REFERENCES",	  PERF_COUNT_HW_CACHE_REFERENCES },
    802 	{ "COUNT_HW_CACHE_MISSES",	  PERF_COUNT_HW_CACHE_MISSES },
    803 	{ "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS },
    804 	{ "COUNT_HW_BRANCH_MISSES",	  PERF_COUNT_HW_BRANCH_MISSES },
    805 	{ "COUNT_HW_BUS_CYCLES",	  PERF_COUNT_HW_BUS_CYCLES },
    806 	{ "COUNT_HW_CACHE_L1D",		  PERF_COUNT_HW_CACHE_L1D },
    807 	{ "COUNT_HW_CACHE_L1I",		  PERF_COUNT_HW_CACHE_L1I },
    808 	{ "COUNT_HW_CACHE_LL",	  	  PERF_COUNT_HW_CACHE_LL },
    809 	{ "COUNT_HW_CACHE_DTLB",	  PERF_COUNT_HW_CACHE_DTLB },
    810 	{ "COUNT_HW_CACHE_ITLB",	  PERF_COUNT_HW_CACHE_ITLB },
    811 	{ "COUNT_HW_CACHE_BPU",		  PERF_COUNT_HW_CACHE_BPU },
    812 	{ "COUNT_HW_CACHE_OP_READ",	  PERF_COUNT_HW_CACHE_OP_READ },
    813 	{ "COUNT_HW_CACHE_OP_WRITE",	  PERF_COUNT_HW_CACHE_OP_WRITE },
    814 	{ "COUNT_HW_CACHE_OP_PREFETCH",	  PERF_COUNT_HW_CACHE_OP_PREFETCH },
    815 	{ "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS },
    816 	{ "COUNT_HW_CACHE_RESULT_MISS",   PERF_COUNT_HW_CACHE_RESULT_MISS },
    817 
    818 	{ "COUNT_HW_STALLED_CYCLES_FRONTEND",	  PERF_COUNT_HW_STALLED_CYCLES_FRONTEND },
    819 	{ "COUNT_HW_STALLED_CYCLES_BACKEND",	  PERF_COUNT_HW_STALLED_CYCLES_BACKEND },
    820 
    821 	{ "COUNT_SW_CPU_CLOCK",	       PERF_COUNT_SW_CPU_CLOCK },
    822 	{ "COUNT_SW_TASK_CLOCK",       PERF_COUNT_SW_TASK_CLOCK },
    823 	{ "COUNT_SW_PAGE_FAULTS",      PERF_COUNT_SW_PAGE_FAULTS },
    824 	{ "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES },
    825 	{ "COUNT_SW_CPU_MIGRATIONS",   PERF_COUNT_SW_CPU_MIGRATIONS },
    826 	{ "COUNT_SW_PAGE_FAULTS_MIN",  PERF_COUNT_SW_PAGE_FAULTS_MIN },
    827 	{ "COUNT_SW_PAGE_FAULTS_MAJ",  PERF_COUNT_SW_PAGE_FAULTS_MAJ },
    828 	{ "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS },
    829 	{ "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS },
    830 
    831 	{ "SAMPLE_IP",	      PERF_SAMPLE_IP },
    832 	{ "SAMPLE_TID",	      PERF_SAMPLE_TID },
    833 	{ "SAMPLE_TIME",      PERF_SAMPLE_TIME },
    834 	{ "SAMPLE_ADDR",      PERF_SAMPLE_ADDR },
    835 	{ "SAMPLE_READ",      PERF_SAMPLE_READ },
    836 	{ "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN },
    837 	{ "SAMPLE_ID",	      PERF_SAMPLE_ID },
    838 	{ "SAMPLE_CPU",	      PERF_SAMPLE_CPU },
    839 	{ "SAMPLE_PERIOD",    PERF_SAMPLE_PERIOD },
    840 	{ "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID },
    841 	{ "SAMPLE_RAW",	      PERF_SAMPLE_RAW },
    842 
    843 	{ "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED },
    844 	{ "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING },
    845 	{ "FORMAT_ID",		       PERF_FORMAT_ID },
    846 	{ "FORMAT_GROUP",	       PERF_FORMAT_GROUP },
    847 
    848 	{ "RECORD_MMAP",       PERF_RECORD_MMAP },
    849 	{ "RECORD_LOST",       PERF_RECORD_LOST },
    850 	{ "RECORD_COMM",       PERF_RECORD_COMM },
    851 	{ "RECORD_EXIT",       PERF_RECORD_EXIT },
    852 	{ "RECORD_THROTTLE",   PERF_RECORD_THROTTLE },
    853 	{ "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE },
    854 	{ "RECORD_FORK",       PERF_RECORD_FORK },
    855 	{ "RECORD_READ",       PERF_RECORD_READ },
    856 	{ "RECORD_SAMPLE",     PERF_RECORD_SAMPLE },
    857 	{ .name = NULL, },
    858 };
    859 
    860 static PyMethodDef perf__methods[] = {
    861 	{ .ml_name = NULL, }
    862 };
    863 
    864 PyMODINIT_FUNC initperf(void)
    865 {
    866 	PyObject *obj;
    867 	int i;
    868 	PyObject *dict, *module = Py_InitModule("perf", perf__methods);
    869 
    870 	if (module == NULL ||
    871 	    pyrf_event__setup_types() < 0 ||
    872 	    pyrf_evlist__setup_types() < 0 ||
    873 	    pyrf_evsel__setup_types() < 0 ||
    874 	    pyrf_thread_map__setup_types() < 0 ||
    875 	    pyrf_cpu_map__setup_types() < 0)
    876 		return;
    877 
    878 	Py_INCREF(&pyrf_evlist__type);
    879 	PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type);
    880 
    881 	Py_INCREF(&pyrf_evsel__type);
    882 	PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
    883 
    884 	Py_INCREF(&pyrf_thread_map__type);
    885 	PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
    886 
    887 	Py_INCREF(&pyrf_cpu_map__type);
    888 	PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type);
    889 
    890 	dict = PyModule_GetDict(module);
    891 	if (dict == NULL)
    892 		goto error;
    893 
    894 	for (i = 0; perf__constants[i].name != NULL; i++) {
    895 		obj = PyInt_FromLong(perf__constants[i].value);
    896 		if (obj == NULL)
    897 			goto error;
    898 		PyDict_SetItemString(dict, perf__constants[i].name, obj);
    899 		Py_DECREF(obj);
    900 	}
    901 
    902 error:
    903 	if (PyErr_Occurred())
    904 		PyErr_SetString(PyExc_ImportError, "perf: Init failed!");
    905 }
    906