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