1 // SPDX-License-Identifier: GPL-2.0 2 #define PY_SSIZE_T_CLEAN 3 #include <Python.h> 4 5 #include <inttypes.h> 6 #include <string.h> 7 8 #include <linux/err.h> 9 #include <poll.h> 10 #include <unistd.h> 11 12 #include <internal/lib.h> 13 #include <perf/cpumap.h> 14 #include <perf/mmap.h> 15 #include <structmember.h> 16 17 #include "addr_location.h" 18 #include "build-id.h" 19 #include "callchain.h" 20 #include "comm.h" 21 #include "config.h" 22 #include "counts.h" 23 #include "data.h" 24 #include "debug.h" 25 #include "dso.h" 26 #include "dwarf-regs.h" 27 #include "event.h" 28 #include "branch.h" 29 #include "evlist.h" 30 #include "evsel.h" 31 #include "expr.h" 32 #include "map.h" 33 #include "metricgroup.h" 34 #include "mmap.h" 35 #include "pmus.h" 36 #include "print_binary.h" 37 #include "record.h" 38 #include "sample.h" 39 #include "session.h" 40 #include "srccode.h" 41 #include "srcline.h" 42 #include "strbuf.h" 43 #include "symbol.h" 44 #include "stat.h" 45 #include "header.h" 46 #include "trace/beauty/syscalltbl.h" 47 #include "thread.h" 48 #include "thread_map.h" 49 #include "tool.h" 50 #include "tp_pmu.h" 51 #include "trace-event.h" 52 53 #ifdef HAVE_LIBTRACEEVENT 54 #include <event-parse.h> 55 #endif 56 57 PyMODINIT_FUNC PyInit_perf(void); 58 59 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel); 60 61 #define member_def(type, member, ptype, help) \ 62 { #member, ptype, \ 63 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \ 64 0, help } 65 66 #define sample_member_def(name, member, ptype, help) \ 67 { #name, ptype, \ 68 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \ 69 0, help } 70 71 #define CHECK_INITIALIZED(ptr, msg) \ 72 do { \ 73 if (!(ptr)) { \ 74 PyErr_SetString(PyExc_ValueError, msg " not initialized"); \ 75 return NULL; \ 76 } \ 77 } while (0) 78 79 #define CHECK_INITIALIZED_INT(ptr, msg) \ 80 do { \ 81 if (!(ptr)) { \ 82 PyErr_SetString(PyExc_ValueError, msg " not initialized"); \ 83 return -1; \ 84 } \ 85 } while (0) 86 87 struct pyrf_event { 88 PyObject_HEAD 89 /** @sample: The parsed sample from the event. */ 90 struct perf_sample sample; 91 /** @al: The address location from machine__resolve, lazily computed. */ 92 struct addr_location al; 93 /** @al_resolved: True when machine__resolve been called. */ 94 bool al_resolved; 95 /** @callchain: Resolved callchain, eagerly computed if requested. */ 96 PyObject *callchain; 97 /** @brstack: Resolved branch stack, eagerly computed if requested. */ 98 PyObject *brstack; 99 /** @event: The underlying perf_event that may be in a file or ring buffer. */ 100 union perf_event event; 101 }; 102 103 #define sample_members \ 104 sample_member_def(sample_pid, pid, T_INT, "event pid"), \ 105 sample_member_def(sample_tid, tid, T_INT, "event tid"), \ 106 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ 107 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \ 108 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \ 109 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \ 110 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), 111 112 static PyObject *pyrf_event__get_evsel(PyObject *self, void *closure __maybe_unused) 113 { 114 struct pyrf_event *pevent = (void *)self; 115 116 if (!pevent->sample.evsel) 117 Py_RETURN_NONE; 118 119 return pyrf_evsel__from_evsel(pevent->sample.evsel); 120 } 121 122 static PyGetSetDef pyrf_event__getset[] = { 123 { 124 .name = "evsel", 125 .get = pyrf_event__get_evsel, 126 .set = NULL, 127 .doc = "tracking event.", 128 }, 129 { .name = NULL, }, 130 }; 131 132 static void pyrf_event__delete(struct pyrf_event *pevent) 133 { 134 if (pevent->al_resolved) 135 addr_location__exit(&pevent->al); 136 Py_XDECREF(pevent->callchain); 137 Py_XDECREF(pevent->brstack); 138 perf_sample__exit(&pevent->sample); 139 Py_TYPE(pevent)->tp_free((PyObject *)pevent); 140 } 141 142 static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); 143 144 static PyMemberDef pyrf_mmap_event__members[] = { 145 sample_members 146 member_def(perf_event_header, type, T_UINT, "event type"), 147 member_def(perf_event_header, misc, T_USHORT, "event misc"), 148 member_def(perf_record_mmap, pid, T_UINT, "event pid"), 149 member_def(perf_record_mmap, tid, T_UINT, "event tid"), 150 member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"), 151 member_def(perf_record_mmap, len, T_ULONGLONG, "map length"), 152 member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"), 153 member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"), 154 { .name = NULL, }, 155 }; 156 157 static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent) 158 { 159 PyObject *ret; 160 char *s; 161 162 if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", " 163 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", " 164 "filename: %s }", 165 pevent->event.mmap.pid, pevent->event.mmap.tid, 166 pevent->event.mmap.start, pevent->event.mmap.len, 167 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 168 ret = PyErr_NoMemory(); 169 } else { 170 ret = PyUnicode_FromString(s); 171 free(s); 172 } 173 return ret; 174 } 175 176 static PyTypeObject pyrf_mmap_event__type = { 177 PyVarObject_HEAD_INIT(NULL, 0) 178 .tp_name = "perf.mmap_event", 179 .tp_basicsize = sizeof(struct pyrf_event), 180 .tp_dealloc = (destructor)pyrf_event__delete, 181 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 182 .tp_doc = pyrf_mmap_event__doc, 183 .tp_members = pyrf_mmap_event__members, 184 .tp_getset = pyrf_event__getset, 185 .tp_repr = (reprfunc)pyrf_mmap_event__repr, 186 }; 187 188 static const char pyrf_mmap2_event__doc[] = PyDoc_STR("perf mmap2 event object."); 189 190 static PyObject *pyrf_mmap2_event__get_maj(PyObject *self, void *closure __maybe_unused) 191 { 192 struct pyrf_event *pevent = (void *)self; 193 194 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) 195 Py_RETURN_NONE; 196 197 return PyLong_FromUnsignedLong(pevent->event.mmap2.maj); 198 } 199 200 static PyObject *pyrf_mmap2_event__get_min(PyObject *self, void *closure __maybe_unused) 201 { 202 struct pyrf_event *pevent = (void *)self; 203 204 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) 205 Py_RETURN_NONE; 206 207 return PyLong_FromUnsignedLong(pevent->event.mmap2.min); 208 } 209 210 static PyObject *pyrf_mmap2_event__get_ino(PyObject *self, void *closure __maybe_unused) 211 { 212 struct pyrf_event *pevent = (void *)self; 213 214 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) 215 Py_RETURN_NONE; 216 217 return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino); 218 } 219 220 static PyObject *pyrf_mmap2_event__get_ino_generation(PyObject *self, void *closure __maybe_unused) 221 { 222 struct pyrf_event *pevent = (void *)self; 223 224 if (pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) 225 Py_RETURN_NONE; 226 227 return PyLong_FromUnsignedLongLong(pevent->event.mmap2.ino_generation); 228 } 229 230 static PyObject *pyrf_mmap2_event__get_build_id(PyObject *self, void *closure __maybe_unused) 231 { 232 struct pyrf_event *pevent = (void *)self; 233 234 if (!(pevent->event.header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID)) 235 Py_RETURN_NONE; 236 237 int size = pevent->event.mmap2.build_id_size; 238 239 if (size > 20) 240 size = 20; 241 242 return PyBytes_FromStringAndSize((const char *)pevent->event.mmap2.build_id, size); 243 } 244 245 static PyGetSetDef pyrf_mmap2_event__getset[] = { 246 { 247 .name = "evsel", 248 .get = pyrf_event__get_evsel, 249 .set = NULL, 250 .doc = "tracking event.", 251 }, 252 { 253 .name = "maj", 254 .get = pyrf_mmap2_event__get_maj, 255 .set = NULL, 256 .doc = "major number.", 257 }, 258 { 259 .name = "min", 260 .get = pyrf_mmap2_event__get_min, 261 .set = NULL, 262 .doc = "minor number.", 263 }, 264 { 265 .name = "ino", 266 .get = pyrf_mmap2_event__get_ino, 267 .set = NULL, 268 .doc = "inode number.", 269 }, 270 { 271 .name = "ino_generation", 272 .get = pyrf_mmap2_event__get_ino_generation, 273 .set = NULL, 274 .doc = "inode generation.", 275 }, 276 { 277 .name = "build_id", 278 .get = pyrf_mmap2_event__get_build_id, 279 .set = NULL, 280 .doc = "binary build ID.", 281 }, 282 { .name = NULL, }, 283 }; 284 285 static PyMemberDef pyrf_mmap2_event__members[] = { 286 sample_members 287 member_def(perf_event_header, type, T_UINT, "event type"), 288 member_def(perf_event_header, misc, T_USHORT, "event misc"), 289 member_def(perf_record_mmap2, pid, T_UINT, "event pid"), 290 member_def(perf_record_mmap2, tid, T_UINT, "event tid"), 291 member_def(perf_record_mmap2, start, T_ULONGLONG, "start of the map"), 292 member_def(perf_record_mmap2, len, T_ULONGLONG, "map length"), 293 member_def(perf_record_mmap2, pgoff, T_ULONGLONG, "page offset"), 294 member_def(perf_record_mmap2, prot, T_UINT, "protection"), 295 member_def(perf_record_mmap2, flags, T_UINT, "flags"), 296 member_def(perf_record_mmap2, filename, T_STRING_INPLACE, "backing store"), 297 { .name = NULL, }, 298 }; 299 300 static PyObject *pyrf_mmap2_event__repr(const struct pyrf_event *pevent) 301 { 302 PyObject *ret; 303 char *s; 304 305 if (asprintf(&s, "{ type: mmap2, pid: %u, tid: %u, start: %#" PRI_lx64 ", length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", flags: %#x, prot: %#x, filename: %s }", 306 pevent->event.mmap2.pid, pevent->event.mmap2.tid, 307 pevent->event.mmap2.start, pevent->event.mmap2.len, 308 pevent->event.mmap2.pgoff, pevent->event.mmap2.flags, 309 pevent->event.mmap2.prot, pevent->event.mmap2.filename) < 0) 310 return PyErr_NoMemory(); 311 312 ret = PyUnicode_FromString(s); 313 free(s); 314 return ret; 315 } 316 317 static PyTypeObject pyrf_mmap2_event__type = { 318 PyVarObject_HEAD_INIT(NULL, 0) 319 .tp_name = "perf.mmap2_event", 320 .tp_basicsize = sizeof(struct pyrf_event), 321 .tp_dealloc = (destructor)pyrf_event__delete, 322 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 323 .tp_doc = pyrf_mmap2_event__doc, 324 .tp_members = pyrf_mmap2_event__members, 325 .tp_getset = pyrf_mmap2_event__getset, 326 .tp_repr = (reprfunc)pyrf_mmap2_event__repr, 327 }; 328 329 static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); 330 331 static PyMemberDef pyrf_task_event__members[] = { 332 sample_members 333 member_def(perf_event_header, type, T_UINT, "event type"), 334 member_def(perf_record_fork, pid, T_UINT, "event pid"), 335 member_def(perf_record_fork, ppid, T_UINT, "event ppid"), 336 member_def(perf_record_fork, tid, T_UINT, "event tid"), 337 member_def(perf_record_fork, ptid, T_UINT, "event ptid"), 338 member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"), 339 { .name = NULL, }, 340 }; 341 342 static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent) 343 { 344 return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 345 "ptid: %u, time: %" PRI_lu64 "}", 346 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 347 pevent->event.fork.pid, 348 pevent->event.fork.ppid, 349 pevent->event.fork.tid, 350 pevent->event.fork.ptid, 351 pevent->event.fork.time); 352 } 353 354 static PyTypeObject pyrf_task_event__type = { 355 PyVarObject_HEAD_INIT(NULL, 0) 356 .tp_name = "perf.task_event", 357 .tp_basicsize = sizeof(struct pyrf_event), 358 .tp_dealloc = (destructor)pyrf_event__delete, 359 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 360 .tp_doc = pyrf_task_event__doc, 361 .tp_members = pyrf_task_event__members, 362 .tp_getset = pyrf_event__getset, 363 .tp_repr = (reprfunc)pyrf_task_event__repr, 364 }; 365 366 static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); 367 368 static PyMemberDef pyrf_comm_event__members[] = { 369 sample_members 370 member_def(perf_event_header, type, T_UINT, "event type"), 371 member_def(perf_record_comm, pid, T_UINT, "event pid"), 372 member_def(perf_record_comm, tid, T_UINT, "event tid"), 373 member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"), 374 { .name = NULL, }, 375 }; 376 377 static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent) 378 { 379 return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 380 pevent->event.comm.pid, 381 pevent->event.comm.tid, 382 pevent->event.comm.comm); 383 } 384 385 static PyTypeObject pyrf_comm_event__type = { 386 PyVarObject_HEAD_INIT(NULL, 0) 387 .tp_name = "perf.comm_event", 388 .tp_basicsize = sizeof(struct pyrf_event), 389 .tp_dealloc = (destructor)pyrf_event__delete, 390 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 391 .tp_doc = pyrf_comm_event__doc, 392 .tp_members = pyrf_comm_event__members, 393 .tp_getset = pyrf_event__getset, 394 .tp_repr = (reprfunc)pyrf_comm_event__repr, 395 }; 396 397 static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); 398 399 static PyMemberDef pyrf_throttle_event__members[] = { 400 sample_members 401 member_def(perf_event_header, type, T_UINT, "event type"), 402 member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"), 403 member_def(perf_record_throttle, id, T_ULONGLONG, "event id"), 404 member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"), 405 { .name = NULL, }, 406 }; 407 408 static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent) 409 { 410 const struct perf_record_throttle *te = (const struct perf_record_throttle *) 411 (&pevent->event.header + 1); 412 413 return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64 414 ", stream_id: %" PRI_lu64 " }", 415 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 416 te->time, te->id, te->stream_id); 417 } 418 419 static PyTypeObject pyrf_throttle_event__type = { 420 PyVarObject_HEAD_INIT(NULL, 0) 421 .tp_name = "perf.throttle_event", 422 .tp_basicsize = sizeof(struct pyrf_event), 423 .tp_dealloc = (destructor)pyrf_event__delete, 424 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 425 .tp_doc = pyrf_throttle_event__doc, 426 .tp_members = pyrf_throttle_event__members, 427 .tp_getset = pyrf_event__getset, 428 .tp_repr = (reprfunc)pyrf_throttle_event__repr, 429 }; 430 431 static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); 432 433 static PyMemberDef pyrf_lost_event__members[] = { 434 sample_members 435 member_def(perf_event_header, type, T_UINT, "event type"), 436 member_def(perf_record_lost, id, T_ULONGLONG, "event id"), 437 member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"), 438 { .name = NULL, }, 439 }; 440 441 static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent) 442 { 443 PyObject *ret; 444 char *s; 445 446 if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", " 447 "lost: %#" PRI_lx64 " }", 448 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 449 ret = PyErr_NoMemory(); 450 } else { 451 ret = PyUnicode_FromString(s); 452 free(s); 453 } 454 return ret; 455 } 456 457 static PyTypeObject pyrf_lost_event__type = { 458 PyVarObject_HEAD_INIT(NULL, 0) 459 .tp_name = "perf.lost_event", 460 .tp_basicsize = sizeof(struct pyrf_event), 461 .tp_dealloc = (destructor)pyrf_event__delete, 462 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 463 .tp_doc = pyrf_lost_event__doc, 464 .tp_members = pyrf_lost_event__members, 465 .tp_getset = pyrf_event__getset, 466 .tp_repr = (reprfunc)pyrf_lost_event__repr, 467 }; 468 469 static const char pyrf_stat_event__doc[] = PyDoc_STR("perf stat event object."); 470 471 static PyMemberDef pyrf_stat_event__members[] = { 472 sample_members 473 member_def(perf_event_header, type, T_UINT, "event type"), 474 member_def(perf_record_stat, id, T_ULONGLONG, "event id"), 475 member_def(perf_record_stat, cpu, T_UINT, "event cpu"), 476 member_def(perf_record_stat, thread, T_UINT, "event thread"), 477 member_def(perf_record_stat, val, T_ULONGLONG, "counter value"), 478 member_def(perf_record_stat, ena, T_ULONGLONG, "enabled time"), 479 member_def(perf_record_stat, run, T_ULONGLONG, "running time"), 480 { .name = NULL, }, 481 }; 482 483 static PyObject *pyrf_stat_event__repr(const struct pyrf_event *pevent) 484 { 485 return PyUnicode_FromFormat( 486 "{ type: stat, id: %llu, cpu: %u, thread: %u, val: %llu, ena: %llu, run: %llu }", 487 pevent->event.stat.id, 488 pevent->event.stat.cpu, 489 pevent->event.stat.thread, 490 pevent->event.stat.val, 491 pevent->event.stat.ena, 492 pevent->event.stat.run); 493 } 494 495 static PyTypeObject pyrf_stat_event__type = { 496 PyVarObject_HEAD_INIT(NULL, 0) 497 .tp_name = "perf.stat_event", 498 .tp_basicsize = sizeof(struct pyrf_event), 499 .tp_new = PyType_GenericNew, 500 .tp_dealloc = (destructor)pyrf_event__delete, 501 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 502 .tp_doc = pyrf_stat_event__doc, 503 .tp_members = pyrf_stat_event__members, 504 .tp_getset = pyrf_event__getset, 505 .tp_repr = (reprfunc)pyrf_stat_event__repr, 506 }; 507 508 static const char pyrf_stat_round_event__doc[] = PyDoc_STR("perf stat round event object."); 509 510 static PyMemberDef pyrf_stat_round_event__members[] = { 511 sample_members 512 member_def(perf_event_header, type, T_UINT, "event type"), 513 { .name = "stat_round_type", .type = T_ULONGLONG, 514 .offset = offsetof(struct pyrf_event, event) + offsetof(struct perf_record_stat_round, type), 515 .doc = "round type" }, 516 member_def(perf_record_stat_round, time, T_ULONGLONG, "round time"), 517 { .name = NULL, }, 518 }; 519 520 static PyObject *pyrf_stat_round_event__repr(const struct pyrf_event *pevent) 521 { 522 return PyUnicode_FromFormat("{ type: stat_round, type: %llu, time: %llu }", 523 pevent->event.stat_round.type, 524 pevent->event.stat_round.time); 525 } 526 527 static PyTypeObject pyrf_stat_round_event__type = { 528 PyVarObject_HEAD_INIT(NULL, 0) 529 .tp_name = "perf.stat_round_event", 530 .tp_basicsize = sizeof(struct pyrf_event), 531 .tp_new = PyType_GenericNew, 532 .tp_dealloc = (destructor)pyrf_event__delete, 533 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 534 .tp_doc = pyrf_stat_round_event__doc, 535 .tp_members = pyrf_stat_round_event__members, 536 .tp_getset = pyrf_event__getset, 537 .tp_repr = (reprfunc)pyrf_stat_round_event__repr, 538 }; 539 540 static const char pyrf_read_event__doc[] = PyDoc_STR("perf read event object."); 541 542 static PyMemberDef pyrf_read_event__members[] = { 543 sample_members 544 member_def(perf_event_header, type, T_UINT, "event type"), 545 member_def(perf_record_read, pid, T_UINT, "event pid"), 546 member_def(perf_record_read, tid, T_UINT, "event tid"), 547 { .name = NULL, }, 548 }; 549 550 static PyObject *pyrf_read_event__repr(const struct pyrf_event *pevent) 551 { 552 return PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }", 553 pevent->event.read.pid, 554 pevent->event.read.tid); 555 /* 556 * FIXME: return the array of read values, 557 * making this method useful ;-) 558 */ 559 } 560 561 static PyTypeObject pyrf_read_event__type = { 562 PyVarObject_HEAD_INIT(NULL, 0) 563 .tp_name = "perf.read_event", 564 .tp_basicsize = sizeof(struct pyrf_event), 565 .tp_dealloc = (destructor)pyrf_event__delete, 566 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 567 .tp_doc = pyrf_read_event__doc, 568 .tp_members = pyrf_read_event__members, 569 .tp_getset = pyrf_event__getset, 570 .tp_repr = (reprfunc)pyrf_read_event__repr, 571 }; 572 573 static const char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object."); 574 575 static PyMemberDef pyrf_sample_event__members[] = { 576 sample_members 577 sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"), 578 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), 579 sample_member_def(sample_phys_addr, phys_addr, T_ULONGLONG, "event physical addr"), 580 sample_member_def(sample_weight, weight, T_ULONGLONG, "event weight"), 581 sample_member_def(sample_data_src, data_src, T_ULONGLONG, "event data source"), 582 sample_member_def(sample_insn_count, insn_cnt, T_ULONGLONG, "event instruction count"), 583 sample_member_def(sample_cyc_count, cyc_cnt, T_ULONGLONG, "event cycle count"), 584 member_def(perf_event_header, type, T_UINT, "event type"), 585 { .name = NULL, }, 586 }; 587 588 static PyObject *pyrf_sample_event__repr(const struct pyrf_event *pevent) 589 { 590 PyObject *ret; 591 char *s; 592 593 if (asprintf(&s, "{ type: sample }") < 0) { 594 ret = PyErr_NoMemory(); 595 } else { 596 ret = PyUnicode_FromString(s); 597 free(s); 598 } 599 return ret; 600 } 601 602 #ifdef HAVE_LIBTRACEEVENT 603 static bool is_tracepoint(const struct pyrf_event *pevent) 604 { 605 if (!pevent->sample.evsel) 606 return false; 607 return pevent->sample.evsel->core.attr.type == PERF_TYPE_TRACEPOINT; 608 } 609 610 static PyObject* 611 tracepoint_field(const struct pyrf_event *pe, struct tep_format_field *field) 612 { 613 struct tep_handle *pevent = field->event->tep; 614 void *data = pe->sample.raw_data; 615 PyObject *ret = NULL; 616 unsigned long long val; 617 unsigned int offset, len; 618 619 if (field->flags & TEP_FIELD_IS_ARRAY) { 620 offset = field->offset; 621 len = field->size; 622 if (field->flags & TEP_FIELD_IS_DYNAMIC) { 623 val = tep_read_number(pevent, data + offset, len); 624 offset = val; 625 len = offset >> 16; 626 offset &= 0xffff; 627 if (tep_field_is_relative(field->flags)) 628 offset += field->offset + field->size; 629 } 630 if (field->flags & TEP_FIELD_IS_STRING && 631 is_printable_array(data + offset, len)) { 632 ret = PyUnicode_FromString((char *)data + offset); 633 } else { 634 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 635 field->flags &= ~TEP_FIELD_IS_STRING; 636 } 637 } else { 638 val = tep_read_number(pevent, data + field->offset, 639 field->size); 640 if (field->flags & TEP_FIELD_IS_POINTER) 641 ret = PyLong_FromUnsignedLong((unsigned long) val); 642 else if (field->flags & TEP_FIELD_IS_SIGNED) 643 ret = PyLong_FromLong((long) val); 644 else 645 ret = PyLong_FromUnsignedLong((unsigned long) val); 646 } 647 648 return ret; 649 } 650 651 static PyObject* 652 get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 653 { 654 struct evsel *evsel = pevent->sample.evsel; 655 struct tep_event *tp_format = evsel__tp_format(evsel); 656 struct tep_format_field *field; 657 658 if (IS_ERR_OR_NULL(tp_format)) 659 return NULL; 660 661 PyObject *obj = PyObject_Str(attr_name); 662 if (obj == NULL) 663 return NULL; 664 665 const char *str = PyUnicode_AsUTF8(obj); 666 if (str == NULL) { 667 Py_DECREF(obj); 668 return NULL; 669 } 670 671 field = tep_find_any_field(tp_format, str); 672 Py_DECREF(obj); 673 return field ? tracepoint_field(pevent, field) : NULL; 674 } 675 #endif /* HAVE_LIBTRACEEVENT */ 676 677 static int pyrf_sample_event__resolve_al(struct pyrf_event *pevent) 678 { 679 struct evsel *evsel = pevent->sample.evsel; 680 struct evlist *evlist = evsel ? evsel->evlist : NULL; 681 struct perf_session *session = evlist ? evlist__session(evlist) : NULL; 682 683 if (pevent->al_resolved) 684 return 0; 685 686 if (!session) 687 return -1; 688 689 addr_location__init(&pevent->al); 690 if (machine__resolve(&session->machines.host, &pevent->al, &pevent->sample) < 0) { 691 addr_location__exit(&pevent->al); 692 return -1; 693 } 694 695 pevent->al_resolved = true; 696 return 0; 697 } 698 699 static PyObject *pyrf_sample_event__get_dso(struct pyrf_event *pevent, 700 void *closure __maybe_unused) 701 { 702 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 703 Py_RETURN_NONE; 704 705 return PyUnicode_FromString(dso__name(map__dso(pevent->al.map))); 706 } 707 708 static PyObject *pyrf_sample_event__get_dso_long_name(struct pyrf_event *pevent, 709 void *closure __maybe_unused) 710 { 711 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 712 Py_RETURN_NONE; 713 714 return PyUnicode_FromString(dso__long_name(map__dso(pevent->al.map))); 715 } 716 717 static PyObject *pyrf_sample_event__get_dso_bid(struct pyrf_event *pevent, 718 void *closure __maybe_unused) 719 { 720 char sbuild_id[SBUILD_ID_SIZE]; 721 722 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 723 Py_RETURN_NONE; 724 725 build_id__snprintf(dso__bid(map__dso(pevent->al.map)), sbuild_id, sizeof(sbuild_id)); 726 return PyUnicode_FromString(sbuild_id); 727 } 728 729 static PyObject *pyrf_sample_event__get_map_start(struct pyrf_event *pevent, 730 void *closure __maybe_unused) 731 { 732 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 733 Py_RETURN_NONE; 734 735 return PyLong_FromUnsignedLong(map__start(pevent->al.map)); 736 } 737 738 static PyObject *pyrf_sample_event__get_map_end(struct pyrf_event *pevent, 739 void *closure __maybe_unused) 740 { 741 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 742 Py_RETURN_NONE; 743 744 return PyLong_FromUnsignedLong(map__end(pevent->al.map)); 745 } 746 747 static PyObject *pyrf_sample_event__get_map_pgoff(struct pyrf_event *pevent, 748 void *closure __maybe_unused) 749 { 750 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.map) 751 Py_RETURN_NONE; 752 753 return PyLong_FromUnsignedLongLong(map__pgoff(pevent->al.map)); 754 } 755 756 static PyObject *pyrf_sample_event__get_symbol(struct pyrf_event *pevent, 757 void *closure __maybe_unused) 758 { 759 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym) 760 Py_RETURN_NONE; 761 762 return PyUnicode_FromString(pevent->al.sym->name); 763 } 764 765 static PyObject *pyrf_sample_event__get_sym_start(struct pyrf_event *pevent, 766 void *closure __maybe_unused) 767 { 768 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym) 769 Py_RETURN_NONE; 770 771 return PyLong_FromUnsignedLongLong(pevent->al.sym->start); 772 } 773 774 static PyObject *pyrf_sample_event__get_sym_end(struct pyrf_event *pevent, 775 void *closure __maybe_unused) 776 { 777 if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym) 778 Py_RETURN_NONE; 779 780 return PyLong_FromUnsignedLongLong(pevent->al.sym->end); 781 } 782 783 static PyObject *pyrf_sample_event__get_raw_buf(struct pyrf_event *pevent, 784 void *closure __maybe_unused) 785 { 786 if (pevent->event.header.type != PERF_RECORD_SAMPLE) 787 Py_RETURN_NONE; 788 789 return PyBytes_FromStringAndSize((const char *)pevent->sample.raw_data, 790 pevent->sample.raw_size); 791 } 792 793 static PyObject *pyrf_sample_event__srccode(PyObject *self, PyObject *args) 794 { 795 struct pyrf_event *pevent = (void *)self; 796 u64 addr = pevent->sample.ip; 797 char *srcfile = NULL; 798 char *srccode = NULL; 799 unsigned int line = 0; 800 int len = 0; 801 PyObject *result; 802 struct addr_location al; 803 804 if (!PyArg_ParseTuple(args, "|K", &addr)) 805 return NULL; 806 807 if (pyrf_sample_event__resolve_al(pevent) < 0) 808 Py_RETURN_NONE; 809 810 if (addr != pevent->sample.ip) { 811 addr_location__init(&al); 812 thread__find_symbol_fb(pevent->al.thread, pevent->sample.cpumode, addr, &al); 813 } else { 814 addr_location__init(&al); 815 al.thread = thread__get(pevent->al.thread); 816 al.map = map__get(pevent->al.map); 817 al.sym = pevent->al.sym; 818 al.addr = pevent->al.addr; 819 } 820 821 if (al.map) { 822 struct dso *dso = map__dso(al.map); 823 824 if (dso) { 825 srcfile = get_srcline_split(dso, map__rip_2objdump(al.map, addr), 826 &line); 827 } 828 } 829 addr_location__exit(&al); 830 831 if (srcfile) { 832 srccode = find_sourceline(srcfile, line, &len); 833 result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len); 834 free(srcfile); 835 } else { 836 result = Py_BuildValue("(sIs#)", NULL, 0, NULL, (Py_ssize_t)0); 837 } 838 839 return result; 840 } 841 842 static PyObject *pyrf_sample_event__insn(PyObject *self, PyObject *args __maybe_unused) 843 { 844 struct pyrf_event *pevent = (void *)self; 845 struct thread *thread; 846 struct machine *machine; 847 848 if (pyrf_sample_event__resolve_al(pevent) < 0) 849 Py_RETURN_NONE; 850 851 thread = pevent->al.thread; 852 853 if (!thread || !thread__maps(thread)) 854 Py_RETURN_NONE; 855 856 machine = maps__machine(thread__maps(thread)); 857 if (!machine) 858 Py_RETURN_NONE; 859 860 if (pevent->sample.ip && !pevent->sample.insn_len) 861 perf_sample__fetch_insn(&pevent->sample, thread, machine); 862 863 if (!pevent->sample.insn_len) 864 Py_RETURN_NONE; 865 866 return PyBytes_FromStringAndSize((const char *)pevent->sample.insn, 867 pevent->sample.insn_len); 868 } 869 870 struct pyrf_callchain_node { 871 PyObject_HEAD 872 u64 ip; 873 struct map *map; 874 struct symbol *sym; 875 }; 876 877 static void pyrf_callchain_node__delete(struct pyrf_callchain_node *pnode) 878 { 879 map__put(pnode->map); 880 Py_TYPE(pnode)->tp_free((PyObject *)pnode); 881 } 882 883 static PyObject *pyrf_callchain_node__get_ip(struct pyrf_callchain_node *pnode, 884 void *closure __maybe_unused) 885 { 886 return PyLong_FromUnsignedLongLong(pnode->ip); 887 } 888 889 static PyObject *pyrf_callchain_node__get_symbol(struct pyrf_callchain_node *pnode, 890 void *closure __maybe_unused) 891 { 892 if (pnode->sym) 893 return PyUnicode_FromString(pnode->sym->name); 894 return PyUnicode_FromString("[unknown]"); 895 } 896 897 static PyObject *pyrf_callchain_node__get_dso(struct pyrf_callchain_node *pnode, 898 void *closure __maybe_unused) 899 { 900 const char *dsoname = "[unknown]"; 901 902 if (pnode->map) { 903 struct dso *dso = map__dso(pnode->map); 904 905 if (dso) { 906 if (symbol_conf.show_kernel_path && dso__long_name(dso)) 907 dsoname = dso__long_name(dso); 908 else 909 dsoname = dso__name(dso); 910 } 911 } 912 return PyUnicode_FromString(dsoname); 913 } 914 915 static PyGetSetDef pyrf_callchain_node__getset[] = { 916 { .name = "ip", .get = (getter)pyrf_callchain_node__get_ip, }, 917 { .name = "symbol", .get = (getter)pyrf_callchain_node__get_symbol, }, 918 { .name = "dso", .get = (getter)pyrf_callchain_node__get_dso, }, 919 { .name = NULL, }, 920 }; 921 922 static PyTypeObject pyrf_callchain_node__type = { 923 PyVarObject_HEAD_INIT(NULL, 0) 924 .tp_name = "perf.callchain_node", 925 .tp_basicsize = sizeof(struct pyrf_callchain_node), 926 .tp_dealloc = (destructor)pyrf_callchain_node__delete, 927 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 928 .tp_doc = "perf callchain node object.", 929 .tp_getset = pyrf_callchain_node__getset, 930 }; 931 932 struct pyrf_callchain_frame { 933 u64 ip; 934 struct map *map; 935 struct symbol *sym; 936 }; 937 938 struct pyrf_callchain { 939 PyObject_HEAD 940 struct pyrf_callchain_frame *frames; 941 u64 nr_frames; 942 }; 943 944 static void pyrf_callchain__delete(struct pyrf_callchain *pchain) 945 { 946 if (pchain->frames) { 947 for (u64 i = 0; i < pchain->nr_frames; i++) 948 map__put(pchain->frames[i].map); 949 free(pchain->frames); 950 } 951 Py_TYPE(pchain)->tp_free((PyObject *)pchain); 952 } 953 954 static Py_ssize_t pyrf_callchain__length(PyObject *obj) 955 { 956 struct pyrf_callchain *pchain = (void *)obj; 957 958 return pchain->nr_frames; 959 } 960 961 static PyObject *pyrf_callchain__item(PyObject *obj, Py_ssize_t i) 962 { 963 struct pyrf_callchain *pchain = (void *)obj; 964 struct pyrf_callchain_node *pnode; 965 966 if (i < 0 || i >= (Py_ssize_t)pchain->nr_frames) { 967 PyErr_SetString(PyExc_IndexError, "Index out of range"); 968 return NULL; 969 } 970 971 pnode = PyObject_New(struct pyrf_callchain_node, &pyrf_callchain_node__type); 972 if (!pnode) 973 return NULL; 974 975 pnode->ip = pchain->frames[i].ip; 976 pnode->map = map__get(pchain->frames[i].map); 977 pnode->sym = pchain->frames[i].sym; 978 979 return (PyObject *)pnode; 980 } 981 982 static PySequenceMethods pyrf_callchain__sequence_methods = { 983 .sq_length = pyrf_callchain__length, 984 .sq_item = pyrf_callchain__item, 985 }; 986 987 static PyTypeObject pyrf_callchain__type = { 988 PyVarObject_HEAD_INIT(NULL, 0) 989 .tp_name = "perf.callchain", 990 .tp_basicsize = sizeof(struct pyrf_callchain), 991 .tp_dealloc = (destructor)pyrf_callchain__delete, 992 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 993 .tp_doc = "perf callchain object.", 994 .tp_as_sequence = &pyrf_callchain__sequence_methods, 995 }; 996 997 static PyObject *pyrf_sample_event__get_callchain(PyObject *self, void *closure __maybe_unused) 998 { 999 struct pyrf_event *pevent = (void *)self; 1000 1001 if (!pevent->callchain) 1002 Py_RETURN_NONE; 1003 1004 Py_INCREF(pevent->callchain); 1005 return pevent->callchain; 1006 } 1007 1008 struct pyrf_branch_entry { 1009 PyObject_HEAD 1010 u64 from; 1011 u64 to; 1012 struct branch_flags flags; 1013 }; 1014 1015 static void pyrf_branch_entry__delete(struct pyrf_branch_entry *pentry) 1016 { 1017 Py_TYPE(pentry)->tp_free((PyObject *)pentry); 1018 } 1019 1020 static PyObject *pyrf_branch_entry__get_from(struct pyrf_branch_entry *pentry, 1021 void *closure __maybe_unused) 1022 { 1023 return PyLong_FromUnsignedLongLong(pentry->from); 1024 } 1025 1026 static PyObject *pyrf_branch_entry__get_to(struct pyrf_branch_entry *pentry, 1027 void *closure __maybe_unused) 1028 { 1029 return PyLong_FromUnsignedLongLong(pentry->to); 1030 } 1031 1032 static PyObject *pyrf_branch_entry__get_mispred(struct pyrf_branch_entry *pentry, 1033 void *closure __maybe_unused) 1034 { 1035 return PyBool_FromLong(pentry->flags.mispred); 1036 } 1037 1038 static PyObject *pyrf_branch_entry__get_predicted(struct pyrf_branch_entry *pentry, 1039 void *closure __maybe_unused) 1040 { 1041 return PyBool_FromLong(pentry->flags.predicted); 1042 } 1043 1044 static PyObject *pyrf_branch_entry__get_in_tx(struct pyrf_branch_entry *pentry, 1045 void *closure __maybe_unused) 1046 { 1047 return PyBool_FromLong(pentry->flags.in_tx); 1048 } 1049 1050 static PyObject *pyrf_branch_entry__get_abort(struct pyrf_branch_entry *pentry, 1051 void *closure __maybe_unused) 1052 { 1053 return PyBool_FromLong(pentry->flags.abort); 1054 } 1055 1056 static PyObject *pyrf_branch_entry__get_cycles(struct pyrf_branch_entry *pentry, 1057 void *closure __maybe_unused) 1058 { 1059 return PyLong_FromUnsignedLongLong(pentry->flags.cycles); 1060 } 1061 1062 static PyObject *pyrf_branch_entry__get_type(struct pyrf_branch_entry *pentry, 1063 void *closure __maybe_unused) 1064 { 1065 return PyLong_FromUnsignedLongLong((unsigned long long)pentry->flags.type); 1066 } 1067 1068 static PyGetSetDef pyrf_branch_entry__getset[] = { 1069 { .name = "from_ip", .get = (getter)pyrf_branch_entry__get_from, }, 1070 { .name = "to_ip", .get = (getter)pyrf_branch_entry__get_to, }, 1071 { .name = "mispred", .get = (getter)pyrf_branch_entry__get_mispred, }, 1072 { .name = "predicted", .get = (getter)pyrf_branch_entry__get_predicted, }, 1073 { .name = "in_tx", .get = (getter)pyrf_branch_entry__get_in_tx, }, 1074 { .name = "abort", .get = (getter)pyrf_branch_entry__get_abort, }, 1075 { .name = "cycles", .get = (getter)pyrf_branch_entry__get_cycles, }, 1076 { .name = "type", .get = (getter)pyrf_branch_entry__get_type, }, 1077 { .name = NULL, }, 1078 }; 1079 1080 static PyTypeObject pyrf_branch_entry__type = { 1081 PyVarObject_HEAD_INIT(NULL, 0) 1082 .tp_name = "perf.branch_entry", 1083 .tp_basicsize = sizeof(struct pyrf_branch_entry), 1084 .tp_dealloc = (destructor)pyrf_branch_entry__delete, 1085 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1086 .tp_doc = "perf branch entry object.", 1087 .tp_getset = pyrf_branch_entry__getset, 1088 }; 1089 1090 struct pyrf_branch_stack { 1091 PyObject_HEAD 1092 struct branch_entry *entries; 1093 u64 nr; 1094 }; 1095 1096 static void pyrf_branch_stack__delete(struct pyrf_branch_stack *pstack) 1097 { 1098 free(pstack->entries); 1099 Py_TYPE(pstack)->tp_free((PyObject *)pstack); 1100 } 1101 1102 static Py_ssize_t pyrf_branch_stack__length(PyObject *obj) 1103 { 1104 struct pyrf_branch_stack *pstack = (void *)obj; 1105 1106 return pstack->nr; 1107 } 1108 1109 static PyObject *pyrf_branch_stack__item(PyObject *obj, Py_ssize_t i) 1110 { 1111 struct pyrf_branch_stack *pstack = (void *)obj; 1112 struct pyrf_branch_entry *pentry; 1113 1114 if (i < 0 || i >= (Py_ssize_t)pstack->nr) { 1115 PyErr_SetString(PyExc_IndexError, "Index out of range"); 1116 return NULL; 1117 } 1118 1119 pentry = PyObject_New(struct pyrf_branch_entry, &pyrf_branch_entry__type); 1120 if (!pentry) 1121 return NULL; 1122 1123 pentry->from = pstack->entries[i].from; 1124 pentry->to = pstack->entries[i].to; 1125 pentry->flags = pstack->entries[i].flags; 1126 1127 return (PyObject *)pentry; 1128 } 1129 1130 static PySequenceMethods pyrf_branch_stack__sequence_methods = { 1131 .sq_length = pyrf_branch_stack__length, 1132 .sq_item = pyrf_branch_stack__item, 1133 }; 1134 1135 static PyTypeObject pyrf_branch_stack__type = { 1136 PyVarObject_HEAD_INIT(NULL, 0) 1137 .tp_name = "perf.branch_stack", 1138 .tp_basicsize = sizeof(struct pyrf_branch_stack), 1139 .tp_dealloc = (destructor)pyrf_branch_stack__delete, 1140 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1141 .tp_doc = "perf branch stack object.", 1142 .tp_as_sequence = &pyrf_branch_stack__sequence_methods, 1143 }; 1144 1145 static PyObject *pyrf_sample_event__get_brstack(PyObject *self, void *closure __maybe_unused) 1146 { 1147 struct pyrf_event *pevent = (void *)self; 1148 1149 if (!pevent->brstack) 1150 Py_RETURN_NONE; 1151 1152 Py_INCREF(pevent->brstack); 1153 return pevent->brstack; 1154 } 1155 1156 static PyObject* 1157 pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name) 1158 { 1159 PyObject *obj = NULL; 1160 1161 #ifdef HAVE_LIBTRACEEVENT 1162 if (is_tracepoint(pevent)) 1163 obj = get_tracepoint_field(pevent, attr_name); 1164 #endif 1165 1166 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name); 1167 } 1168 1169 static PyGetSetDef pyrf_sample_event__getset[] = { 1170 { 1171 .name = "callchain", 1172 .get = pyrf_sample_event__get_callchain, 1173 .set = NULL, 1174 .doc = "event callchain.", 1175 }, 1176 { 1177 .name = "brstack", 1178 .get = pyrf_sample_event__get_brstack, 1179 .set = NULL, 1180 .doc = "event branch stack.", 1181 }, 1182 { 1183 .name = "raw_buf", 1184 .get = (getter)pyrf_sample_event__get_raw_buf, 1185 .set = NULL, 1186 .doc = "event raw buffer.", 1187 }, 1188 { 1189 .name = "evsel", 1190 .get = pyrf_event__get_evsel, 1191 .set = NULL, 1192 .doc = "tracking event.", 1193 }, 1194 { 1195 .name = "dso", 1196 .get = (getter)pyrf_sample_event__get_dso, 1197 .set = NULL, 1198 .doc = "event dso short name.", 1199 }, 1200 { 1201 .name = "dso_long_name", 1202 .get = (getter)pyrf_sample_event__get_dso_long_name, 1203 .set = NULL, 1204 .doc = "event dso long name.", 1205 }, 1206 { 1207 .name = "dso_bid", 1208 .get = (getter)pyrf_sample_event__get_dso_bid, 1209 .set = NULL, 1210 .doc = "event dso build id.", 1211 }, 1212 { 1213 .name = "map_start", 1214 .get = (getter)pyrf_sample_event__get_map_start, 1215 .set = NULL, 1216 .doc = "event map start address.", 1217 }, 1218 { 1219 .name = "map_end", 1220 .get = (getter)pyrf_sample_event__get_map_end, 1221 .set = NULL, 1222 .doc = "event map end address.", 1223 }, 1224 { 1225 .name = "map_pgoff", 1226 .get = (getter)pyrf_sample_event__get_map_pgoff, 1227 .set = NULL, 1228 .doc = "event map page offset.", 1229 }, 1230 { 1231 .name = "symbol", 1232 .get = (getter)pyrf_sample_event__get_symbol, 1233 .set = NULL, 1234 .doc = "event symbol name.", 1235 }, 1236 { 1237 .name = "sym_start", 1238 .get = (getter)pyrf_sample_event__get_sym_start, 1239 .set = NULL, 1240 .doc = "event symbol start address.", 1241 }, 1242 { 1243 .name = "sym_end", 1244 .get = (getter)pyrf_sample_event__get_sym_end, 1245 .set = NULL, 1246 .doc = "event symbol end address.", 1247 }, 1248 { .name = NULL, }, 1249 }; 1250 1251 static PyMethodDef pyrf_sample_event__methods[] = { 1252 { 1253 .ml_name = "srccode", 1254 .ml_meth = (PyCFunction)pyrf_sample_event__srccode, 1255 .ml_flags = METH_VARARGS, 1256 .ml_doc = PyDoc_STR("Get source code for an address.") 1257 }, 1258 { 1259 .ml_name = "insn", 1260 .ml_meth = (PyCFunction)pyrf_sample_event__insn, 1261 .ml_flags = METH_NOARGS, 1262 .ml_doc = PyDoc_STR("Get instruction bytes for a sample.") 1263 }, 1264 { .ml_name = NULL, } 1265 }; 1266 1267 static PyTypeObject pyrf_sample_event__type = { 1268 PyVarObject_HEAD_INIT(NULL, 0) 1269 .tp_name = "perf.sample_event", 1270 .tp_basicsize = sizeof(struct pyrf_event), 1271 .tp_dealloc = (destructor)pyrf_event__delete, 1272 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1273 .tp_doc = pyrf_sample_event__doc, 1274 .tp_members = pyrf_sample_event__members, 1275 .tp_getset = pyrf_sample_event__getset, 1276 .tp_methods = pyrf_sample_event__methods, 1277 .tp_repr = (reprfunc)pyrf_sample_event__repr, 1278 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro, 1279 }; 1280 1281 static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); 1282 1283 static PyMemberDef pyrf_context_switch_event__members[] = { 1284 sample_members 1285 member_def(perf_event_header, type, T_UINT, "event type"), 1286 member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"), 1287 member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"), 1288 { .name = NULL, }, 1289 }; 1290 1291 static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent) 1292 { 1293 PyObject *ret; 1294 char *s; 1295 1296 if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }", 1297 pevent->event.context_switch.next_prev_pid, 1298 pevent->event.context_switch.next_prev_tid, 1299 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 1300 ret = PyErr_NoMemory(); 1301 } else { 1302 ret = PyUnicode_FromString(s); 1303 free(s); 1304 } 1305 return ret; 1306 } 1307 1308 static PyTypeObject pyrf_context_switch_event__type = { 1309 PyVarObject_HEAD_INIT(NULL, 0) 1310 .tp_name = "perf.context_switch_event", 1311 .tp_basicsize = sizeof(struct pyrf_event), 1312 .tp_dealloc = (destructor)pyrf_event__delete, 1313 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1314 .tp_doc = pyrf_context_switch_event__doc, 1315 .tp_members = pyrf_context_switch_event__members, 1316 .tp_getset = pyrf_event__getset, 1317 .tp_repr = (reprfunc)pyrf_context_switch_event__repr, 1318 }; 1319 1320 static int pyrf_event__setup_types(void) 1321 { 1322 int err; 1323 1324 err = PyType_Ready(&pyrf_mmap_event__type); 1325 if (err < 0) 1326 goto out; 1327 err = PyType_Ready(&pyrf_mmap2_event__type); 1328 if (err < 0) 1329 goto out; 1330 err = PyType_Ready(&pyrf_lost_event__type); 1331 if (err < 0) 1332 goto out; 1333 err = PyType_Ready(&pyrf_task_event__type); 1334 if (err < 0) 1335 goto out; 1336 err = PyType_Ready(&pyrf_comm_event__type); 1337 if (err < 0) 1338 goto out; 1339 err = PyType_Ready(&pyrf_throttle_event__type); 1340 if (err < 0) 1341 goto out; 1342 err = PyType_Ready(&pyrf_read_event__type); 1343 if (err < 0) 1344 goto out; 1345 err = PyType_Ready(&pyrf_sample_event__type); 1346 if (err < 0) 1347 goto out; 1348 err = PyType_Ready(&pyrf_context_switch_event__type); 1349 if (err < 0) 1350 goto out; 1351 err = PyType_Ready(&pyrf_stat_event__type); 1352 if (err < 0) 1353 goto out; 1354 err = PyType_Ready(&pyrf_stat_round_event__type); 1355 if (err < 0) 1356 goto out; 1357 err = PyType_Ready(&pyrf_callchain_node__type); 1358 if (err < 0) 1359 goto out; 1360 err = PyType_Ready(&pyrf_callchain__type); 1361 if (err < 0) 1362 goto out; 1363 err = PyType_Ready(&pyrf_branch_entry__type); 1364 if (err < 0) 1365 goto out; 1366 err = PyType_Ready(&pyrf_branch_stack__type); 1367 if (err < 0) 1368 goto out; 1369 out: 1370 return err; 1371 } 1372 1373 static PyTypeObject *pyrf_event__type[] = { 1374 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, 1375 [PERF_RECORD_MMAP2] = &pyrf_mmap2_event__type, 1376 [PERF_RECORD_LOST] = &pyrf_lost_event__type, 1377 [PERF_RECORD_COMM] = &pyrf_comm_event__type, 1378 [PERF_RECORD_EXIT] = &pyrf_task_event__type, 1379 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, 1380 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, 1381 [PERF_RECORD_FORK] = &pyrf_task_event__type, 1382 [PERF_RECORD_READ] = &pyrf_read_event__type, 1383 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, 1384 [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type, 1385 [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type, 1386 [PERF_RECORD_STAT] = &pyrf_stat_event__type, 1387 [PERF_RECORD_STAT_ROUND] = &pyrf_stat_round_event__type, 1388 }; 1389 1390 static PyObject *pyrf_event__new(const union perf_event *event, struct evsel *evsel, 1391 struct perf_session *session, 1392 struct machine *machine) 1393 { 1394 struct pyrf_event *pevent; 1395 struct perf_sample *sample; 1396 int err; 1397 u32 min_size; 1398 bool needs_swap; 1399 1400 if (!machine) 1401 machine = session ? &session->machines.host : NULL; 1402 1403 if (event->header.type >= ARRAY_SIZE(pyrf_event__type) || 1404 pyrf_event__type[event->header.type] == NULL) { 1405 return PyErr_Format(PyExc_TypeError, "Unexpected header type %u", 1406 event->header.type); 1407 } 1408 1409 if (perf_event__too_small(event, &min_size)) { 1410 return PyErr_Format(PyExc_ValueError, "Event size %u too small for type %u", 1411 event->header.size, event->header.type); 1412 } 1413 1414 size_t copy_size = event->header.size; 1415 1416 if (copy_size > sizeof(pevent->event)) { 1417 return PyErr_Format(PyExc_TypeError, "Unexpected event size: %zd < %zu", 1418 sizeof(pevent->event), copy_size); 1419 } 1420 1421 pevent = PyObject_New(struct pyrf_event, pyrf_event__type[event->header.type]); 1422 if (pevent == NULL) 1423 return PyErr_NoMemory(); 1424 1425 /* Copy the event for memory safety and initialize variables. */ 1426 memcpy(&pevent->event, event, copy_size); 1427 if (copy_size < sizeof(pevent->event)) 1428 memset((char *)&pevent->event + copy_size, 0, sizeof(pevent->event) - copy_size); 1429 1430 if (event->header.type == PERF_RECORD_MMAP2) 1431 pevent->event.mmap2.filename[sizeof(pevent->event.mmap2.filename) - 1] = '\0'; 1432 1433 perf_sample__init(&pevent->sample, /*all=*/true); 1434 pevent->callchain = NULL; 1435 pevent->brstack = NULL; 1436 pevent->al_resolved = false; 1437 addr_location__init(&pevent->al); 1438 1439 if (!evsel) 1440 return (PyObject *)pevent; 1441 1442 /* Parse the sample again so that pointers are within the copied event. */ 1443 needs_swap = evsel->needs_swap; 1444 1445 evsel->needs_swap = false; 1446 err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample); 1447 evsel->needs_swap = needs_swap; 1448 if (err < 0) { 1449 Py_DECREF(pevent); 1450 return PyErr_Format(PyExc_OSError, 1451 "perf: can't parse sample, err=%d", err); 1452 } 1453 sample = &pevent->sample; 1454 if (machine && sample->callchain) { 1455 struct addr_location al; 1456 struct callchain_cursor *cursor; 1457 u64 i; 1458 struct pyrf_callchain *pchain; 1459 1460 addr_location__init(&al); 1461 if (machine__resolve(machine, &al, sample) >= 0) { 1462 cursor = get_tls_callchain_cursor(); 1463 if (thread__resolve_callchain(al.thread, cursor, sample, 1464 NULL, NULL, PERF_MAX_STACK_DEPTH) == 0) { 1465 callchain_cursor_commit(cursor); 1466 1467 pchain = PyObject_New(struct pyrf_callchain, &pyrf_callchain__type); 1468 if (!pchain) { 1469 addr_location__exit(&al); 1470 Py_DECREF(pevent); 1471 return NULL; 1472 } 1473 pchain->nr_frames = cursor->nr; 1474 pchain->frames = calloc(pchain->nr_frames, 1475 sizeof(*pchain->frames)); 1476 if (!pchain->frames) { 1477 Py_DECREF(pchain); 1478 addr_location__exit(&al); 1479 Py_DECREF(pevent); 1480 return PyErr_NoMemory(); 1481 } 1482 struct callchain_cursor_node *node; 1483 1484 for (i = 0; i < pchain->nr_frames; i++) { 1485 node = callchain_cursor_current(cursor); 1486 pchain->frames[i].ip = node->ip; 1487 pchain->frames[i].map = 1488 map__get(node->ms.map); 1489 pchain->frames[i].sym = node->ms.sym; 1490 callchain_cursor_advance(cursor); 1491 } 1492 pevent->callchain = (PyObject *)pchain; 1493 } 1494 addr_location__exit(&al); 1495 } 1496 } 1497 if (sample->branch_stack) { 1498 struct branch_stack *bs = sample->branch_stack; 1499 struct branch_entry *entries = perf_sample__branch_entries(sample); 1500 struct pyrf_branch_stack *pstack; 1501 1502 pstack = PyObject_New(struct pyrf_branch_stack, &pyrf_branch_stack__type); 1503 if (!pstack) { 1504 Py_DECREF(pevent); 1505 return NULL; 1506 } 1507 pstack->nr = bs->nr; 1508 pstack->entries = calloc(bs->nr, sizeof(struct branch_entry)); 1509 if (!pstack->entries) { 1510 Py_DECREF(pstack); 1511 Py_DECREF(pevent); 1512 return PyErr_NoMemory(); 1513 } 1514 memcpy(pstack->entries, entries, 1515 bs->nr * sizeof(struct branch_entry)); 1516 pevent->brstack = (PyObject *)pstack; 1517 } 1518 return (PyObject *)pevent; 1519 } 1520 1521 struct pyrf_cpu_map { 1522 PyObject_HEAD 1523 1524 struct perf_cpu_map *cpus; 1525 }; 1526 1527 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, 1528 PyObject *args, PyObject *kwargs) 1529 { 1530 static char *kwlist[] = { "cpustr", NULL }; 1531 char *cpustr = NULL; 1532 1533 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", 1534 kwlist, &cpustr)) 1535 return -1; 1536 1537 pcpus->cpus = perf_cpu_map__new(cpustr); 1538 if (pcpus->cpus == NULL) 1539 return -1; 1540 return 0; 1541 } 1542 1543 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 1544 { 1545 perf_cpu_map__put(pcpus->cpus); 1546 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); 1547 } 1548 1549 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) 1550 { 1551 struct pyrf_cpu_map *pcpus = (void *)obj; 1552 1553 return perf_cpu_map__nr(pcpus->cpus); 1554 } 1555 1556 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i) 1557 { 1558 struct pyrf_cpu_map *pcpus = (void *)obj; 1559 1560 if (i >= perf_cpu_map__nr(pcpus->cpus)) { 1561 PyErr_SetString(PyExc_IndexError, "Index out of range"); 1562 return NULL; 1563 } 1564 1565 return Py_BuildValue("i", perf_cpu_map__cpu(pcpus->cpus, i).cpu); 1566 } 1567 1568 static PySequenceMethods pyrf_cpu_map__sequence_methods = { 1569 .sq_length = pyrf_cpu_map__length, 1570 .sq_item = pyrf_cpu_map__item, 1571 }; 1572 1573 static const char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object."); 1574 1575 static PyTypeObject pyrf_cpu_map__type = { 1576 PyVarObject_HEAD_INIT(NULL, 0) 1577 .tp_name = "perf.cpu_map", 1578 .tp_basicsize = sizeof(struct pyrf_cpu_map), 1579 .tp_dealloc = (destructor)pyrf_cpu_map__delete, 1580 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1581 .tp_doc = pyrf_cpu_map__doc, 1582 .tp_as_sequence = &pyrf_cpu_map__sequence_methods, 1583 .tp_init = (initproc)pyrf_cpu_map__init, 1584 }; 1585 1586 static int pyrf_cpu_map__setup_types(void) 1587 { 1588 pyrf_cpu_map__type.tp_new = PyType_GenericNew; 1589 return PyType_Ready(&pyrf_cpu_map__type); 1590 } 1591 1592 struct pyrf_thread_map { 1593 PyObject_HEAD 1594 1595 struct perf_thread_map *threads; 1596 }; 1597 1598 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 1599 PyObject *args, PyObject *kwargs) 1600 { 1601 static char *kwlist[] = { "pid", "tid", NULL }; 1602 int pid = -1, tid = -1; 1603 1604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 1605 kwlist, &pid, &tid)) 1606 return -1; 1607 1608 pthreads->threads = thread_map__new(pid, tid); 1609 if (pthreads->threads == NULL) 1610 return -1; 1611 return 0; 1612 } 1613 1614 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 1615 { 1616 perf_thread_map__put(pthreads->threads); 1617 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); 1618 } 1619 1620 static Py_ssize_t pyrf_thread_map__length(PyObject *obj) 1621 { 1622 struct pyrf_thread_map *pthreads = (void *)obj; 1623 1624 return perf_thread_map__nr(pthreads->threads); 1625 } 1626 1627 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i) 1628 { 1629 struct pyrf_thread_map *pthreads = (void *)obj; 1630 1631 if (i >= perf_thread_map__nr(pthreads->threads)) { 1632 PyErr_SetString(PyExc_IndexError, "Index out of range"); 1633 return NULL; 1634 } 1635 1636 return Py_BuildValue("i", perf_thread_map__pid(pthreads->threads, i)); 1637 } 1638 1639 static PySequenceMethods pyrf_thread_map__sequence_methods = { 1640 .sq_length = pyrf_thread_map__length, 1641 .sq_item = pyrf_thread_map__item, 1642 }; 1643 1644 static const char pyrf_thread_map__doc[] = PyDoc_STR("thread map object."); 1645 1646 static PyTypeObject pyrf_thread_map__type = { 1647 PyVarObject_HEAD_INIT(NULL, 0) 1648 .tp_name = "perf.thread_map", 1649 .tp_basicsize = sizeof(struct pyrf_thread_map), 1650 .tp_dealloc = (destructor)pyrf_thread_map__delete, 1651 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1652 .tp_doc = pyrf_thread_map__doc, 1653 .tp_as_sequence = &pyrf_thread_map__sequence_methods, 1654 .tp_init = (initproc)pyrf_thread_map__init, 1655 }; 1656 1657 static int pyrf_thread_map__setup_types(void) 1658 { 1659 pyrf_thread_map__type.tp_new = PyType_GenericNew; 1660 return PyType_Ready(&pyrf_thread_map__type); 1661 } 1662 1663 /** 1664 * A python wrapper for perf_pmus that are globally owned by the pmus.c code. 1665 */ 1666 struct pyrf_pmu { 1667 PyObject_HEAD 1668 1669 struct perf_pmu *pmu; 1670 }; 1671 1672 static void pyrf_pmu__delete(struct pyrf_pmu *ppmu) 1673 { 1674 Py_TYPE(ppmu)->tp_free((PyObject *)ppmu); 1675 } 1676 1677 static PyObject *pyrf_pmu__name(PyObject *self) 1678 { 1679 struct pyrf_pmu *ppmu = (void *)self; 1680 1681 CHECK_INITIALIZED(ppmu->pmu, "pmu"); 1682 return PyUnicode_FromString(ppmu->pmu->name); 1683 } 1684 1685 static bool add_to_dict(PyObject *dict, const char *key, const char *value) 1686 { 1687 PyObject *pkey, *pvalue; 1688 bool ret; 1689 1690 if (value == NULL) 1691 return true; 1692 1693 pkey = PyUnicode_FromString(key); 1694 pvalue = PyUnicode_FromString(value); 1695 1696 ret = pkey && pvalue && PyDict_SetItem(dict, pkey, pvalue) == 0; 1697 Py_XDECREF(pkey); 1698 Py_XDECREF(pvalue); 1699 return ret; 1700 } 1701 1702 static int pyrf_pmu__events_cb(void *state, struct pmu_event_info *info) 1703 { 1704 PyObject *py_list = state; 1705 PyObject *dict = PyDict_New(); 1706 1707 if (!dict) 1708 return -ENOMEM; 1709 1710 if (!add_to_dict(dict, "name", info->name) || 1711 !add_to_dict(dict, "alias", info->alias) || 1712 !add_to_dict(dict, "scale_unit", info->scale_unit) || 1713 !add_to_dict(dict, "desc", info->desc) || 1714 !add_to_dict(dict, "long_desc", info->long_desc) || 1715 !add_to_dict(dict, "encoding_desc", info->encoding_desc) || 1716 !add_to_dict(dict, "topic", info->topic) || 1717 !add_to_dict(dict, "event_type_desc", info->event_type_desc) || 1718 !add_to_dict(dict, "str", info->str) || 1719 !add_to_dict(dict, "deprecated", info->deprecated ? "deprecated" : NULL) || 1720 PyList_Append(py_list, dict) != 0) { 1721 Py_DECREF(dict); 1722 return -ENOMEM; 1723 } 1724 Py_DECREF(dict); 1725 return 0; 1726 } 1727 1728 static PyObject *pyrf_pmu__events(PyObject *self) 1729 { 1730 struct pyrf_pmu *ppmu = (void *)self; 1731 PyObject *py_list; 1732 int ret; 1733 1734 CHECK_INITIALIZED(ppmu->pmu, "pmu"); 1735 1736 py_list = PyList_New(0); 1737 if (!py_list) 1738 return NULL; 1739 1740 ret = perf_pmu__for_each_event(ppmu->pmu, 1741 /*skip_duplicate_pmus=*/false, 1742 py_list, 1743 pyrf_pmu__events_cb); 1744 if (ret) { 1745 Py_DECREF(py_list); 1746 errno = -ret; 1747 PyErr_SetFromErrno(PyExc_OSError); 1748 return NULL; 1749 } 1750 return py_list; 1751 } 1752 1753 static PyObject *pyrf_pmu__repr(PyObject *self) 1754 { 1755 struct pyrf_pmu *ppmu = (void *)self; 1756 1757 CHECK_INITIALIZED(ppmu->pmu, "pmu"); 1758 return PyUnicode_FromFormat("pmu(%s)", ppmu->pmu->name); 1759 } 1760 1761 static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object."); 1762 1763 static PyMethodDef pyrf_pmu__methods[] = { 1764 { 1765 .ml_name = "events", 1766 .ml_meth = (PyCFunction)pyrf_pmu__events, 1767 .ml_flags = METH_NOARGS, 1768 .ml_doc = PyDoc_STR("Returns a sequence of events encoded as a dictionaries.") 1769 }, 1770 { 1771 .ml_name = "name", 1772 .ml_meth = (PyCFunction)pyrf_pmu__name, 1773 .ml_flags = METH_NOARGS, 1774 .ml_doc = PyDoc_STR("Name of the PMU including suffixes.") 1775 }, 1776 { .ml_name = NULL, } 1777 }; 1778 1779 /** The python type for a perf.pmu. */ 1780 static PyTypeObject pyrf_pmu__type = { 1781 PyVarObject_HEAD_INIT(NULL, 0) 1782 .tp_name = "perf.pmu", 1783 .tp_basicsize = sizeof(struct pyrf_pmu), 1784 .tp_dealloc = (destructor)pyrf_pmu__delete, 1785 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1786 .tp_doc = pyrf_pmu__doc, 1787 .tp_methods = pyrf_pmu__methods, 1788 .tp_str = pyrf_pmu__name, 1789 .tp_repr = pyrf_pmu__repr, 1790 }; 1791 1792 static int pyrf_pmu__setup_types(void) 1793 { 1794 pyrf_pmu__type.tp_new = PyType_GenericNew; 1795 return PyType_Ready(&pyrf_pmu__type); 1796 } 1797 1798 1799 /** A python iterator for pmus that has no equivalent in the C code. */ 1800 struct pyrf_pmu_iterator { 1801 PyObject_HEAD 1802 struct perf_pmu *pmu; 1803 }; 1804 1805 static void pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator *self) 1806 { 1807 Py_TYPE(self)->tp_free((PyObject *) self); 1808 } 1809 1810 static PyObject *pyrf_pmu_iterator__new(PyTypeObject *type, PyObject *args __maybe_unused, 1811 PyObject *kwds __maybe_unused) 1812 { 1813 struct pyrf_pmu_iterator *itr = (void *)type->tp_alloc(type, 0); 1814 1815 if (itr != NULL) 1816 itr->pmu = perf_pmus__scan(/*pmu=*/NULL); 1817 1818 return (PyObject *) itr; 1819 } 1820 1821 static PyObject *pyrf_pmu_iterator__iter(PyObject *self) 1822 { 1823 Py_INCREF(self); 1824 return self; 1825 } 1826 1827 static PyObject *pyrf_pmu_iterator__iternext(PyObject *self) 1828 { 1829 struct pyrf_pmu_iterator *itr = (void *)self; 1830 struct pyrf_pmu *ppmu; 1831 1832 if (itr->pmu == NULL) { 1833 PyErr_SetNone(PyExc_StopIteration); 1834 return NULL; 1835 } 1836 // Create object to return. 1837 ppmu = PyObject_New(struct pyrf_pmu, &pyrf_pmu__type); 1838 if (ppmu) { 1839 ppmu->pmu = itr->pmu; 1840 // Advance iterator. 1841 itr->pmu = perf_pmus__scan(itr->pmu); 1842 } 1843 return (PyObject *)ppmu; 1844 } 1845 1846 /** The python type for the PMU iterator. */ 1847 static PyTypeObject pyrf_pmu_iterator__type = { 1848 PyVarObject_HEAD_INIT(NULL, 0) 1849 .tp_name = "pmus.iterator", 1850 .tp_doc = "Iterator for the pmus string sequence.", 1851 .tp_basicsize = sizeof(struct pyrf_pmu_iterator), 1852 .tp_itemsize = 0, 1853 .tp_flags = Py_TPFLAGS_DEFAULT, 1854 .tp_new = pyrf_pmu_iterator__new, 1855 .tp_dealloc = (destructor) pyrf_pmu_iterator__dealloc, 1856 .tp_iter = pyrf_pmu_iterator__iter, 1857 .tp_iternext = pyrf_pmu_iterator__iternext, 1858 }; 1859 1860 static int pyrf_pmu_iterator__setup_types(void) 1861 { 1862 return PyType_Ready(&pyrf_pmu_iterator__type); 1863 } 1864 1865 static PyObject *pyrf__pmus(PyObject *self, PyObject *args) 1866 { 1867 // Calling the class creates an instance of the iterator. 1868 return PyObject_CallObject((PyObject *) &pyrf_pmu_iterator__type, /*args=*/NULL); 1869 } 1870 1871 struct pyrf_counts_values { 1872 PyObject_HEAD 1873 1874 struct perf_counts_values values; 1875 }; 1876 1877 static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object."); 1878 1879 static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values) 1880 { 1881 Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values); 1882 } 1883 1884 #define counts_values_member_def(member, ptype, help) \ 1885 { #member, ptype, \ 1886 offsetof(struct pyrf_counts_values, values.member), \ 1887 0, help } 1888 1889 static PyMemberDef pyrf_counts_values_members[] = { 1890 counts_values_member_def(val, T_ULONGLONG, "Value of event"), 1891 counts_values_member_def(ena, T_ULONGLONG, "Time for which enabled"), 1892 counts_values_member_def(run, T_ULONGLONG, "Time for which running"), 1893 counts_values_member_def(id, T_ULONGLONG, "Unique ID for an event"), 1894 counts_values_member_def(lost, T_ULONGLONG, "Num of lost samples"), 1895 { .name = NULL, }, 1896 }; 1897 1898 static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure) 1899 { 1900 PyObject *vals = PyList_New(5); 1901 1902 if (!vals) 1903 return NULL; 1904 for (int i = 0; i < 5; i++) { 1905 PyObject *val = PyLong_FromUnsignedLongLong(self->values.values[i]); 1906 1907 if (!val) { 1908 Py_DECREF(vals); 1909 return NULL; 1910 } 1911 PyList_SetItem(vals, i, val); 1912 } 1913 1914 return vals; 1915 } 1916 1917 static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list, 1918 void *closure) 1919 { 1920 Py_ssize_t size; 1921 PyObject *item = NULL; 1922 1923 if (list == NULL) { 1924 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 1925 return -1; 1926 } 1927 1928 if (!PyList_Check(list)) { 1929 PyErr_SetString(PyExc_TypeError, "Value assigned must be a list"); 1930 return -1; 1931 } 1932 1933 size = PyList_Size(list); 1934 if (size != 5) { 1935 PyErr_SetString(PyExc_ValueError, "List must have exactly 5 entries"); 1936 return -1; 1937 } 1938 1939 for (Py_ssize_t i = 0; i < size; i++) { 1940 unsigned long long val; 1941 1942 item = PyList_GetItem(list, i); 1943 if (!PyLong_Check(item)) { 1944 PyErr_SetString(PyExc_TypeError, "List members should be numbers"); 1945 return -1; 1946 } 1947 val = PyLong_AsUnsignedLongLong(item); 1948 if (val == (unsigned long long)-1 && PyErr_Occurred()) 1949 return -1; 1950 self->values.values[i] = val; 1951 } 1952 1953 return 0; 1954 } 1955 1956 static PyGetSetDef pyrf_counts_values_getset[] = { 1957 {"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values, 1958 "Name field", NULL}, 1959 { .name = NULL, }, 1960 }; 1961 1962 static PyTypeObject pyrf_counts_values__type = { 1963 PyVarObject_HEAD_INIT(NULL, 0) 1964 .tp_name = "perf.counts_values", 1965 .tp_basicsize = sizeof(struct pyrf_counts_values), 1966 .tp_dealloc = (destructor)pyrf_counts_values__delete, 1967 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1968 .tp_doc = pyrf_counts_values__doc, 1969 .tp_members = pyrf_counts_values_members, 1970 .tp_getset = pyrf_counts_values_getset, 1971 }; 1972 1973 static int pyrf_counts_values__setup_types(void) 1974 { 1975 pyrf_counts_values__type.tp_new = PyType_GenericNew; 1976 return PyType_Ready(&pyrf_counts_values__type); 1977 } 1978 1979 struct pyrf_evsel { 1980 PyObject_HEAD 1981 1982 struct evsel *evsel; 1983 }; 1984 1985 static int pyrf_evsel__init(struct pyrf_evsel *pevsel, 1986 PyObject *args, PyObject *kwargs) 1987 { 1988 struct perf_event_attr attr = { 1989 .type = PERF_TYPE_HARDWARE, 1990 .config = PERF_COUNT_HW_CPU_CYCLES, 1991 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID, 1992 }; 1993 static char *kwlist[] = { 1994 "type", 1995 "config", 1996 "sample_freq", 1997 "sample_period", 1998 "sample_type", 1999 "read_format", 2000 "disabled", 2001 "inherit", 2002 "pinned", 2003 "exclusive", 2004 "exclude_user", 2005 "exclude_kernel", 2006 "exclude_hv", 2007 "exclude_idle", 2008 "mmap", 2009 "context_switch", 2010 "comm", 2011 "freq", 2012 "inherit_stat", 2013 "enable_on_exec", 2014 "task", 2015 "watermark", 2016 "precise_ip", 2017 "mmap_data", 2018 "sample_id_all", 2019 "wakeup_events", 2020 "bp_type", 2021 "bp_addr", 2022 "bp_len", 2023 "idx", 2024 NULL 2025 }; 2026 u64 sample_period = 0; 2027 u32 disabled = 0, 2028 inherit = 0, 2029 pinned = 0, 2030 exclusive = 0, 2031 exclude_user = 0, 2032 exclude_kernel = 0, 2033 exclude_hv = 0, 2034 exclude_idle = 0, 2035 mmap = 0, 2036 context_switch = 0, 2037 comm = 0, 2038 freq = 1, 2039 inherit_stat = 0, 2040 enable_on_exec = 0, 2041 task = 0, 2042 watermark = 0, 2043 precise_ip = 0, 2044 mmap_data = 0, 2045 sample_id_all = 1, 2046 idx = 0; 2047 2048 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 2049 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKKi", kwlist, 2050 &attr.type, &attr.config, &attr.sample_freq, 2051 &sample_period, &attr.sample_type, 2052 &attr.read_format, &disabled, &inherit, 2053 &pinned, &exclusive, &exclude_user, 2054 &exclude_kernel, &exclude_hv, &exclude_idle, 2055 &mmap, &context_switch, &comm, &freq, &inherit_stat, 2056 &enable_on_exec, &task, &watermark, 2057 &precise_ip, &mmap_data, &sample_id_all, 2058 &attr.wakeup_events, &attr.bp_type, 2059 &attr.bp_addr, &attr.bp_len, &idx)) 2060 return -1; 2061 2062 /* union... */ 2063 if (sample_period != 0) { 2064 if (attr.sample_freq != 0) 2065 return -1; /* FIXME: throw right exception */ 2066 attr.sample_period = sample_period; 2067 } 2068 2069 /* Bitfields */ 2070 attr.disabled = disabled; 2071 attr.inherit = inherit; 2072 attr.pinned = pinned; 2073 attr.exclusive = exclusive; 2074 attr.exclude_user = exclude_user; 2075 attr.exclude_kernel = exclude_kernel; 2076 attr.exclude_hv = exclude_hv; 2077 attr.exclude_idle = exclude_idle; 2078 attr.mmap = mmap; 2079 attr.context_switch = context_switch; 2080 attr.comm = comm; 2081 attr.freq = freq; 2082 attr.inherit_stat = inherit_stat; 2083 attr.enable_on_exec = enable_on_exec; 2084 attr.task = task; 2085 attr.watermark = watermark; 2086 attr.precise_ip = precise_ip; 2087 attr.mmap_data = mmap_data; 2088 attr.sample_id_all = sample_id_all; 2089 attr.size = sizeof(attr); 2090 2091 evsel__put(pevsel->evsel); 2092 pevsel->evsel = evsel__new(&attr); 2093 if (!pevsel->evsel) { 2094 PyErr_NoMemory(); 2095 return -1; 2096 } 2097 return 0; 2098 } 2099 2100 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 2101 { 2102 evsel__put(pevsel->evsel); 2103 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel); 2104 } 2105 2106 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, 2107 PyObject *args, PyObject *kwargs) 2108 { 2109 struct evsel *evsel = pevsel->evsel; 2110 struct perf_cpu_map *cpus = NULL; 2111 struct perf_thread_map *threads = NULL; 2112 PyObject *pcpus = NULL, *pthreads = NULL; 2113 int group = 0, inherit = 0; 2114 static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL }; 2115 2116 CHECK_INITIALIZED(evsel, "evsel"); 2117 2118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, 2119 &pcpus, &pthreads, &group, &inherit)) 2120 return NULL; 2121 2122 if (pthreads != NULL && pthreads != Py_None) { 2123 if (!PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) { 2124 PyErr_SetString(PyExc_TypeError, "threads must be a thread_map"); 2125 return NULL; 2126 } 2127 threads = ((struct pyrf_thread_map *)pthreads)->threads; 2128 } 2129 2130 if (pcpus != NULL && pcpus != Py_None) { 2131 if (!PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) { 2132 PyErr_SetString(PyExc_TypeError, "cpus must be a cpu_map"); 2133 return NULL; 2134 } 2135 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 2136 } 2137 2138 evsel->core.attr.inherit = inherit; 2139 /* 2140 * This will group just the fds for this single evsel, to group 2141 * multiple events, use evlist.open(). 2142 */ 2143 if (evsel__open(evsel, cpus, threads) < 0) { 2144 PyErr_SetFromErrno(PyExc_OSError); 2145 return NULL; 2146 } 2147 2148 Py_INCREF(Py_None); 2149 return Py_None; 2150 } 2151 2152 static PyObject *pyrf_evsel__cpus(struct pyrf_evsel *pevsel) 2153 { 2154 struct pyrf_cpu_map *pcpu_map; 2155 2156 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2157 2158 pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type); 2159 if (pcpu_map) 2160 pcpu_map->cpus = perf_cpu_map__get(pevsel->evsel->core.cpus); 2161 2162 return (PyObject *)pcpu_map; 2163 } 2164 2165 static PyObject *pyrf_evsel__threads(struct pyrf_evsel *pevsel) 2166 { 2167 struct pyrf_thread_map *pthread_map; 2168 2169 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2170 2171 pthread_map = PyObject_New(struct pyrf_thread_map, &pyrf_thread_map__type); 2172 if (pthread_map) 2173 pthread_map->threads = perf_thread_map__get(pevsel->evsel->core.threads); 2174 2175 return (PyObject *)pthread_map; 2176 } 2177 2178 /* 2179 * Ensure evsel's counts and prev_raw_counts are allocated, the latter 2180 * used by tool PMUs to compute the cumulative count as expected by 2181 * stat's process_counter_values. 2182 */ 2183 static int evsel__ensure_counts(struct evsel *evsel) 2184 { 2185 int nthreads, ncpus; 2186 2187 if (evsel->counts != NULL) 2188 return 0; 2189 2190 nthreads = perf_thread_map__nr(evsel->core.threads); 2191 ncpus = perf_cpu_map__nr(evsel->core.cpus); 2192 2193 evsel->counts = perf_counts__new(ncpus, nthreads); 2194 if (evsel->counts == NULL) 2195 return -ENOMEM; 2196 2197 evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads); 2198 if (evsel->prev_raw_counts == NULL) 2199 return -ENOMEM; 2200 2201 return 0; 2202 } 2203 2204 static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel, 2205 PyObject *args, PyObject *kwargs) 2206 { 2207 struct evsel *evsel = pevsel->evsel; 2208 int cpu = 0, cpu_idx, thread = 0, thread_idx; 2209 struct perf_counts_values *old_count, *new_count; 2210 struct pyrf_counts_values *count_values; 2211 2212 CHECK_INITIALIZED(evsel, "evsel"); 2213 2214 if (!PyArg_ParseTuple(args, "ii", &cpu, &thread)) 2215 return NULL; 2216 2217 cpu_idx = perf_cpu_map__idx(evsel->core.cpus, (struct perf_cpu){.cpu = cpu}); 2218 if (cpu_idx < 0) { 2219 PyErr_Format(PyExc_TypeError, "CPU %d is not part of evsel's CPUs", cpu); 2220 return NULL; 2221 } 2222 thread_idx = perf_thread_map__idx(evsel->core.threads, thread); 2223 if (thread_idx < 0) { 2224 PyErr_Format(PyExc_TypeError, "Thread %d is not part of evsel's threads", 2225 thread); 2226 return NULL; 2227 } 2228 2229 if (evsel__ensure_counts(evsel)) 2230 return PyErr_NoMemory(); 2231 2232 count_values = PyObject_New(struct pyrf_counts_values, &pyrf_counts_values__type); 2233 if (!count_values) 2234 return NULL; 2235 2236 /* Set up pointers to the old and newly read counter values. */ 2237 old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx); 2238 new_count = perf_counts(evsel->counts, cpu_idx, thread_idx); 2239 /* Update the value in evsel->counts. */ 2240 evsel__read_counter(evsel, cpu_idx, thread_idx); 2241 /* Copy the value and turn it into the delta from old_count. */ 2242 count_values->values = *new_count; 2243 count_values->values.val -= old_count->val; 2244 count_values->values.ena -= old_count->ena; 2245 count_values->values.run -= old_count->run; 2246 /* Save the new count over the old_count for the next read. */ 2247 *old_count = *new_count; 2248 return (PyObject *)count_values; 2249 } 2250 2251 static PyObject *pyrf_evsel__str(PyObject *self) 2252 { 2253 struct pyrf_evsel *pevsel = (void *)self; 2254 struct evsel *evsel = pevsel->evsel; 2255 2256 if (!evsel) 2257 return PyUnicode_FromString("evsel(uninitialized)"); 2258 2259 return PyUnicode_FromFormat("evsel(%s)", evsel__name(evsel)); 2260 } 2261 2262 static PyMethodDef pyrf_evsel__methods[] = { 2263 { 2264 .ml_name = "open", 2265 .ml_meth = (PyCFunction)pyrf_evsel__open, 2266 .ml_flags = METH_VARARGS | METH_KEYWORDS, 2267 .ml_doc = PyDoc_STR("open the event selector file descriptor table.") 2268 }, 2269 { 2270 .ml_name = "cpus", 2271 .ml_meth = (PyCFunction)pyrf_evsel__cpus, 2272 .ml_flags = METH_NOARGS, 2273 .ml_doc = PyDoc_STR("CPUs the event is to be used with.") 2274 }, 2275 { 2276 .ml_name = "threads", 2277 .ml_meth = (PyCFunction)pyrf_evsel__threads, 2278 .ml_flags = METH_NOARGS, 2279 .ml_doc = PyDoc_STR("threads the event is to be used with.") 2280 }, 2281 { 2282 .ml_name = "read", 2283 .ml_meth = (PyCFunction)pyrf_evsel__read, 2284 .ml_flags = METH_VARARGS | METH_KEYWORDS, 2285 .ml_doc = PyDoc_STR("read counters") 2286 }, 2287 { .ml_name = NULL, } 2288 }; 2289 2290 static PyObject *pyrf_evsel__get_tracking(PyObject *self, void *closure __maybe_unused) 2291 { 2292 struct pyrf_evsel *pevsel = (void *)self; 2293 2294 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2295 2296 if (pevsel->evsel->tracking) 2297 Py_RETURN_TRUE; 2298 else 2299 Py_RETURN_FALSE; 2300 } 2301 2302 static int pyrf_evsel__set_tracking(PyObject *self, PyObject *val, void *closure __maybe_unused) 2303 { 2304 struct pyrf_evsel *pevsel = (void *)self; 2305 int is_true; 2306 2307 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2308 2309 if (val == NULL) { 2310 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2311 return -1; 2312 } 2313 2314 is_true = PyObject_IsTrue(val); 2315 if (is_true < 0) 2316 return -1; 2317 2318 pevsel->evsel->tracking = is_true; 2319 return 0; 2320 } 2321 2322 static int pyrf_evsel__set_attr_config(PyObject *self, PyObject *val, void *closure __maybe_unused) 2323 { 2324 struct pyrf_evsel *pevsel = (void *)self; 2325 unsigned long long new_val; 2326 2327 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2328 2329 if (val == NULL) { 2330 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2331 return -1; 2332 } 2333 2334 new_val = PyLong_AsUnsignedLongLong(val); 2335 if (PyErr_Occurred()) 2336 return -1; 2337 2338 pevsel->evsel->core.attr.config = new_val; 2339 return 0; 2340 } 2341 2342 static PyObject *pyrf_evsel__get_attr_config(PyObject *self, void *closure __maybe_unused) 2343 { 2344 struct pyrf_evsel *pevsel = (void *)self; 2345 2346 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2347 2348 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.config); 2349 } 2350 2351 static int pyrf_evsel__set_attr_read_format(PyObject *self, PyObject *val, void *closure __maybe_unused) 2352 { 2353 struct pyrf_evsel *pevsel = (void *)self; 2354 unsigned long long new_val; 2355 2356 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2357 2358 if (val == NULL) { 2359 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2360 return -1; 2361 } 2362 2363 new_val = PyLong_AsUnsignedLongLong(val); 2364 if (PyErr_Occurred()) 2365 return -1; 2366 2367 pevsel->evsel->core.attr.read_format = new_val; 2368 return 0; 2369 } 2370 2371 static PyObject *pyrf_evsel__get_attr_read_format(PyObject *self, void *closure __maybe_unused) 2372 { 2373 struct pyrf_evsel *pevsel = (void *)self; 2374 2375 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2376 2377 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.read_format); 2378 } 2379 2380 static int pyrf_evsel__set_attr_sample_period(PyObject *self, PyObject *val, void *closure __maybe_unused) 2381 { 2382 struct pyrf_evsel *pevsel = (void *)self; 2383 unsigned long long new_val; 2384 2385 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2386 2387 if (val == NULL) { 2388 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2389 return -1; 2390 } 2391 2392 new_val = PyLong_AsUnsignedLongLong(val); 2393 if (PyErr_Occurred()) 2394 return -1; 2395 2396 pevsel->evsel->core.attr.sample_period = new_val; 2397 return 0; 2398 } 2399 2400 static PyObject *pyrf_evsel__get_attr_sample_period(PyObject *self, void *closure __maybe_unused) 2401 { 2402 struct pyrf_evsel *pevsel = (void *)self; 2403 2404 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2405 2406 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.sample_period); 2407 } 2408 2409 static int pyrf_evsel__set_attr_sample_type(PyObject *self, PyObject *val, void *closure __maybe_unused) 2410 { 2411 struct pyrf_evsel *pevsel = (void *)self; 2412 unsigned long long new_val; 2413 2414 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2415 2416 if (val == NULL) { 2417 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2418 return -1; 2419 } 2420 2421 new_val = PyLong_AsUnsignedLongLong(val); 2422 if (PyErr_Occurred()) 2423 return -1; 2424 2425 pevsel->evsel->core.attr.sample_type = new_val; 2426 return 0; 2427 } 2428 2429 static PyObject *pyrf_evsel__get_attr_sample_type(PyObject *self, void *closure __maybe_unused) 2430 { 2431 struct pyrf_evsel *pevsel = (void *)self; 2432 2433 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2434 2435 return PyLong_FromUnsignedLongLong(pevsel->evsel->core.attr.sample_type); 2436 } 2437 2438 static PyObject *pyrf_evsel__get_attr_size(PyObject *self, void *closure __maybe_unused) 2439 { 2440 struct pyrf_evsel *pevsel = (void *)self; 2441 2442 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2443 2444 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.size); 2445 } 2446 2447 static int pyrf_evsel__set_attr_type(PyObject *self, PyObject *val, void *closure __maybe_unused) 2448 { 2449 struct pyrf_evsel *pevsel = (void *)self; 2450 unsigned long new_val; 2451 2452 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2453 2454 if (val == NULL) { 2455 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2456 return -1; 2457 } 2458 2459 new_val = PyLong_AsUnsignedLong(val); 2460 if (PyErr_Occurred()) 2461 return -1; 2462 2463 pevsel->evsel->core.attr.type = new_val; 2464 return 0; 2465 } 2466 2467 static PyObject *pyrf_evsel__get_attr_type(PyObject *self, void *closure __maybe_unused) 2468 { 2469 struct pyrf_evsel *pevsel = (void *)self; 2470 2471 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2472 2473 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.type); 2474 } 2475 2476 static int pyrf_evsel__set_attr_wakeup_events(PyObject *self, PyObject *val, void *closure __maybe_unused) 2477 { 2478 struct pyrf_evsel *pevsel = (void *)self; 2479 unsigned long new_val; 2480 2481 CHECK_INITIALIZED_INT(pevsel->evsel, "evsel"); 2482 2483 if (val == NULL) { 2484 PyErr_SetString(PyExc_TypeError, "cannot delete attribute"); 2485 return -1; 2486 } 2487 2488 new_val = PyLong_AsUnsignedLong(val); 2489 if (PyErr_Occurred()) 2490 return -1; 2491 2492 pevsel->evsel->core.attr.wakeup_events = new_val; 2493 return 0; 2494 } 2495 2496 static PyObject *pyrf_evsel__get_attr_wakeup_events(PyObject *self, void *closure __maybe_unused) 2497 { 2498 struct pyrf_evsel *pevsel = (void *)self; 2499 2500 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2501 2502 return PyLong_FromUnsignedLong(pevsel->evsel->core.attr.wakeup_events); 2503 } 2504 2505 static PyObject *pyrf_evsel__get_ids(struct pyrf_evsel *pevsel, void *closure __maybe_unused) 2506 { 2507 struct evsel *evsel; 2508 PyObject *list; 2509 2510 CHECK_INITIALIZED(pevsel->evsel, "evsel"); 2511 2512 evsel = pevsel->evsel; 2513 list = PyList_New(0); 2514 2515 if (!list) 2516 return NULL; 2517 2518 for (u32 i = 0; i < evsel->core.ids; i++) { 2519 PyObject *id = PyLong_FromUnsignedLongLong(evsel->core.id[i]); 2520 int ret; 2521 2522 if (!id) { 2523 Py_DECREF(list); 2524 return NULL; 2525 } 2526 ret = PyList_Append(list, id); 2527 Py_DECREF(id); 2528 if (ret < 0) { 2529 Py_DECREF(list); 2530 return NULL; 2531 } 2532 } 2533 2534 return list; 2535 } 2536 2537 static PyGetSetDef pyrf_evsel__getset[] = { 2538 { 2539 .name = "ids", 2540 .get = (getter)pyrf_evsel__get_ids, 2541 .set = NULL, 2542 .doc = "event IDs.", 2543 }, 2544 { 2545 .name = "tracking", 2546 .get = pyrf_evsel__get_tracking, 2547 .set = pyrf_evsel__set_tracking, 2548 .doc = "tracking event.", 2549 }, 2550 { 2551 .name = "config", 2552 .get = pyrf_evsel__get_attr_config, 2553 .set = pyrf_evsel__set_attr_config, 2554 .doc = "attribute config.", 2555 }, 2556 { 2557 .name = "read_format", 2558 .get = pyrf_evsel__get_attr_read_format, 2559 .set = pyrf_evsel__set_attr_read_format, 2560 .doc = "attribute read_format.", 2561 }, 2562 { 2563 .name = "sample_period", 2564 .get = pyrf_evsel__get_attr_sample_period, 2565 .set = pyrf_evsel__set_attr_sample_period, 2566 .doc = "attribute sample_period.", 2567 }, 2568 { 2569 .name = "sample_type", 2570 .get = pyrf_evsel__get_attr_sample_type, 2571 .set = pyrf_evsel__set_attr_sample_type, 2572 .doc = "attribute sample_type.", 2573 }, 2574 { 2575 .name = "size", 2576 .get = pyrf_evsel__get_attr_size, 2577 .doc = "attribute size.", 2578 }, 2579 { 2580 .name = "type", 2581 .get = pyrf_evsel__get_attr_type, 2582 .set = pyrf_evsel__set_attr_type, 2583 .doc = "attribute type.", 2584 }, 2585 { 2586 .name = "wakeup_events", 2587 .get = pyrf_evsel__get_attr_wakeup_events, 2588 .set = pyrf_evsel__set_attr_wakeup_events, 2589 .doc = "attribute wakeup_events.", 2590 }, 2591 { .name = NULL}, 2592 }; 2593 2594 static const char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object."); 2595 2596 static PyObject *pyrf_evsel__getattro(struct pyrf_evsel *pevsel, PyObject *attr_name) 2597 { 2598 if (!pevsel->evsel) { 2599 PyErr_SetString(PyExc_ValueError, "evsel not initialized"); 2600 return NULL; 2601 } 2602 return PyObject_GenericGetAttr((PyObject *) pevsel, attr_name); 2603 } 2604 2605 static int pyrf_evsel__setattro(struct pyrf_evsel *pevsel, PyObject *attr_name, PyObject *value) 2606 { 2607 if (!pevsel->evsel) { 2608 PyErr_SetString(PyExc_ValueError, "evsel not initialized"); 2609 return -1; 2610 } 2611 return PyObject_GenericSetAttr((PyObject *) pevsel, attr_name, value); 2612 } 2613 2614 static PyTypeObject pyrf_evsel__type = { 2615 PyVarObject_HEAD_INIT(NULL, 0) 2616 .tp_name = "perf.evsel", 2617 .tp_basicsize = sizeof(struct pyrf_evsel), 2618 .tp_dealloc = (destructor)pyrf_evsel__delete, 2619 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 2620 .tp_doc = pyrf_evsel__doc, 2621 .tp_getset = pyrf_evsel__getset, 2622 .tp_methods = pyrf_evsel__methods, 2623 .tp_init = (initproc)pyrf_evsel__init, 2624 .tp_str = pyrf_evsel__str, 2625 .tp_repr = pyrf_evsel__str, 2626 .tp_getattro = (getattrofunc) pyrf_evsel__getattro, 2627 .tp_setattro = (setattrofunc) pyrf_evsel__setattro, 2628 }; 2629 2630 static PyObject *pyrf_evsel__new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 2631 { 2632 struct pyrf_evsel *pevsel; 2633 2634 pevsel = (struct pyrf_evsel *)PyType_GenericNew(type, args, kwargs); 2635 if (pevsel) 2636 pevsel->evsel = NULL; 2637 return (PyObject *)pevsel; 2638 } 2639 2640 static int pyrf_evsel__setup_types(void) 2641 { 2642 pyrf_evsel__type.tp_new = pyrf_evsel__new; 2643 return PyType_Ready(&pyrf_evsel__type); 2644 } 2645 2646 struct pyrf_evlist { 2647 PyObject_HEAD 2648 2649 struct evlist *evlist; 2650 }; 2651 2652 static int pyrf_evlist__init(struct pyrf_evlist *pevlist, 2653 PyObject *args, PyObject *kwargs __maybe_unused) 2654 { 2655 PyObject *pcpus = NULL, *pthreads = NULL; 2656 struct perf_cpu_map *cpus; 2657 struct perf_thread_map *threads; 2658 2659 if (!PyArg_ParseTuple(args, "O!O!", 2660 &pyrf_cpu_map__type, &pcpus, 2661 &pyrf_thread_map__type, &pthreads)) 2662 return -1; 2663 2664 evlist__put(pevlist->evlist); 2665 pevlist->evlist = evlist__new(); 2666 if (!pevlist->evlist) { 2667 PyErr_NoMemory(); 2668 return -1; 2669 } 2670 threads = ((struct pyrf_thread_map *)pthreads)->threads; 2671 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 2672 perf_evlist__set_maps(evlist__core(pevlist->evlist), cpus, threads); 2673 2674 return 0; 2675 } 2676 2677 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 2678 { 2679 evlist__put(pevlist->evlist); 2680 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist); 2681 } 2682 2683 static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist) 2684 { 2685 struct pyrf_cpu_map *pcpu_map; 2686 2687 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2688 2689 pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type); 2690 if (pcpu_map) 2691 pcpu_map->cpus = perf_cpu_map__get(evlist__core(pevlist->evlist)->all_cpus); 2692 2693 return (PyObject *)pcpu_map; 2694 } 2695 2696 static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist) 2697 { 2698 PyObject *list; 2699 struct rb_node *node; 2700 2701 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2702 2703 list = PyList_New(/*len=*/0); 2704 if (!list) 2705 return NULL; 2706 2707 for (node = rb_first_cached(&evlist__metric_events(pevlist->evlist)->entries); node; 2708 node = rb_next(node)) { 2709 struct metric_event *me = container_of(node, struct metric_event, nd); 2710 struct list_head *pos; 2711 2712 list_for_each(pos, &me->head) { 2713 struct metric_expr *expr = container_of(pos, struct metric_expr, nd); 2714 PyObject *str = PyUnicode_FromString(expr->metric_name); 2715 2716 if (!str || PyList_Append(list, str) != 0) { 2717 Py_DECREF(list); 2718 return NULL; 2719 } 2720 Py_DECREF(str); 2721 } 2722 } 2723 return list; 2724 } 2725 2726 static int prepare_metric(const struct metric_expr *mexp, 2727 const struct evsel *evsel, 2728 struct expr_parse_ctx *pctx, 2729 int cpu_idx, int thread_idx) 2730 { 2731 struct evsel * const *metric_events = mexp->metric_events; 2732 struct metric_ref *metric_refs = mexp->metric_refs; 2733 2734 for (int i = 0; metric_events[i]; i++) { 2735 struct evsel *cur = metric_events[i]; 2736 double val, ena, run; 2737 int ret, source_count = 0; 2738 struct perf_counts_values *old_count, *new_count; 2739 char *n = strdup(evsel__metric_id(cur)); 2740 2741 if (!n) 2742 return -ENOMEM; 2743 2744 /* 2745 * If there are multiple uncore PMUs and we're not reading the 2746 * leader's stats, determine the stats for the appropriate 2747 * uncore PMU. 2748 */ 2749 if (evsel && evsel->metric_leader && 2750 evsel->pmu != evsel->metric_leader->pmu && 2751 cur->pmu == evsel->metric_leader->pmu) { 2752 struct evsel *pos; 2753 2754 evlist__for_each_entry(evsel->evlist, pos) { 2755 if (pos->pmu != evsel->pmu) 2756 continue; 2757 if (pos->metric_leader != cur) 2758 continue; 2759 cur = pos; 2760 source_count = 1; 2761 break; 2762 } 2763 } 2764 2765 if (source_count == 0) 2766 source_count = evsel__source_count(cur); 2767 2768 ret = evsel__ensure_counts(cur); 2769 if (ret) 2770 return ret; 2771 2772 /* Set up pointers to the old and newly read counter values. */ 2773 old_count = perf_counts(cur->prev_raw_counts, cpu_idx, thread_idx); 2774 new_count = perf_counts(cur->counts, cpu_idx, thread_idx); 2775 /* Update the value in cur->counts. */ 2776 evsel__read_counter(cur, cpu_idx, thread_idx); 2777 2778 val = new_count->val - old_count->val; 2779 ena = new_count->ena - old_count->ena; 2780 run = new_count->run - old_count->run; 2781 2782 if (ena != run && run != 0) 2783 val = val * ena / run; 2784 ret = expr__add_id_val_source_count(pctx, n, val, source_count); 2785 if (ret) 2786 return ret; 2787 } 2788 2789 for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) { 2790 int ret = expr__add_ref(pctx, &metric_refs[i]); 2791 2792 if (ret) 2793 return ret; 2794 } 2795 2796 return 0; 2797 } 2798 2799 static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, 2800 PyObject *args, PyObject *kwargs) 2801 { 2802 int ret, cpu = 0, cpu_idx = 0, thread = 0, thread_idx = 0; 2803 const char *metric; 2804 struct rb_node *node; 2805 struct metric_expr *mexp = NULL; 2806 struct expr_parse_ctx *pctx; 2807 double result = 0; 2808 struct evsel *metric_evsel = NULL; 2809 2810 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2811 2812 if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread)) 2813 return NULL; 2814 2815 for (node = rb_first_cached(&evlist__metric_events(pevlist->evlist)->entries); 2816 mexp == NULL && node; 2817 node = rb_next(node)) { 2818 struct metric_event *me = container_of(node, struct metric_event, nd); 2819 struct list_head *pos; 2820 2821 list_for_each(pos, &me->head) { 2822 struct metric_expr *e = container_of(pos, struct metric_expr, nd); 2823 struct evsel *pos2; 2824 2825 if (strcmp(e->metric_name, metric)) 2826 continue; 2827 2828 if (e->metric_events[0] == NULL) 2829 continue; 2830 2831 evlist__for_each_entry(pevlist->evlist, pos2) { 2832 if (pos2->metric_leader != e->metric_events[0]) 2833 continue; 2834 cpu_idx = perf_cpu_map__idx(pos2->core.cpus, 2835 (struct perf_cpu){.cpu = cpu}); 2836 if (cpu_idx < 0) 2837 continue; 2838 2839 thread_idx = perf_thread_map__idx(pos2->core.threads, thread); 2840 if (thread_idx < 0) 2841 continue; 2842 metric_evsel = pos2; 2843 mexp = e; 2844 goto done; 2845 } 2846 } 2847 } 2848 done: 2849 if (!mexp) { 2850 PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'", 2851 metric, cpu, thread); 2852 return NULL; 2853 } 2854 2855 pctx = expr__ctx_new(); 2856 if (!pctx) 2857 return PyErr_NoMemory(); 2858 2859 ret = prepare_metric(mexp, metric_evsel, pctx, cpu_idx, thread_idx); 2860 if (ret) { 2861 expr__ctx_free(pctx); 2862 errno = -ret; 2863 PyErr_SetFromErrno(PyExc_OSError); 2864 return NULL; 2865 } 2866 if (expr__parse(&result, pctx, mexp->metric_expr)) 2867 result = 0.0; 2868 2869 expr__ctx_free(pctx); 2870 return PyFloat_FromDouble(result); 2871 } 2872 2873 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, 2874 PyObject *args, PyObject *kwargs) 2875 { 2876 struct evlist *evlist; 2877 static char *kwlist[] = { "pages", "overwrite", NULL }; 2878 int pages = 128, overwrite = false; 2879 2880 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2881 2882 evlist = pevlist->evlist; 2883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, 2884 &pages, &overwrite)) 2885 return NULL; 2886 2887 if (evlist__do_mmap(evlist, pages) < 0) { 2888 PyErr_SetFromErrno(PyExc_OSError); 2889 return NULL; 2890 } 2891 2892 Py_INCREF(Py_None); 2893 return Py_None; 2894 } 2895 2896 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, 2897 PyObject *args, PyObject *kwargs) 2898 { 2899 struct evlist *evlist; 2900 static char *kwlist[] = { "timeout", NULL }; 2901 int timeout = -1, n; 2902 2903 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2904 2905 evlist = pevlist->evlist; 2906 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 2907 return NULL; 2908 2909 n = evlist__poll(evlist, timeout); 2910 if (n < 0) { 2911 PyErr_SetFromErrno(PyExc_OSError); 2912 return NULL; 2913 } 2914 2915 return Py_BuildValue("i", n); 2916 } 2917 2918 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, 2919 PyObject *args __maybe_unused, 2920 PyObject *kwargs __maybe_unused) 2921 { 2922 struct evlist *evlist; 2923 PyObject *list; 2924 int i; 2925 2926 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2927 2928 evlist = pevlist->evlist; 2929 list = PyList_New(0); 2930 if (!list) 2931 return NULL; 2932 2933 for (i = 0; i < evlist__core(evlist)->pollfd.nr; ++i) { 2934 PyObject *file; 2935 file = PyFile_FromFd(evlist__core(evlist)->pollfd.entries[i].fd, "perf", "r", -1, 2936 NULL, NULL, NULL, 0); 2937 if (file == NULL) 2938 goto free_list; 2939 2940 if (PyList_Append(list, file) != 0) { 2941 Py_DECREF(file); 2942 goto free_list; 2943 } 2944 2945 Py_DECREF(file); 2946 } 2947 2948 return list; 2949 free_list: 2950 Py_XDECREF(list); 2951 return PyErr_NoMemory(); 2952 } 2953 2954 2955 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, 2956 PyObject *args, 2957 PyObject *kwargs __maybe_unused) 2958 { 2959 struct evlist *evlist; 2960 PyObject *pevsel; 2961 struct evsel *evsel; 2962 2963 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 2964 2965 evlist = pevlist->evlist; 2966 if (!PyArg_ParseTuple(args, "O!", &pyrf_evsel__type, &pevsel)) 2967 return NULL; 2968 2969 CHECK_INITIALIZED(((struct pyrf_evsel *)pevsel)->evsel, "evsel"); 2970 2971 evsel = ((struct pyrf_evsel *)pevsel)->evsel; 2972 CHECK_INITIALIZED(evsel, "evsel"); 2973 2974 evsel->core.idx = evlist__nr_entries(evlist); 2975 evlist__add(evlist, evsel__get(evsel)); 2976 2977 return Py_BuildValue("i", evlist__nr_entries(evlist)); 2978 } 2979 2980 static struct mmap *get_md(struct evlist *evlist, int cpu) 2981 { 2982 int i; 2983 2984 for (i = 0; i < evlist__core(evlist)->nr_mmaps; i++) { 2985 struct mmap *md = &evlist__mmap(evlist)[i]; 2986 2987 if (md->core.cpu.cpu == cpu) 2988 return md; 2989 } 2990 2991 return NULL; 2992 } 2993 2994 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, 2995 PyObject *args, PyObject *kwargs) 2996 { 2997 struct evlist *evlist; 2998 union perf_event *event; 2999 struct evsel *evsel; 3000 int sample_id_all = 1, cpu; 3001 static char *kwlist[] = { "cpu", "sample_id_all", NULL }; 3002 struct mmap *md; 3003 PyObject *pyevent; 3004 int err; 3005 3006 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3007 3008 evlist = pevlist->evlist; 3009 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 3010 &cpu, &sample_id_all)) 3011 return NULL; 3012 3013 md = get_md(evlist, cpu); 3014 if (!md) 3015 return PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu); 3016 3017 err = perf_mmap__read_init(&md->core); 3018 if (err < 0) { 3019 if (err == -EAGAIN) 3020 Py_RETURN_NONE; 3021 return PyErr_Format(PyExc_OSError, 3022 "perf: error mmap read init, err=%d", err); 3023 } 3024 3025 event = perf_mmap__read_event(&md->core); 3026 if (event == NULL) 3027 Py_RETURN_NONE; 3028 3029 evsel = evlist__event2evsel(evlist, event); 3030 if (!evsel) { 3031 /* Unknown evsel. */ 3032 perf_mmap__consume(&md->core); 3033 Py_RETURN_NONE; 3034 } 3035 pyevent = pyrf_event__new(event, evsel, evlist__session(evlist), /*machine=*/NULL); 3036 perf_mmap__consume(&md->core); 3037 if (pyevent == NULL) 3038 return PyErr_Occurred() ? NULL : PyErr_NoMemory(); 3039 3040 return pyevent; 3041 } 3042 3043 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, 3044 PyObject *args, PyObject *kwargs) 3045 { 3046 struct evlist *evlist; 3047 3048 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3049 3050 evlist = pevlist->evlist; 3051 if (evlist__open(evlist) < 0) { 3052 PyErr_SetFromErrno(PyExc_OSError); 3053 return NULL; 3054 } 3055 3056 Py_INCREF(Py_None); 3057 return Py_None; 3058 } 3059 3060 static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist) 3061 { 3062 struct evlist *evlist; 3063 3064 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3065 3066 evlist = pevlist->evlist; 3067 evlist__close(evlist); 3068 3069 Py_INCREF(Py_None); 3070 return Py_None; 3071 } 3072 3073 static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist) 3074 { 3075 struct record_opts opts = { 3076 .sample_time = true, 3077 .mmap_pages = UINT_MAX, 3078 .user_freq = UINT_MAX, 3079 .user_interval = ULLONG_MAX, 3080 .freq = 4000, 3081 .target = { 3082 .uses_mmap = true, 3083 .default_per_cpu = true, 3084 }, 3085 .nr_threads_synthesize = 1, 3086 .ctl_fd = -1, 3087 .ctl_fd_ack = -1, 3088 .no_buffering = true, 3089 .no_inherit = true, 3090 }; 3091 struct evlist *evlist; 3092 3093 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3094 3095 evlist = pevlist->evlist; 3096 evlist__config(evlist, &opts, &callchain_param); 3097 Py_INCREF(Py_None); 3098 return Py_None; 3099 } 3100 3101 static PyObject *pyrf_evlist__disable(struct pyrf_evlist *pevlist) 3102 { 3103 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3104 evlist__disable(pevlist->evlist); 3105 Py_INCREF(Py_None); 3106 return Py_None; 3107 } 3108 3109 static PyObject *pyrf_evlist__enable(struct pyrf_evlist *pevlist) 3110 { 3111 CHECK_INITIALIZED(pevlist->evlist, "evlist"); 3112 evlist__enable(pevlist->evlist); 3113 Py_INCREF(Py_None); 3114 return Py_None; 3115 } 3116 3117 static PyMethodDef pyrf_evlist__methods[] = { 3118 { 3119 .ml_name = "all_cpus", 3120 .ml_meth = (PyCFunction)pyrf_evlist__all_cpus, 3121 .ml_flags = METH_NOARGS, 3122 .ml_doc = PyDoc_STR("CPU map union of all evsel CPU maps.") 3123 }, 3124 { 3125 .ml_name = "metrics", 3126 .ml_meth = (PyCFunction)pyrf_evlist__metrics, 3127 .ml_flags = METH_NOARGS, 3128 .ml_doc = PyDoc_STR("List of metric names within the evlist.") 3129 }, 3130 { 3131 .ml_name = "compute_metric", 3132 .ml_meth = (PyCFunction)pyrf_evlist__compute_metric, 3133 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3134 .ml_doc = PyDoc_STR("compute metric for given name, cpu and thread") 3135 }, 3136 { 3137 .ml_name = "mmap", 3138 .ml_meth = (PyCFunction)pyrf_evlist__mmap, 3139 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3140 .ml_doc = PyDoc_STR("mmap the file descriptor table.") 3141 }, 3142 { 3143 .ml_name = "open", 3144 .ml_meth = (PyCFunction)pyrf_evlist__open, 3145 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3146 .ml_doc = PyDoc_STR("open the file descriptors.") 3147 }, 3148 { 3149 .ml_name = "close", 3150 .ml_meth = (PyCFunction)pyrf_evlist__close, 3151 .ml_flags = METH_NOARGS, 3152 .ml_doc = PyDoc_STR("close the file descriptors.") 3153 }, 3154 { 3155 .ml_name = "poll", 3156 .ml_meth = (PyCFunction)pyrf_evlist__poll, 3157 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3158 .ml_doc = PyDoc_STR("poll the file descriptor table.") 3159 }, 3160 { 3161 .ml_name = "get_pollfd", 3162 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd, 3163 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3164 .ml_doc = PyDoc_STR("get the poll file descriptor table.") 3165 }, 3166 { 3167 .ml_name = "add", 3168 .ml_meth = (PyCFunction)pyrf_evlist__add, 3169 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3170 .ml_doc = PyDoc_STR("adds an event selector to the list.") 3171 }, 3172 { 3173 .ml_name = "read_on_cpu", 3174 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu, 3175 .ml_flags = METH_VARARGS | METH_KEYWORDS, 3176 .ml_doc = PyDoc_STR("reads an event.") 3177 }, 3178 { 3179 .ml_name = "config", 3180 .ml_meth = (PyCFunction)pyrf_evlist__config, 3181 .ml_flags = METH_NOARGS, 3182 .ml_doc = PyDoc_STR("Apply default record options to the evlist.") 3183 }, 3184 { 3185 .ml_name = "disable", 3186 .ml_meth = (PyCFunction)pyrf_evlist__disable, 3187 .ml_flags = METH_NOARGS, 3188 .ml_doc = PyDoc_STR("Disable the evsels in the evlist.") 3189 }, 3190 { 3191 .ml_name = "enable", 3192 .ml_meth = (PyCFunction)pyrf_evlist__enable, 3193 .ml_flags = METH_NOARGS, 3194 .ml_doc = PyDoc_STR("Enable the evsels in the evlist.") 3195 }, 3196 { .ml_name = NULL, } 3197 }; 3198 3199 static Py_ssize_t pyrf_evlist__length(PyObject *obj) 3200 { 3201 struct pyrf_evlist *pevlist = (void *)obj; 3202 3203 if (!pevlist->evlist) 3204 return 0; 3205 3206 return evlist__nr_entries(pevlist->evlist); 3207 } 3208 3209 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel) 3210 { 3211 struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type); 3212 3213 if (!pevsel) 3214 return NULL; 3215 3216 pevsel->evsel = evsel__get(evsel); 3217 return (PyObject *)pevsel; 3218 } 3219 3220 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) 3221 { 3222 struct pyrf_evlist *pevlist = (void *)obj; 3223 struct evsel *pos; 3224 3225 if (!pevlist->evlist || i >= evlist__nr_entries(pevlist->evlist)) { 3226 PyErr_SetString(PyExc_IndexError, "Index out of range"); 3227 return NULL; 3228 } 3229 3230 evlist__for_each_entry(pevlist->evlist, pos) { 3231 if (i-- == 0) 3232 break; 3233 } 3234 return pyrf_evsel__from_evsel(pos); 3235 } 3236 3237 static PyObject *pyrf_evlist__str(PyObject *self) 3238 { 3239 struct pyrf_evlist *pevlist = (void *)self; 3240 struct evsel *pos; 3241 struct strbuf sb = STRBUF_INIT; 3242 bool first = true; 3243 PyObject *result; 3244 3245 if (!pevlist->evlist) 3246 return PyUnicode_FromString("evlist(uninitialized)"); 3247 3248 strbuf_addstr(&sb, "evlist(["); 3249 evlist__for_each_entry(pevlist->evlist, pos) { 3250 if (!first) 3251 strbuf_addch(&sb, ','); 3252 strbuf_addstr(&sb, evsel__name(pos)); 3253 first = false; 3254 } 3255 strbuf_addstr(&sb, "])"); 3256 result = PyUnicode_FromString(sb.buf); 3257 strbuf_release(&sb); 3258 return result; 3259 } 3260 3261 static PySequenceMethods pyrf_evlist__sequence_methods = { 3262 .sq_length = pyrf_evlist__length, 3263 .sq_item = pyrf_evlist__item, 3264 }; 3265 3266 static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object."); 3267 3268 static PyObject *pyrf_evlist__getattro(struct pyrf_evlist *pevlist, PyObject *attr_name) 3269 { 3270 if (!pevlist->evlist) { 3271 PyErr_SetString(PyExc_ValueError, "evlist not initialized"); 3272 return NULL; 3273 } 3274 return PyObject_GenericGetAttr((PyObject *) pevlist, attr_name); 3275 } 3276 3277 static int pyrf_evlist__setattro(struct pyrf_evlist *pevlist, PyObject *attr_name, PyObject *value) 3278 { 3279 if (!pevlist->evlist) { 3280 PyErr_SetString(PyExc_ValueError, "evlist not initialized"); 3281 return -1; 3282 } 3283 return PyObject_GenericSetAttr((PyObject *) pevlist, attr_name, value); 3284 } 3285 3286 static PyTypeObject pyrf_evlist__type = { 3287 PyVarObject_HEAD_INIT(NULL, 0) 3288 .tp_name = "perf.evlist", 3289 .tp_basicsize = sizeof(struct pyrf_evlist), 3290 .tp_dealloc = (destructor)pyrf_evlist__delete, 3291 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 3292 .tp_as_sequence = &pyrf_evlist__sequence_methods, 3293 .tp_doc = pyrf_evlist__doc, 3294 .tp_methods = pyrf_evlist__methods, 3295 .tp_init = (initproc)pyrf_evlist__init, 3296 .tp_repr = pyrf_evlist__str, 3297 .tp_str = pyrf_evlist__str, 3298 .tp_getattro = (getattrofunc) pyrf_evlist__getattro, 3299 .tp_setattro = (setattrofunc) pyrf_evlist__setattro, 3300 }; 3301 3302 static PyObject *pyrf_evlist__new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 3303 { 3304 struct pyrf_evlist *pevlist; 3305 3306 pevlist = (struct pyrf_evlist *)PyType_GenericNew(type, args, kwargs); 3307 if (pevlist) 3308 pevlist->evlist = NULL; 3309 return (PyObject *)pevlist; 3310 } 3311 3312 static int pyrf_evlist__setup_types(void) 3313 { 3314 pyrf_evlist__type.tp_new = pyrf_evlist__new; 3315 return PyType_Ready(&pyrf_evlist__type); 3316 } 3317 3318 #define PERF_CONST(name) { #name, PERF_##name } 3319 3320 struct perf_constant { 3321 const char *name; 3322 int value; 3323 }; 3324 3325 static const struct perf_constant perf__constants[] = { 3326 PERF_CONST(TYPE_HARDWARE), 3327 PERF_CONST(TYPE_SOFTWARE), 3328 PERF_CONST(TYPE_TRACEPOINT), 3329 PERF_CONST(TYPE_HW_CACHE), 3330 PERF_CONST(TYPE_RAW), 3331 PERF_CONST(TYPE_BREAKPOINT), 3332 3333 PERF_CONST(COUNT_HW_CPU_CYCLES), 3334 PERF_CONST(COUNT_HW_REF_CPU_CYCLES), 3335 PERF_CONST(COUNT_HW_INSTRUCTIONS), 3336 PERF_CONST(COUNT_HW_CACHE_REFERENCES), 3337 PERF_CONST(COUNT_HW_CACHE_MISSES), 3338 PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS), 3339 PERF_CONST(COUNT_HW_BRANCH_MISSES), 3340 PERF_CONST(COUNT_HW_BUS_CYCLES), 3341 PERF_CONST(COUNT_HW_CACHE_L1D), 3342 PERF_CONST(COUNT_HW_CACHE_L1I), 3343 PERF_CONST(COUNT_HW_CACHE_LL), 3344 PERF_CONST(COUNT_HW_CACHE_DTLB), 3345 PERF_CONST(COUNT_HW_CACHE_ITLB), 3346 PERF_CONST(COUNT_HW_CACHE_BPU), 3347 PERF_CONST(COUNT_HW_CACHE_OP_READ), 3348 PERF_CONST(COUNT_HW_CACHE_OP_WRITE), 3349 PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH), 3350 PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS), 3351 PERF_CONST(COUNT_HW_CACHE_RESULT_MISS), 3352 3353 PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND), 3354 PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND), 3355 3356 PERF_CONST(COUNT_SW_CPU_CLOCK), 3357 PERF_CONST(COUNT_SW_TASK_CLOCK), 3358 PERF_CONST(COUNT_SW_PAGE_FAULTS), 3359 PERF_CONST(COUNT_SW_CONTEXT_SWITCHES), 3360 PERF_CONST(COUNT_SW_CPU_MIGRATIONS), 3361 PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN), 3362 PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ), 3363 PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS), 3364 PERF_CONST(COUNT_SW_EMULATION_FAULTS), 3365 PERF_CONST(COUNT_SW_DUMMY), 3366 3367 PERF_CONST(SAMPLE_IP), 3368 PERF_CONST(SAMPLE_TID), 3369 PERF_CONST(SAMPLE_TIME), 3370 PERF_CONST(SAMPLE_ADDR), 3371 PERF_CONST(SAMPLE_READ), 3372 PERF_CONST(SAMPLE_CALLCHAIN), 3373 PERF_CONST(SAMPLE_ID), 3374 PERF_CONST(SAMPLE_CPU), 3375 PERF_CONST(SAMPLE_PERIOD), 3376 PERF_CONST(SAMPLE_STREAM_ID), 3377 PERF_CONST(SAMPLE_RAW), 3378 3379 PERF_CONST(FORMAT_TOTAL_TIME_ENABLED), 3380 PERF_CONST(FORMAT_TOTAL_TIME_RUNNING), 3381 PERF_CONST(FORMAT_ID), 3382 PERF_CONST(FORMAT_GROUP), 3383 3384 PERF_CONST(RECORD_MMAP), 3385 PERF_CONST(RECORD_LOST), 3386 PERF_CONST(RECORD_COMM), 3387 PERF_CONST(RECORD_EXIT), 3388 PERF_CONST(RECORD_THROTTLE), 3389 PERF_CONST(RECORD_UNTHROTTLE), 3390 PERF_CONST(RECORD_FORK), 3391 PERF_CONST(RECORD_READ), 3392 PERF_CONST(RECORD_SAMPLE), 3393 PERF_CONST(RECORD_MMAP2), 3394 PERF_CONST(RECORD_AUX), 3395 PERF_CONST(RECORD_ITRACE_START), 3396 PERF_CONST(RECORD_LOST_SAMPLES), 3397 PERF_CONST(RECORD_SWITCH), 3398 PERF_CONST(RECORD_SWITCH_CPU_WIDE), 3399 PERF_CONST(RECORD_STAT), 3400 PERF_CONST(RECORD_STAT_ROUND), 3401 3402 PERF_CONST(RECORD_MISC_SWITCH_OUT), 3403 { .name = NULL, }, 3404 }; 3405 3406 static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, 3407 PyObject *args, PyObject *kwargs) 3408 { 3409 static char *kwlist[] = { "sys", "name", NULL }; 3410 char *sys = NULL; 3411 char *name = NULL; 3412 3413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist, 3414 &sys, &name)) 3415 return NULL; 3416 3417 return PyLong_FromLong(tp_pmu__id(sys, name)); 3418 } 3419 3420 static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist) 3421 { 3422 struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type); 3423 3424 if (!pevlist) 3425 return NULL; 3426 3427 pevlist->evlist = evlist__get(evlist); 3428 return (PyObject *)pevlist; 3429 } 3430 3431 static PyObject *pyrf__parse_events(PyObject *self, PyObject *args) 3432 { 3433 const char *input; 3434 struct evlist *evlist = evlist__new(); 3435 struct parse_events_error err; 3436 PyObject *result; 3437 PyObject *pcpus = NULL, *pthreads = NULL; 3438 struct perf_cpu_map *cpus; 3439 struct perf_thread_map *threads; 3440 3441 if (!evlist) 3442 return PyErr_NoMemory(); 3443 3444 if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) { 3445 evlist__put(evlist); 3446 return NULL; 3447 } 3448 3449 if (pthreads && pthreads != Py_None && 3450 !PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) { 3451 PyErr_SetString(PyExc_TypeError, "threads must be a perf.thread_map or None"); 3452 evlist__put(evlist); 3453 return NULL; 3454 } 3455 3456 if (pcpus && pcpus != Py_None && 3457 !PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) { 3458 PyErr_SetString(PyExc_TypeError, "cpus must be a perf.cpu_map or None"); 3459 evlist__put(evlist); 3460 return NULL; 3461 } 3462 3463 threads = (pthreads && pthreads != Py_None) ? 3464 ((struct pyrf_thread_map *)pthreads)->threads : NULL; 3465 cpus = (pcpus && pcpus != Py_None) ? 3466 ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; 3467 3468 parse_events_error__init(&err); 3469 perf_evlist__set_maps(evlist__core(evlist), cpus, threads); 3470 if (parse_events(evlist, input, &err)) { 3471 parse_events_error__print(&err, input); 3472 PyErr_SetFromErrno(PyExc_OSError); 3473 evlist__put(evlist); 3474 return NULL; 3475 } 3476 result = pyrf_evlist__from_evlist(evlist); 3477 evlist__put(evlist); 3478 return result; 3479 } 3480 3481 static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args) 3482 { 3483 const char *input, *pmu = NULL; 3484 struct evlist *evlist = evlist__new(); 3485 PyObject *result; 3486 PyObject *pcpus = NULL, *pthreads = NULL; 3487 struct perf_cpu_map *cpus; 3488 struct perf_thread_map *threads; 3489 int ret; 3490 3491 if (!evlist) 3492 return PyErr_NoMemory(); 3493 3494 if (!PyArg_ParseTuple(args, "s|sOO", &input, &pmu, &pcpus, &pthreads)) { 3495 evlist__put(evlist); 3496 return NULL; 3497 } 3498 3499 if (pthreads && pthreads != Py_None && 3500 !PyObject_TypeCheck(pthreads, &pyrf_thread_map__type)) { 3501 PyErr_SetString(PyExc_TypeError, "threads must be a perf.thread_map or None"); 3502 evlist__put(evlist); 3503 return NULL; 3504 } 3505 3506 if (pcpus && pcpus != Py_None && 3507 !PyObject_TypeCheck(pcpus, &pyrf_cpu_map__type)) { 3508 PyErr_SetString(PyExc_TypeError, "cpus must be a perf.cpu_map or None"); 3509 evlist__put(evlist); 3510 return NULL; 3511 } 3512 3513 threads = (pthreads && pthreads != Py_None) ? 3514 ((struct pyrf_thread_map *)pthreads)->threads : NULL; 3515 cpus = (pcpus && pcpus != Py_None) ? 3516 ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; 3517 3518 perf_evlist__set_maps(evlist__core(evlist), cpus, threads); 3519 ret = metricgroup__parse_groups(evlist, pmu ?: "all", 3520 /*cputype_filter=*/false, input, 3521 /*metric_no_group=*/ false, 3522 /*metric_no_merge=*/ false, 3523 /*metric_no_threshold=*/ true, 3524 /*user_requested_cpu_list=*/ NULL, 3525 /*system_wide=*/true, 3526 /*hardware_aware_grouping=*/ false); 3527 if (ret) { 3528 evlist__put(evlist); 3529 errno = -ret; 3530 PyErr_SetFromErrno(PyExc_OSError); 3531 return NULL; 3532 } 3533 result = pyrf_evlist__from_evlist(evlist); 3534 evlist__put(evlist); 3535 return result; 3536 } 3537 3538 static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm) 3539 { 3540 PyObject *groups = PyList_New(/*len=*/0); 3541 const char *mg = pm->metric_group; 3542 3543 if (!groups) 3544 return NULL; 3545 3546 while (mg) { 3547 PyObject *val = NULL; 3548 const char *sep = strchr(mg, ';'); 3549 size_t len = sep ? (size_t)(sep - mg) : strlen(mg); 3550 3551 if (len > 0) { 3552 val = PyUnicode_FromStringAndSize(mg, len); 3553 if (val) 3554 PyList_Append(groups, val); 3555 3556 Py_XDECREF(val); 3557 } 3558 mg = sep ? sep + 1 : NULL; 3559 } 3560 return groups; 3561 } 3562 3563 static int pyrf__metrics_cb(const struct pmu_metric *pm, 3564 const struct pmu_metrics_table *table __maybe_unused, 3565 void *vdata) 3566 { 3567 PyObject *py_list = vdata; 3568 PyObject *dict = PyDict_New(); 3569 PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL; 3570 PyObject *value = key ? pyrf__metrics_groups(pm) : NULL; 3571 3572 if (!value || PyDict_SetItem(dict, key, value) != 0) { 3573 Py_XDECREF(key); 3574 Py_XDECREF(value); 3575 Py_XDECREF(dict); 3576 return -ENOMEM; 3577 } 3578 Py_DECREF(key); 3579 Py_DECREF(value); 3580 3581 if (!add_to_dict(dict, "MetricName", pm->metric_name) || 3582 !add_to_dict(dict, "PMU", pm->pmu) || 3583 !add_to_dict(dict, "MetricExpr", pm->metric_expr) || 3584 !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) || 3585 !add_to_dict(dict, "ScaleUnit", pm->unit) || 3586 !add_to_dict(dict, "Compat", pm->compat) || 3587 !add_to_dict(dict, "BriefDescription", pm->desc) || 3588 !add_to_dict(dict, "PublicDescription", pm->long_desc) || 3589 PyList_Append(py_list, dict) != 0) { 3590 Py_DECREF(dict); 3591 return -ENOMEM; 3592 } 3593 Py_DECREF(dict); 3594 return 0; 3595 } 3596 3597 static PyObject *pyrf__metrics(PyObject *self, PyObject *args) 3598 { 3599 const struct pmu_metrics_table *table = pmu_metrics_table__find(); 3600 PyObject *list = PyList_New(/*len=*/0); 3601 int ret; 3602 3603 if (!list) 3604 return NULL; 3605 3606 ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list); 3607 if (!ret) 3608 ret = pmu_for_each_sys_metric(pyrf__metrics_cb, list); 3609 3610 if (ret) { 3611 Py_DECREF(list); 3612 errno = -ret; 3613 PyErr_SetFromErrno(PyExc_OSError); 3614 return NULL; 3615 } 3616 return list; 3617 } 3618 3619 struct pyrf_data { 3620 PyObject_HEAD 3621 3622 struct perf_data data; 3623 }; 3624 3625 static int pyrf_data__init(struct pyrf_data *pdata, PyObject *args, PyObject *kwargs) 3626 { 3627 static char *kwlist[] = { "path", "fd", NULL }; 3628 char *path = NULL; 3629 int fd = -1; 3630 3631 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|si", kwlist, &path, &fd)) 3632 return -1; 3633 3634 if (pdata->data.open) 3635 perf_data__close(&pdata->data); 3636 free((char *)pdata->data.path); 3637 memset(&pdata->data, 0, sizeof(pdata->data)); 3638 3639 if (fd != -1) { 3640 struct stat st; 3641 3642 if (fstat(fd, &st) < 0 || !S_ISFIFO(st.st_mode)) { 3643 PyErr_SetString(PyExc_ValueError, 3644 "fd argument is only supported for pipes"); 3645 return -1; 3646 } 3647 if (!path) 3648 path = "-"; 3649 else if (strcmp(path, "-") != 0) { 3650 PyErr_SetString(PyExc_ValueError, 3651 "path must be '-' when fd is provided"); 3652 return -1; 3653 } 3654 fd = dup(fd); 3655 if (fd < 0) { 3656 PyErr_SetFromErrno(PyExc_OSError); 3657 return -1; 3658 } 3659 } else if (path && strcmp(path, "-") == 0) { 3660 fd = dup(0); 3661 if (fd < 0) { 3662 PyErr_SetFromErrno(PyExc_OSError); 3663 return -1; 3664 } 3665 } 3666 3667 if (!path) 3668 path = "perf.data"; 3669 3670 pdata->data.path = strdup(path); 3671 if (!pdata->data.path) { 3672 if (fd != -1) 3673 close(fd); 3674 PyErr_NoMemory(); 3675 return -1; 3676 } 3677 3678 pdata->data.mode = PERF_DATA_MODE_READ; 3679 pdata->data.file.fd = fd; 3680 if (perf_data__open(&pdata->data) < 0) { 3681 PyErr_Format(PyExc_IOError, "Failed to open perf data: %s", 3682 pdata->data.path ? pdata->data.path : "perf.data"); 3683 return -1; 3684 } 3685 return 0; 3686 } 3687 3688 static void pyrf_data__delete(struct pyrf_data *pdata) 3689 { 3690 perf_data__close(&pdata->data); 3691 free((char *)pdata->data.path); 3692 Py_TYPE(pdata)->tp_free((PyObject *)pdata); 3693 } 3694 3695 static PyObject *pyrf_data__str(PyObject *self) 3696 { 3697 const struct pyrf_data *pdata = (const struct pyrf_data *)self; 3698 3699 if (!pdata->data.path) 3700 return PyUnicode_FromString("[uninitialized]"); 3701 return PyUnicode_FromString(pdata->data.path); 3702 } 3703 3704 static PyObject *pyrf_data__new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 3705 { 3706 struct pyrf_data *pdata; 3707 3708 pdata = (struct pyrf_data *)PyType_GenericNew(type, args, kwargs); 3709 if (pdata) 3710 memset(&pdata->data, 0, sizeof(pdata->data)); 3711 return (PyObject *)pdata; 3712 } 3713 3714 static const char pyrf_data__doc[] = PyDoc_STR("perf data file object."); 3715 3716 static PyTypeObject pyrf_data__type = { 3717 PyVarObject_HEAD_INIT(NULL, 0) 3718 .tp_name = "perf.data", 3719 .tp_basicsize = sizeof(struct pyrf_data), 3720 .tp_dealloc = (destructor)pyrf_data__delete, 3721 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 3722 .tp_doc = pyrf_data__doc, 3723 .tp_init = (initproc)pyrf_data__init, 3724 .tp_repr = pyrf_data__str, 3725 .tp_str = pyrf_data__str, 3726 }; 3727 3728 static int pyrf_data__setup_types(void) 3729 { 3730 pyrf_data__type.tp_new = pyrf_data__new; 3731 return PyType_Ready(&pyrf_data__type); 3732 } 3733 3734 struct pyrf_thread { 3735 PyObject_HEAD 3736 3737 struct thread *thread; 3738 }; 3739 3740 static void pyrf_thread__delete(struct pyrf_thread *pthread) 3741 { 3742 thread__put(pthread->thread); 3743 Py_TYPE(pthread)->tp_free((PyObject *)pthread); 3744 } 3745 3746 static PyObject *pyrf_thread__comm(PyObject *obj) 3747 { 3748 struct pyrf_thread *pthread = (void *)obj; 3749 const char *str; 3750 3751 CHECK_INITIALIZED(pthread->thread, "perf.thread"); 3752 3753 str = thread__comm_str(pthread->thread); 3754 3755 if (!str) 3756 Py_RETURN_NONE; 3757 3758 return PyUnicode_FromString(str); 3759 } 3760 3761 static PyMethodDef pyrf_thread__methods[] = { 3762 { 3763 .ml_name = "comm", 3764 .ml_meth = (PyCFunction)pyrf_thread__comm, 3765 .ml_flags = METH_NOARGS, 3766 .ml_doc = PyDoc_STR("Comm(and) associated with this thread.") 3767 }, 3768 { .ml_name = NULL, } 3769 }; 3770 3771 static PyObject *pyrf_thread__get_pid(struct pyrf_thread *pthread, void *closure __maybe_unused) 3772 { 3773 CHECK_INITIALIZED(pthread->thread, "thread"); 3774 return PyLong_FromLong(thread__pid(pthread->thread)); 3775 } 3776 3777 static PyObject *pyrf_thread__get_tid(struct pyrf_thread *pthread, void *closure __maybe_unused) 3778 { 3779 CHECK_INITIALIZED(pthread->thread, "thread"); 3780 return PyLong_FromLong(thread__tid(pthread->thread)); 3781 } 3782 3783 static PyObject *pyrf_thread__get_ppid(struct pyrf_thread *pthread, void *closure __maybe_unused) 3784 { 3785 CHECK_INITIALIZED(pthread->thread, "thread"); 3786 return PyLong_FromLong(thread__ppid(pthread->thread)); 3787 } 3788 3789 static PyObject *pyrf_thread__get_cpu(struct pyrf_thread *pthread, void *closure __maybe_unused) 3790 { 3791 CHECK_INITIALIZED(pthread->thread, "thread"); 3792 return PyLong_FromLong(thread__cpu(pthread->thread)); 3793 } 3794 3795 static PyGetSetDef pyrf_thread__getset[] = { 3796 { .name = "pid", .get = (getter)pyrf_thread__get_pid, .doc = "process ID" }, 3797 { .name = "tid", .get = (getter)pyrf_thread__get_tid, .doc = "thread ID" }, 3798 { .name = "ppid", .get = (getter)pyrf_thread__get_ppid, .doc = "parent process ID" }, 3799 { .name = "cpu", .get = (getter)pyrf_thread__get_cpu, .doc = "cpu number" }, 3800 { .name = NULL } 3801 }; 3802 3803 static const char pyrf_thread__doc[] = PyDoc_STR("perf thread object."); 3804 3805 static PyTypeObject pyrf_thread__type = { 3806 PyVarObject_HEAD_INIT(NULL, 0) 3807 .tp_name = "perf.thread", 3808 .tp_basicsize = sizeof(struct pyrf_thread), 3809 .tp_dealloc = (destructor)pyrf_thread__delete, 3810 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 3811 .tp_methods = pyrf_thread__methods, 3812 .tp_getset = pyrf_thread__getset, 3813 .tp_doc = pyrf_thread__doc, 3814 }; 3815 3816 static int pyrf_thread__setup_types(void) 3817 { 3818 return PyType_Ready(&pyrf_thread__type); 3819 } 3820 3821 static PyObject *pyrf_thread__from_thread(struct thread *thread) 3822 { 3823 struct pyrf_thread *pthread = PyObject_New(struct pyrf_thread, &pyrf_thread__type); 3824 3825 if (!pthread) 3826 return NULL; 3827 3828 pthread->thread = thread__get(thread); 3829 return (PyObject *)pthread; 3830 } 3831 3832 struct pyrf_session { 3833 PyObject_HEAD 3834 3835 struct perf_session *session; 3836 struct perf_tool tool; 3837 struct pyrf_data *pdata; 3838 PyObject *sample; 3839 PyObject *stat; 3840 }; 3841 3842 static int pyrf_session_tool__sample(const struct perf_tool *tool, 3843 union perf_event *event, 3844 struct perf_sample *sample, 3845 struct machine *machine) 3846 { 3847 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool); 3848 PyObject *pyevent = pyrf_event__new(event, sample->evsel, psession->session, machine); 3849 PyObject *ret; 3850 3851 if (pyevent == NULL) 3852 return -ENOMEM; 3853 3854 ret = PyObject_CallFunction(psession->sample, "O", pyevent); 3855 if (!ret) { 3856 Py_DECREF(pyevent); 3857 return -1; 3858 } 3859 Py_DECREF(ret); 3860 Py_DECREF(pyevent); 3861 return 0; 3862 } 3863 3864 static int pyrf_session_tool__stat(const struct perf_tool *tool, 3865 struct perf_session *session, 3866 union perf_event *event) 3867 { 3868 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool); 3869 struct evsel *evsel = evlist__id2evsel(session->evlist, event->stat.id); 3870 PyObject *pyevent = pyrf_event__new(event, /*evsel=*/NULL, psession->session, 3871 /*machine=*/NULL); 3872 const char *name = evsel ? evsel__name(evsel) : "unknown"; 3873 PyObject *ret; 3874 3875 if (pyevent == NULL) 3876 return -ENOMEM; 3877 3878 ret = PyObject_CallFunction(psession->stat, "Oz", pyevent, name); 3879 if (!ret) { 3880 Py_DECREF(pyevent); 3881 return -1; 3882 } 3883 Py_DECREF(ret); 3884 Py_DECREF(pyevent); 3885 return 0; 3886 } 3887 3888 static int pyrf_session_tool__stat_round(const struct perf_tool *tool, 3889 struct perf_session *session __maybe_unused, 3890 union perf_event *event) 3891 { 3892 struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool); 3893 PyObject *pyevent = pyrf_event__new(event, /*evsel=*/NULL, psession->session, 3894 /*machine=*/NULL); 3895 PyObject *ret; 3896 3897 if (pyevent == NULL) 3898 return -ENOMEM; 3899 3900 ret = PyObject_CallFunction(psession->stat, "Oz", pyevent, NULL); 3901 if (!ret) { 3902 Py_DECREF(pyevent); 3903 return -1; 3904 } 3905 Py_DECREF(ret); 3906 Py_DECREF(pyevent); 3907 return 0; 3908 } 3909 3910 static PyObject *pyrf_session__find_thread(struct pyrf_session *psession, PyObject *args) 3911 { 3912 struct machine *machine; 3913 struct thread *thread = NULL; 3914 PyObject *result; 3915 int pid; 3916 3917 CHECK_INITIALIZED(psession->session, "session"); 3918 3919 if (!PyArg_ParseTuple(args, "i", &pid)) 3920 return NULL; 3921 3922 machine = &psession->session->machines.host; 3923 thread = machine__find_thread(machine, pid, pid); 3924 3925 if (!thread) { 3926 machine = perf_session__find_machine(psession->session, pid); 3927 if (machine) 3928 thread = machine__find_thread(machine, pid, pid); 3929 } 3930 3931 if (!thread) { 3932 PyErr_Format(PyExc_TypeError, "Failed to find thread %d", pid); 3933 return NULL; 3934 } 3935 result = pyrf_thread__from_thread(thread); 3936 thread__put(thread); 3937 return result; 3938 } 3939 3940 static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 3941 { 3942 struct pyrf_data *pdata; 3943 PyObject *sample = NULL, *stat = NULL; 3944 static char *kwlist[] = { "data", "sample", "stat", NULL }; 3945 struct pyrf_session *psession; 3946 struct perf_session *session; 3947 3948 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &pyrf_data__type, &pdata, 3949 &sample, &stat)) 3950 return NULL; 3951 3952 psession = PyObject_New(struct pyrf_session, type); 3953 if (!psession) 3954 return NULL; 3955 3956 psession->session = NULL; 3957 psession->sample = NULL; 3958 psession->stat = NULL; 3959 psession->pdata = NULL; 3960 3961 Py_INCREF(pdata); 3962 psession->pdata = pdata; 3963 3964 perf_tool__init(&psession->tool, /*ordered_events=*/true); 3965 psession->tool.ordering_requires_timestamps = true; 3966 3967 #define ADD_TOOL(name) \ 3968 do { \ 3969 if (name) { \ 3970 if (!PyCallable_Check(name)) { \ 3971 PyErr_SetString(PyExc_TypeError, #name " must be callable"); \ 3972 goto err_out; \ 3973 } \ 3974 psession->tool.name = pyrf_session_tool__##name; \ 3975 Py_INCREF(name); \ 3976 psession->name = name; \ 3977 } \ 3978 } while (0) 3979 3980 ADD_TOOL(sample); 3981 ADD_TOOL(stat); 3982 #undef ADD_TOOL 3983 3984 if (stat) 3985 psession->tool.stat_round = pyrf_session_tool__stat_round; 3986 3987 3988 psession->tool.comm = perf_event__process_comm; 3989 psession->tool.mmap = perf_event__process_mmap; 3990 psession->tool.mmap2 = perf_event__process_mmap2; 3991 psession->tool.namespaces = perf_event__process_namespaces; 3992 psession->tool.cgroup = perf_event__process_cgroup; 3993 psession->tool.exit = perf_event__process_exit; 3994 psession->tool.fork = perf_event__process_fork; 3995 psession->tool.ksymbol = perf_event__process_ksymbol; 3996 psession->tool.text_poke = perf_event__process_text_poke; 3997 psession->tool.build_id = perf_event__process_build_id; 3998 psession->tool.attr = perf_event__process_attr; 3999 psession->tool.feature = perf_event__process_feature; 4000 4001 session = perf_session__new(&pdata->data, &psession->tool); 4002 if (IS_ERR(session)) { 4003 PyErr_Format(PyExc_IOError, "failed to create session: %ld", PTR_ERR(session)); 4004 goto err_out; 4005 } 4006 psession->session = session; 4007 4008 symbol_conf.use_callchain = true; 4009 symbol_conf.show_kernel_path = true; 4010 symbol_conf.inline_name = false; 4011 if (symbol__init(perf_session__env(session)) < 0) { 4012 PyErr_SetString(PyExc_OSError, "perf: symbol__init failed"); 4013 goto err_out; 4014 } 4015 4016 4017 4018 return (PyObject *)psession; 4019 err_out: 4020 Py_DECREF(psession); 4021 return NULL; 4022 } 4023 4024 static void pyrf_session__delete(struct pyrf_session *psession) 4025 { 4026 perf_session__delete(psession->session); 4027 Py_XDECREF(psession->pdata); 4028 Py_XDECREF(psession->sample); 4029 Py_XDECREF(psession->stat); 4030 Py_TYPE(psession)->tp_free((PyObject *)psession); 4031 } 4032 4033 static PyObject *pyrf_session__find_thread_events(struct pyrf_session *psession) 4034 { 4035 int err; 4036 4037 CHECK_INITIALIZED(psession->session, "session"); 4038 4039 err = perf_session__process_events(psession->session); 4040 4041 if (PyErr_Occurred()) 4042 return NULL; 4043 4044 if (err < 0) { 4045 PyErr_Format(PyExc_OSError, "Process events failed: %d", err); 4046 return NULL; 4047 } 4048 4049 Py_RETURN_NONE; 4050 } 4051 4052 static PyMethodDef pyrf_session__methods[] = { 4053 { 4054 .ml_name = "process_events", 4055 .ml_meth = (PyCFunction)pyrf_session__find_thread_events, 4056 .ml_flags = METH_NOARGS, 4057 .ml_doc = PyDoc_STR("Iterate and process events.") 4058 }, 4059 { 4060 .ml_name = "find_thread", 4061 .ml_meth = (PyCFunction)pyrf_session__find_thread, 4062 .ml_flags = METH_VARARGS, 4063 .ml_doc = PyDoc_STR("Returns the thread associated with a pid.") 4064 }, 4065 { .ml_name = NULL, } 4066 }; 4067 4068 static const char pyrf_session__doc[] = PyDoc_STR("perf session object."); 4069 4070 static PyObject *pyrf_session__getattro(struct pyrf_session *psession, PyObject *attr_name) 4071 { 4072 if (!psession->session) { 4073 PyErr_SetString(PyExc_ValueError, "session not initialized"); 4074 return NULL; 4075 } 4076 return PyObject_GenericGetAttr((PyObject *) psession, attr_name); 4077 } 4078 4079 static int pyrf_session__setattro(struct pyrf_session *psession, PyObject *attr_name, 4080 PyObject *value) 4081 { 4082 if (!psession->session) { 4083 PyErr_SetString(PyExc_ValueError, "session not initialized"); 4084 return -1; 4085 } 4086 return PyObject_GenericSetAttr((PyObject *) psession, attr_name, value); 4087 } 4088 4089 static PyTypeObject pyrf_session__type = { 4090 PyVarObject_HEAD_INIT(NULL, 0) 4091 .tp_name = "perf.session", 4092 .tp_basicsize = sizeof(struct pyrf_session), 4093 .tp_dealloc = (destructor)pyrf_session__delete, 4094 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 4095 .tp_methods = pyrf_session__methods, 4096 .tp_doc = pyrf_session__doc, 4097 .tp_new = pyrf_session__new, 4098 .tp_getattro = (getattrofunc) pyrf_session__getattro, 4099 .tp_setattro = (setattrofunc) pyrf_session__setattro, 4100 }; 4101 4102 static int pyrf_session__setup_types(void) 4103 { 4104 return PyType_Ready(&pyrf_session__type); 4105 } 4106 4107 static PyObject *pyrf__syscall_name(PyObject *self, PyObject *args, PyObject *kwargs) 4108 { 4109 const char *name; 4110 int id; 4111 int elf_machine = EM_HOST; 4112 static char *kwlist[] = { "id", "elf_machine", NULL }; 4113 4114 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|$i", kwlist, &id, &elf_machine)) 4115 return NULL; 4116 4117 name = syscalltbl__name(elf_machine, id); 4118 if (!name) 4119 Py_RETURN_NONE; 4120 return PyUnicode_FromString(name); 4121 } 4122 4123 static PyObject *pyrf__syscall_id(PyObject *self, PyObject *args, PyObject *kwargs) 4124 { 4125 const char *name; 4126 int id; 4127 int elf_machine = EM_HOST; 4128 static char *kwlist[] = { "name", "elf_machine", NULL }; 4129 4130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|$i", kwlist, &name, &elf_machine)) 4131 return NULL; 4132 4133 id = syscalltbl__id(elf_machine, name); 4134 if (id < 0) { 4135 PyErr_Format(PyExc_ValueError, "Failed to find syscall %s", name); 4136 return NULL; 4137 } 4138 return PyLong_FromLong(id); 4139 } 4140 4141 static PyObject *pyrf__config_get(PyObject *self, PyObject *args) 4142 { 4143 const char *config_name, *val; 4144 4145 if (!PyArg_ParseTuple(args, "s", &config_name)) 4146 return NULL; 4147 4148 val = perf_config_get(config_name); 4149 if (!val) 4150 Py_RETURN_NONE; 4151 return PyUnicode_FromString(val); 4152 } 4153 4154 static PyMethodDef perf__methods[] = { 4155 { 4156 .ml_name = "config_get", 4157 .ml_meth = (PyCFunction) pyrf__config_get, 4158 .ml_flags = METH_VARARGS, 4159 .ml_doc = PyDoc_STR("Get a perf config value.") 4160 }, 4161 { 4162 .ml_name = "metrics", 4163 .ml_meth = (PyCFunction) pyrf__metrics, 4164 .ml_flags = METH_NOARGS, 4165 .ml_doc = PyDoc_STR( 4166 "Returns a list of metrics represented as string values in dictionaries.") 4167 }, 4168 { 4169 .ml_name = "tracepoint", 4170 .ml_meth = (PyCFunction) pyrf__tracepoint, 4171 .ml_flags = METH_VARARGS | METH_KEYWORDS, 4172 .ml_doc = PyDoc_STR("Get tracepoint config.") 4173 }, 4174 { 4175 .ml_name = "parse_events", 4176 .ml_meth = (PyCFunction) pyrf__parse_events, 4177 .ml_flags = METH_VARARGS, 4178 .ml_doc = PyDoc_STR("Parse a string of events and return an evlist.") 4179 }, 4180 { 4181 .ml_name = "parse_metrics", 4182 .ml_meth = (PyCFunction) pyrf__parse_metrics, 4183 .ml_flags = METH_VARARGS, 4184 .ml_doc = PyDoc_STR( 4185 "Parse a string of metrics or metric groups and return an evlist.") 4186 }, 4187 { 4188 .ml_name = "pmus", 4189 .ml_meth = (PyCFunction) pyrf__pmus, 4190 .ml_flags = METH_NOARGS, 4191 .ml_doc = PyDoc_STR("Returns a sequence of pmus.") 4192 }, 4193 { 4194 .ml_name = "syscall_name", 4195 .ml_meth = (PyCFunction) pyrf__syscall_name, 4196 .ml_flags = METH_VARARGS | METH_KEYWORDS, 4197 .ml_doc = PyDoc_STR("Turns a syscall number to a string.") 4198 }, 4199 { 4200 .ml_name = "syscall_id", 4201 .ml_meth = (PyCFunction) pyrf__syscall_id, 4202 .ml_flags = METH_VARARGS | METH_KEYWORDS, 4203 .ml_doc = PyDoc_STR("Turns a syscall name to a number.") 4204 }, 4205 { .ml_name = NULL, } 4206 }; 4207 4208 PyMODINIT_FUNC PyInit_perf(void) 4209 { 4210 PyObject *obj; 4211 int i; 4212 PyObject *dict; 4213 static struct PyModuleDef moduledef = { 4214 PyModuleDef_HEAD_INIT, 4215 "perf", /* m_name */ 4216 "", /* m_doc */ 4217 -1, /* m_size */ 4218 perf__methods, /* m_methods */ 4219 NULL, /* m_reload */ 4220 NULL, /* m_traverse */ 4221 NULL, /* m_clear */ 4222 NULL, /* m_free */ 4223 }; 4224 PyObject *module = PyModule_Create(&moduledef); 4225 4226 if (module == NULL) 4227 return NULL; 4228 4229 if (pyrf_event__setup_types() < 0 || 4230 pyrf_evlist__setup_types() < 0 || 4231 pyrf_evsel__setup_types() < 0 || 4232 pyrf_thread_map__setup_types() < 0 || 4233 pyrf_cpu_map__setup_types() < 0 || 4234 pyrf_pmu_iterator__setup_types() < 0 || 4235 pyrf_pmu__setup_types() < 0 || 4236 pyrf_counts_values__setup_types() < 0 || 4237 pyrf_data__setup_types() < 0 || 4238 pyrf_session__setup_types() < 0 || 4239 pyrf_thread__setup_types() < 0) { 4240 Py_DECREF(module); 4241 return NULL; 4242 } 4243 4244 /* The page_size is placed in util object. */ 4245 page_size = sysconf(_SC_PAGE_SIZE); 4246 4247 Py_INCREF(&pyrf_evlist__type); 4248 PyModule_AddObject(module, "evlist", (PyObject *)&pyrf_evlist__type); 4249 4250 Py_INCREF(&pyrf_evsel__type); 4251 PyModule_AddObject(module, "evsel", (PyObject *)&pyrf_evsel__type); 4252 4253 Py_INCREF(&pyrf_thread__type); 4254 PyModule_AddObject(module, "thread", (PyObject *)&pyrf_thread__type); 4255 4256 Py_INCREF(&pyrf_callchain__type); 4257 PyModule_AddObject(module, "callchain", (PyObject *)&pyrf_callchain__type); 4258 4259 Py_INCREF(&pyrf_callchain_node__type); 4260 PyModule_AddObject(module, "callchain_node", (PyObject *)&pyrf_callchain_node__type); 4261 4262 Py_INCREF(&pyrf_mmap_event__type); 4263 PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type); 4264 4265 Py_INCREF(&pyrf_mmap2_event__type); 4266 PyModule_AddObject(module, "mmap2_event", (PyObject *)&pyrf_mmap2_event__type); 4267 4268 Py_INCREF(&pyrf_lost_event__type); 4269 PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type); 4270 4271 Py_INCREF(&pyrf_comm_event__type); 4272 PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type); 4273 4274 Py_INCREF(&pyrf_task_event__type); 4275 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); 4276 4277 Py_INCREF(&pyrf_throttle_event__type); 4278 PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type); 4279 4280 Py_INCREF(&pyrf_task_event__type); 4281 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); 4282 4283 Py_INCREF(&pyrf_read_event__type); 4284 PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type); 4285 4286 Py_INCREF(&pyrf_sample_event__type); 4287 PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type); 4288 4289 Py_INCREF(&pyrf_context_switch_event__type); 4290 PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type); 4291 4292 Py_INCREF(&pyrf_stat_event__type); 4293 PyModule_AddObject(module, "stat_event", (PyObject *)&pyrf_stat_event__type); 4294 4295 Py_INCREF(&pyrf_stat_round_event__type); 4296 PyModule_AddObject(module, "stat_round_event", (PyObject *)&pyrf_stat_round_event__type); 4297 4298 Py_INCREF(&pyrf_thread_map__type); 4299 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); 4300 4301 Py_INCREF(&pyrf_cpu_map__type); 4302 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type); 4303 4304 Py_INCREF(&pyrf_counts_values__type); 4305 PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type); 4306 4307 Py_INCREF(&pyrf_data__type); 4308 PyModule_AddObject(module, "data", (PyObject *)&pyrf_data__type); 4309 4310 Py_INCREF(&pyrf_session__type); 4311 PyModule_AddObject(module, "session", (PyObject *)&pyrf_session__type); 4312 4313 Py_INCREF(&pyrf_branch_entry__type); 4314 if (PyModule_AddObject(module, "branch_entry", (PyObject *)&pyrf_branch_entry__type) < 0) { 4315 Py_DECREF(&pyrf_branch_entry__type); 4316 goto error; 4317 } 4318 4319 Py_INCREF(&pyrf_branch_stack__type); 4320 if (PyModule_AddObject(module, "branch_stack", (PyObject *)&pyrf_branch_stack__type) < 0) { 4321 Py_DECREF(&pyrf_branch_stack__type); 4322 goto error; 4323 } 4324 4325 dict = PyModule_GetDict(module); 4326 if (dict == NULL) 4327 goto error; 4328 4329 for (i = 0; perf__constants[i].name != NULL; i++) { 4330 obj = PyLong_FromLong(perf__constants[i].value); 4331 if (obj == NULL) 4332 goto error; 4333 PyDict_SetItemString(dict, perf__constants[i].name, obj); 4334 Py_DECREF(obj); 4335 } 4336 4337 error: 4338 if (PyErr_Occurred()) { 4339 Py_XDECREF(module); 4340 return NULL; 4341 } 4342 return module; 4343 } 4344