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