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 if (pyevent == NULL) 826 return PyErr_NoMemory(); 827 828 err = perf_evlist__parse_sample(evlist, event, &pevent->sample); 829 if (err) 830 return PyErr_Format(PyExc_OSError, 831 "perf: can't parse sample, err=%d", err); 832 return pyevent; 833 } 834 835 Py_INCREF(Py_None); 836 return Py_None; 837 } 838 839 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, 840 PyObject *args, PyObject *kwargs) 841 { 842 struct perf_evlist *evlist = &pevlist->evlist; 843 int group = 0; 844 static char *kwlist[] = { "group", NULL }; 845 846 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, &group)) 847 return NULL; 848 849 if (group) 850 perf_evlist__set_leader(evlist); 851 852 if (perf_evlist__open(evlist) < 0) { 853 PyErr_SetFromErrno(PyExc_OSError); 854 return NULL; 855 } 856 857 Py_INCREF(Py_None); 858 return Py_None; 859 } 860 861 static PyMethodDef pyrf_evlist__methods[] = { 862 { 863 .ml_name = "mmap", 864 .ml_meth = (PyCFunction)pyrf_evlist__mmap, 865 .ml_flags = METH_VARARGS | METH_KEYWORDS, 866 .ml_doc = PyDoc_STR("mmap the file descriptor table.") 867 }, 868 { 869 .ml_name = "open", 870 .ml_meth = (PyCFunction)pyrf_evlist__open, 871 .ml_flags = METH_VARARGS | METH_KEYWORDS, 872 .ml_doc = PyDoc_STR("open the file descriptors.") 873 }, 874 { 875 .ml_name = "poll", 876 .ml_meth = (PyCFunction)pyrf_evlist__poll, 877 .ml_flags = METH_VARARGS | METH_KEYWORDS, 878 .ml_doc = PyDoc_STR("poll the file descriptor table.") 879 }, 880 { 881 .ml_name = "get_pollfd", 882 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd, 883 .ml_flags = METH_VARARGS | METH_KEYWORDS, 884 .ml_doc = PyDoc_STR("get the poll file descriptor table.") 885 }, 886 { 887 .ml_name = "add", 888 .ml_meth = (PyCFunction)pyrf_evlist__add, 889 .ml_flags = METH_VARARGS | METH_KEYWORDS, 890 .ml_doc = PyDoc_STR("adds an event selector to the list.") 891 }, 892 { 893 .ml_name = "read_on_cpu", 894 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu, 895 .ml_flags = METH_VARARGS | METH_KEYWORDS, 896 .ml_doc = PyDoc_STR("reads an event.") 897 }, 898 { .ml_name = NULL, } 899 }; 900 901 static Py_ssize_t pyrf_evlist__length(PyObject *obj) 902 { 903 struct pyrf_evlist *pevlist = (void *)obj; 904 905 return pevlist->evlist.nr_entries; 906 } 907 908 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) 909 { 910 struct pyrf_evlist *pevlist = (void *)obj; 911 struct perf_evsel *pos; 912 913 if (i >= pevlist->evlist.nr_entries) 914 return NULL; 915 916 list_for_each_entry(pos, &pevlist->evlist.entries, node) 917 if (i-- == 0) 918 break; 919 920 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); 921 } 922 923 static PySequenceMethods pyrf_evlist__sequence_methods = { 924 .sq_length = pyrf_evlist__length, 925 .sq_item = pyrf_evlist__item, 926 }; 927 928 static char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object."); 929 930 static PyTypeObject pyrf_evlist__type = { 931 PyVarObject_HEAD_INIT(NULL, 0) 932 .tp_name = "perf.evlist", 933 .tp_basicsize = sizeof(struct pyrf_evlist), 934 .tp_dealloc = (destructor)pyrf_evlist__delete, 935 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 936 .tp_as_sequence = &pyrf_evlist__sequence_methods, 937 .tp_doc = pyrf_evlist__doc, 938 .tp_methods = pyrf_evlist__methods, 939 .tp_init = (initproc)pyrf_evlist__init, 940 }; 941 942 static int pyrf_evlist__setup_types(void) 943 { 944 pyrf_evlist__type.tp_new = PyType_GenericNew; 945 return PyType_Ready(&pyrf_evlist__type); 946 } 947 948 static struct { 949 const char *name; 950 int value; 951 } perf__constants[] = { 952 { "TYPE_HARDWARE", PERF_TYPE_HARDWARE }, 953 { "TYPE_SOFTWARE", PERF_TYPE_SOFTWARE }, 954 { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT }, 955 { "TYPE_HW_CACHE", PERF_TYPE_HW_CACHE }, 956 { "TYPE_RAW", PERF_TYPE_RAW }, 957 { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT }, 958 959 { "COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES }, 960 { "COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS }, 961 { "COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES }, 962 { "COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES }, 963 { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, 964 { "COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES }, 965 { "COUNT_HW_BUS_CYCLES", PERF_COUNT_HW_BUS_CYCLES }, 966 { "COUNT_HW_CACHE_L1D", PERF_COUNT_HW_CACHE_L1D }, 967 { "COUNT_HW_CACHE_L1I", PERF_COUNT_HW_CACHE_L1I }, 968 { "COUNT_HW_CACHE_LL", PERF_COUNT_HW_CACHE_LL }, 969 { "COUNT_HW_CACHE_DTLB", PERF_COUNT_HW_CACHE_DTLB }, 970 { "COUNT_HW_CACHE_ITLB", PERF_COUNT_HW_CACHE_ITLB }, 971 { "COUNT_HW_CACHE_BPU", PERF_COUNT_HW_CACHE_BPU }, 972 { "COUNT_HW_CACHE_OP_READ", PERF_COUNT_HW_CACHE_OP_READ }, 973 { "COUNT_HW_CACHE_OP_WRITE", PERF_COUNT_HW_CACHE_OP_WRITE }, 974 { "COUNT_HW_CACHE_OP_PREFETCH", PERF_COUNT_HW_CACHE_OP_PREFETCH }, 975 { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS }, 976 { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS }, 977 978 { "COUNT_HW_STALLED_CYCLES_FRONTEND", PERF_COUNT_HW_STALLED_CYCLES_FRONTEND }, 979 { "COUNT_HW_STALLED_CYCLES_BACKEND", PERF_COUNT_HW_STALLED_CYCLES_BACKEND }, 980 981 { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK }, 982 { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK }, 983 { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS }, 984 { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES }, 985 { "COUNT_SW_CPU_MIGRATIONS", PERF_COUNT_SW_CPU_MIGRATIONS }, 986 { "COUNT_SW_PAGE_FAULTS_MIN", PERF_COUNT_SW_PAGE_FAULTS_MIN }, 987 { "COUNT_SW_PAGE_FAULTS_MAJ", PERF_COUNT_SW_PAGE_FAULTS_MAJ }, 988 { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS }, 989 { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS }, 990 { "COUNT_SW_DUMMY", PERF_COUNT_SW_DUMMY }, 991 992 { "SAMPLE_IP", PERF_SAMPLE_IP }, 993 { "SAMPLE_TID", PERF_SAMPLE_TID }, 994 { "SAMPLE_TIME", PERF_SAMPLE_TIME }, 995 { "SAMPLE_ADDR", PERF_SAMPLE_ADDR }, 996 { "SAMPLE_READ", PERF_SAMPLE_READ }, 997 { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN }, 998 { "SAMPLE_ID", PERF_SAMPLE_ID }, 999 { "SAMPLE_CPU", PERF_SAMPLE_CPU }, 1000 { "SAMPLE_PERIOD", PERF_SAMPLE_PERIOD }, 1001 { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID }, 1002 { "SAMPLE_RAW", PERF_SAMPLE_RAW }, 1003 1004 { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED }, 1005 { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING }, 1006 { "FORMAT_ID", PERF_FORMAT_ID }, 1007 { "FORMAT_GROUP", PERF_FORMAT_GROUP }, 1008 1009 { "RECORD_MMAP", PERF_RECORD_MMAP }, 1010 { "RECORD_LOST", PERF_RECORD_LOST }, 1011 { "RECORD_COMM", PERF_RECORD_COMM }, 1012 { "RECORD_EXIT", PERF_RECORD_EXIT }, 1013 { "RECORD_THROTTLE", PERF_RECORD_THROTTLE }, 1014 { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE }, 1015 { "RECORD_FORK", PERF_RECORD_FORK }, 1016 { "RECORD_READ", PERF_RECORD_READ }, 1017 { "RECORD_SAMPLE", PERF_RECORD_SAMPLE }, 1018 { .name = NULL, }, 1019 }; 1020 1021 static PyMethodDef perf__methods[] = { 1022 { .ml_name = NULL, } 1023 }; 1024 1025 PyMODINIT_FUNC initperf(void) 1026 { 1027 PyObject *obj; 1028 int i; 1029 PyObject *dict, *module = Py_InitModule("perf", perf__methods); 1030 1031 if (module == NULL || 1032 pyrf_event__setup_types() < 0 || 1033 pyrf_evlist__setup_types() < 0 || 1034 pyrf_evsel__setup_types() < 0 || 1035 pyrf_thread_map__setup_types() < 0 || 1036 pyrf_cpu_map__setup_types() < 0) 1037 return; 1038 1039 page_size = sysconf(_SC_PAGE_SIZE); 1040 1041 Py_INCREF(&pyrf_evlist__type); 1042 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type); 1043 1044 Py_INCREF(&pyrf_evsel__type); 1045 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); 1046 1047 Py_INCREF(&pyrf_thread_map__type); 1048 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); 1049 1050 Py_INCREF(&pyrf_cpu_map__type); 1051 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type); 1052 1053 dict = PyModule_GetDict(module); 1054 if (dict == NULL) 1055 goto error; 1056 1057 for (i = 0; perf__constants[i].name != NULL; i++) { 1058 obj = PyInt_FromLong(perf__constants[i].value); 1059 if (obj == NULL) 1060 goto error; 1061 PyDict_SetItemString(dict, perf__constants[i].name, obj); 1062 Py_DECREF(obj); 1063 } 1064 1065 error: 1066 if (PyErr_Occurred()) 1067 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 1068 } 1069 1070 /* 1071 * Dummy, to avoid dragging all the test_attr infrastructure in the python 1072 * binding. 1073 */ 1074 void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu, 1075 int fd, int group_fd, unsigned long flags) 1076 { 1077 } 1078