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