1 // SPDX-License-Identifier: GPL-2.0 2 #include <Python.h> 3 #include <structmember.h> 4 #include <inttypes.h> 5 #include <poll.h> 6 #include <linux/err.h> 7 #include <perf/cpumap.h> 8 #ifdef HAVE_LIBTRACEEVENT 9 #include <event-parse.h> 10 #endif 11 #include <perf/mmap.h> 12 #include "callchain.h" 13 #include "counts.h" 14 #include "evlist.h" 15 #include "evsel.h" 16 #include "event.h" 17 #include "expr.h" 18 #include "print_binary.h" 19 #include "record.h" 20 #include "strbuf.h" 21 #include "thread_map.h" 22 #include "tp_pmu.h" 23 #include "trace-event.h" 24 #include "metricgroup.h" 25 #include "mmap.h" 26 #include "util/sample.h" 27 #include <internal/lib.h> 28 29 PyMODINIT_FUNC PyInit_perf(void); 30 31 #define member_def(type, member, ptype, help) \ 32 { #member, ptype, \ 33 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \ 34 0, help } 35 36 #define sample_member_def(name, member, ptype, help) \ 37 { #name, ptype, \ 38 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \ 39 0, help } 40 41 struct pyrf_event { 42 PyObject_HEAD 43 struct evsel *evsel; 44 struct perf_sample sample; 45 union perf_event event; 46 }; 47 48 #define sample_members \ 49 sample_member_def(sample_ip, ip, T_ULONGLONG, "event ip"), \ 50 sample_member_def(sample_pid, pid, T_INT, "event pid"), \ 51 sample_member_def(sample_tid, tid, T_INT, "event tid"), \ 52 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ 53 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \ 54 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \ 55 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \ 56 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \ 57 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), 58 59 static const char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); 60 61 static PyMemberDef pyrf_mmap_event__members[] = { 62 sample_members 63 member_def(perf_event_header, type, T_UINT, "event type"), 64 member_def(perf_event_header, misc, T_UINT, "event misc"), 65 member_def(perf_record_mmap, pid, T_UINT, "event pid"), 66 member_def(perf_record_mmap, tid, T_UINT, "event tid"), 67 member_def(perf_record_mmap, start, T_ULONGLONG, "start of the map"), 68 member_def(perf_record_mmap, len, T_ULONGLONG, "map length"), 69 member_def(perf_record_mmap, pgoff, T_ULONGLONG, "page offset"), 70 member_def(perf_record_mmap, filename, T_STRING_INPLACE, "backing store"), 71 { .name = NULL, }, 72 }; 73 74 static PyObject *pyrf_mmap_event__repr(const struct pyrf_event *pevent) 75 { 76 PyObject *ret; 77 char *s; 78 79 if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRI_lx64 ", " 80 "length: %#" PRI_lx64 ", offset: %#" PRI_lx64 ", " 81 "filename: %s }", 82 pevent->event.mmap.pid, pevent->event.mmap.tid, 83 pevent->event.mmap.start, pevent->event.mmap.len, 84 pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { 85 ret = PyErr_NoMemory(); 86 } else { 87 ret = PyUnicode_FromString(s); 88 free(s); 89 } 90 return ret; 91 } 92 93 static PyTypeObject pyrf_mmap_event__type = { 94 PyVarObject_HEAD_INIT(NULL, 0) 95 .tp_name = "perf.mmap_event", 96 .tp_basicsize = sizeof(struct pyrf_event), 97 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 98 .tp_doc = pyrf_mmap_event__doc, 99 .tp_members = pyrf_mmap_event__members, 100 .tp_repr = (reprfunc)pyrf_mmap_event__repr, 101 }; 102 103 static const char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); 104 105 static PyMemberDef pyrf_task_event__members[] = { 106 sample_members 107 member_def(perf_event_header, type, T_UINT, "event type"), 108 member_def(perf_record_fork, pid, T_UINT, "event pid"), 109 member_def(perf_record_fork, ppid, T_UINT, "event ppid"), 110 member_def(perf_record_fork, tid, T_UINT, "event tid"), 111 member_def(perf_record_fork, ptid, T_UINT, "event ptid"), 112 member_def(perf_record_fork, time, T_ULONGLONG, "timestamp"), 113 { .name = NULL, }, 114 }; 115 116 static PyObject *pyrf_task_event__repr(const struct pyrf_event *pevent) 117 { 118 return PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " 119 "ptid: %u, time: %" PRI_lu64 "}", 120 pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", 121 pevent->event.fork.pid, 122 pevent->event.fork.ppid, 123 pevent->event.fork.tid, 124 pevent->event.fork.ptid, 125 pevent->event.fork.time); 126 } 127 128 static PyTypeObject pyrf_task_event__type = { 129 PyVarObject_HEAD_INIT(NULL, 0) 130 .tp_name = "perf.task_event", 131 .tp_basicsize = sizeof(struct pyrf_event), 132 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 133 .tp_doc = pyrf_task_event__doc, 134 .tp_members = pyrf_task_event__members, 135 .tp_repr = (reprfunc)pyrf_task_event__repr, 136 }; 137 138 static const char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); 139 140 static PyMemberDef pyrf_comm_event__members[] = { 141 sample_members 142 member_def(perf_event_header, type, T_UINT, "event type"), 143 member_def(perf_record_comm, pid, T_UINT, "event pid"), 144 member_def(perf_record_comm, tid, T_UINT, "event tid"), 145 member_def(perf_record_comm, comm, T_STRING_INPLACE, "process name"), 146 { .name = NULL, }, 147 }; 148 149 static PyObject *pyrf_comm_event__repr(const struct pyrf_event *pevent) 150 { 151 return PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", 152 pevent->event.comm.pid, 153 pevent->event.comm.tid, 154 pevent->event.comm.comm); 155 } 156 157 static PyTypeObject pyrf_comm_event__type = { 158 PyVarObject_HEAD_INIT(NULL, 0) 159 .tp_name = "perf.comm_event", 160 .tp_basicsize = sizeof(struct pyrf_event), 161 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 162 .tp_doc = pyrf_comm_event__doc, 163 .tp_members = pyrf_comm_event__members, 164 .tp_repr = (reprfunc)pyrf_comm_event__repr, 165 }; 166 167 static const char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); 168 169 static PyMemberDef pyrf_throttle_event__members[] = { 170 sample_members 171 member_def(perf_event_header, type, T_UINT, "event type"), 172 member_def(perf_record_throttle, time, T_ULONGLONG, "timestamp"), 173 member_def(perf_record_throttle, id, T_ULONGLONG, "event id"), 174 member_def(perf_record_throttle, stream_id, T_ULONGLONG, "event stream id"), 175 { .name = NULL, }, 176 }; 177 178 static PyObject *pyrf_throttle_event__repr(const struct pyrf_event *pevent) 179 { 180 const struct perf_record_throttle *te = (const struct perf_record_throttle *) 181 (&pevent->event.header + 1); 182 183 return PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRI_lu64 ", id: %" PRI_lu64 184 ", stream_id: %" PRI_lu64 " }", 185 pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", 186 te->time, te->id, te->stream_id); 187 } 188 189 static PyTypeObject pyrf_throttle_event__type = { 190 PyVarObject_HEAD_INIT(NULL, 0) 191 .tp_name = "perf.throttle_event", 192 .tp_basicsize = sizeof(struct pyrf_event), 193 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 194 .tp_doc = pyrf_throttle_event__doc, 195 .tp_members = pyrf_throttle_event__members, 196 .tp_repr = (reprfunc)pyrf_throttle_event__repr, 197 }; 198 199 static const char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); 200 201 static PyMemberDef pyrf_lost_event__members[] = { 202 sample_members 203 member_def(perf_record_lost, id, T_ULONGLONG, "event id"), 204 member_def(perf_record_lost, lost, T_ULONGLONG, "number of lost events"), 205 { .name = NULL, }, 206 }; 207 208 static PyObject *pyrf_lost_event__repr(const struct pyrf_event *pevent) 209 { 210 PyObject *ret; 211 char *s; 212 213 if (asprintf(&s, "{ type: lost, id: %#" PRI_lx64 ", " 214 "lost: %#" PRI_lx64 " }", 215 pevent->event.lost.id, pevent->event.lost.lost) < 0) { 216 ret = PyErr_NoMemory(); 217 } else { 218 ret = PyUnicode_FromString(s); 219 free(s); 220 } 221 return ret; 222 } 223 224 static PyTypeObject pyrf_lost_event__type = { 225 PyVarObject_HEAD_INIT(NULL, 0) 226 .tp_name = "perf.lost_event", 227 .tp_basicsize = sizeof(struct pyrf_event), 228 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 229 .tp_doc = pyrf_lost_event__doc, 230 .tp_members = pyrf_lost_event__members, 231 .tp_repr = (reprfunc)pyrf_lost_event__repr, 232 }; 233 234 static const char pyrf_read_event__doc[] = PyDoc_STR("perf read event object."); 235 236 static PyMemberDef pyrf_read_event__members[] = { 237 sample_members 238 member_def(perf_record_read, pid, T_UINT, "event pid"), 239 member_def(perf_record_read, tid, T_UINT, "event tid"), 240 { .name = NULL, }, 241 }; 242 243 static PyObject *pyrf_read_event__repr(const struct pyrf_event *pevent) 244 { 245 return PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }", 246 pevent->event.read.pid, 247 pevent->event.read.tid); 248 /* 249 * FIXME: return the array of read values, 250 * making this method useful ;-) 251 */ 252 } 253 254 static PyTypeObject pyrf_read_event__type = { 255 PyVarObject_HEAD_INIT(NULL, 0) 256 .tp_name = "perf.read_event", 257 .tp_basicsize = sizeof(struct pyrf_event), 258 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 259 .tp_doc = pyrf_read_event__doc, 260 .tp_members = pyrf_read_event__members, 261 .tp_repr = (reprfunc)pyrf_read_event__repr, 262 }; 263 264 static const char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object."); 265 266 static PyMemberDef pyrf_sample_event__members[] = { 267 sample_members 268 member_def(perf_event_header, type, T_UINT, "event type"), 269 { .name = NULL, }, 270 }; 271 272 static void pyrf_sample_event__delete(struct pyrf_event *pevent) 273 { 274 perf_sample__exit(&pevent->sample); 275 Py_TYPE(pevent)->tp_free((PyObject*)pevent); 276 } 277 278 static PyObject *pyrf_sample_event__repr(const struct pyrf_event *pevent) 279 { 280 PyObject *ret; 281 char *s; 282 283 if (asprintf(&s, "{ type: sample }") < 0) { 284 ret = PyErr_NoMemory(); 285 } else { 286 ret = PyUnicode_FromString(s); 287 free(s); 288 } 289 return ret; 290 } 291 292 #ifdef HAVE_LIBTRACEEVENT 293 static bool is_tracepoint(const struct pyrf_event *pevent) 294 { 295 return pevent->evsel->core.attr.type == PERF_TYPE_TRACEPOINT; 296 } 297 298 static PyObject* 299 tracepoint_field(const struct pyrf_event *pe, struct tep_format_field *field) 300 { 301 struct tep_handle *pevent = field->event->tep; 302 void *data = pe->sample.raw_data; 303 PyObject *ret = NULL; 304 unsigned long long val; 305 unsigned int offset, len; 306 307 if (field->flags & TEP_FIELD_IS_ARRAY) { 308 offset = field->offset; 309 len = field->size; 310 if (field->flags & TEP_FIELD_IS_DYNAMIC) { 311 val = tep_read_number(pevent, data + offset, len); 312 offset = val; 313 len = offset >> 16; 314 offset &= 0xffff; 315 if (tep_field_is_relative(field->flags)) 316 offset += field->offset + field->size; 317 } 318 if (field->flags & TEP_FIELD_IS_STRING && 319 is_printable_array(data + offset, len)) { 320 ret = PyUnicode_FromString((char *)data + offset); 321 } else { 322 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); 323 field->flags &= ~TEP_FIELD_IS_STRING; 324 } 325 } else { 326 val = tep_read_number(pevent, data + field->offset, 327 field->size); 328 if (field->flags & TEP_FIELD_IS_POINTER) 329 ret = PyLong_FromUnsignedLong((unsigned long) val); 330 else if (field->flags & TEP_FIELD_IS_SIGNED) 331 ret = PyLong_FromLong((long) val); 332 else 333 ret = PyLong_FromUnsignedLong((unsigned long) val); 334 } 335 336 return ret; 337 } 338 339 static PyObject* 340 get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) 341 { 342 struct evsel *evsel = pevent->evsel; 343 struct tep_event *tp_format = evsel__tp_format(evsel); 344 struct tep_format_field *field; 345 346 if (IS_ERR_OR_NULL(tp_format)) 347 return NULL; 348 349 PyObject *obj = PyObject_Str(attr_name); 350 if (obj == NULL) 351 return NULL; 352 353 const char *str = PyUnicode_AsUTF8(obj); 354 if (str == NULL) { 355 Py_DECREF(obj); 356 return NULL; 357 } 358 359 field = tep_find_any_field(tp_format, str); 360 Py_DECREF(obj); 361 return field ? tracepoint_field(pevent, field) : NULL; 362 } 363 #endif /* HAVE_LIBTRACEEVENT */ 364 365 static PyObject* 366 pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name) 367 { 368 PyObject *obj = NULL; 369 370 #ifdef HAVE_LIBTRACEEVENT 371 if (is_tracepoint(pevent)) 372 obj = get_tracepoint_field(pevent, attr_name); 373 #endif 374 375 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name); 376 } 377 378 static PyTypeObject pyrf_sample_event__type = { 379 PyVarObject_HEAD_INIT(NULL, 0) 380 .tp_name = "perf.sample_event", 381 .tp_basicsize = sizeof(struct pyrf_event), 382 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 383 .tp_doc = pyrf_sample_event__doc, 384 .tp_members = pyrf_sample_event__members, 385 .tp_repr = (reprfunc)pyrf_sample_event__repr, 386 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro, 387 }; 388 389 static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); 390 391 static PyMemberDef pyrf_context_switch_event__members[] = { 392 sample_members 393 member_def(perf_event_header, type, T_UINT, "event type"), 394 member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"), 395 member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"), 396 { .name = NULL, }, 397 }; 398 399 static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent) 400 { 401 PyObject *ret; 402 char *s; 403 404 if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }", 405 pevent->event.context_switch.next_prev_pid, 406 pevent->event.context_switch.next_prev_tid, 407 !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { 408 ret = PyErr_NoMemory(); 409 } else { 410 ret = PyUnicode_FromString(s); 411 free(s); 412 } 413 return ret; 414 } 415 416 static PyTypeObject pyrf_context_switch_event__type = { 417 PyVarObject_HEAD_INIT(NULL, 0) 418 .tp_name = "perf.context_switch_event", 419 .tp_basicsize = sizeof(struct pyrf_event), 420 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 421 .tp_doc = pyrf_context_switch_event__doc, 422 .tp_members = pyrf_context_switch_event__members, 423 .tp_repr = (reprfunc)pyrf_context_switch_event__repr, 424 }; 425 426 static int pyrf_event__setup_types(void) 427 { 428 int err; 429 pyrf_mmap_event__type.tp_new = 430 pyrf_task_event__type.tp_new = 431 pyrf_comm_event__type.tp_new = 432 pyrf_lost_event__type.tp_new = 433 pyrf_read_event__type.tp_new = 434 pyrf_sample_event__type.tp_new = 435 pyrf_context_switch_event__type.tp_new = 436 pyrf_throttle_event__type.tp_new = PyType_GenericNew; 437 438 pyrf_sample_event__type.tp_dealloc = (destructor)pyrf_sample_event__delete, 439 440 err = PyType_Ready(&pyrf_mmap_event__type); 441 if (err < 0) 442 goto out; 443 err = PyType_Ready(&pyrf_lost_event__type); 444 if (err < 0) 445 goto out; 446 err = PyType_Ready(&pyrf_task_event__type); 447 if (err < 0) 448 goto out; 449 err = PyType_Ready(&pyrf_comm_event__type); 450 if (err < 0) 451 goto out; 452 err = PyType_Ready(&pyrf_throttle_event__type); 453 if (err < 0) 454 goto out; 455 err = PyType_Ready(&pyrf_read_event__type); 456 if (err < 0) 457 goto out; 458 err = PyType_Ready(&pyrf_sample_event__type); 459 if (err < 0) 460 goto out; 461 err = PyType_Ready(&pyrf_context_switch_event__type); 462 if (err < 0) 463 goto out; 464 out: 465 return err; 466 } 467 468 static PyTypeObject *pyrf_event__type[] = { 469 [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, 470 [PERF_RECORD_LOST] = &pyrf_lost_event__type, 471 [PERF_RECORD_COMM] = &pyrf_comm_event__type, 472 [PERF_RECORD_EXIT] = &pyrf_task_event__type, 473 [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, 474 [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, 475 [PERF_RECORD_FORK] = &pyrf_task_event__type, 476 [PERF_RECORD_READ] = &pyrf_read_event__type, 477 [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, 478 [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type, 479 [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type, 480 }; 481 482 static PyObject *pyrf_event__new(const union perf_event *event) 483 { 484 struct pyrf_event *pevent; 485 PyTypeObject *ptype; 486 487 if ((event->header.type < PERF_RECORD_MMAP || 488 event->header.type > PERF_RECORD_SAMPLE) && 489 !(event->header.type == PERF_RECORD_SWITCH || 490 event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) { 491 PyErr_Format(PyExc_TypeError, "Unexpected header type %u", 492 event->header.type); 493 return NULL; 494 } 495 496 // FIXME this better be dynamic or we need to parse everything 497 // before calling perf_mmap__consume(), including tracepoint fields. 498 if (sizeof(pevent->event) < event->header.size) { 499 PyErr_Format(PyExc_TypeError, "Unexpected event size: %zd < %u", 500 sizeof(pevent->event), event->header.size); 501 return NULL; 502 } 503 504 ptype = pyrf_event__type[event->header.type]; 505 pevent = PyObject_New(struct pyrf_event, ptype); 506 if (pevent != NULL) 507 memcpy(&pevent->event, event, event->header.size); 508 return (PyObject *)pevent; 509 } 510 511 struct pyrf_cpu_map { 512 PyObject_HEAD 513 514 struct perf_cpu_map *cpus; 515 }; 516 517 static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus, 518 PyObject *args, PyObject *kwargs) 519 { 520 static char *kwlist[] = { "cpustr", NULL }; 521 char *cpustr = NULL; 522 523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", 524 kwlist, &cpustr)) 525 return -1; 526 527 pcpus->cpus = perf_cpu_map__new(cpustr); 528 if (pcpus->cpus == NULL) 529 return -1; 530 return 0; 531 } 532 533 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus) 534 { 535 perf_cpu_map__put(pcpus->cpus); 536 Py_TYPE(pcpus)->tp_free((PyObject*)pcpus); 537 } 538 539 static Py_ssize_t pyrf_cpu_map__length(PyObject *obj) 540 { 541 struct pyrf_cpu_map *pcpus = (void *)obj; 542 543 return perf_cpu_map__nr(pcpus->cpus); 544 } 545 546 static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i) 547 { 548 struct pyrf_cpu_map *pcpus = (void *)obj; 549 550 if (i >= perf_cpu_map__nr(pcpus->cpus)) { 551 PyErr_SetString(PyExc_IndexError, "Index out of range"); 552 return NULL; 553 } 554 555 return Py_BuildValue("i", perf_cpu_map__cpu(pcpus->cpus, i).cpu); 556 } 557 558 static PySequenceMethods pyrf_cpu_map__sequence_methods = { 559 .sq_length = pyrf_cpu_map__length, 560 .sq_item = pyrf_cpu_map__item, 561 }; 562 563 static const char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object."); 564 565 static PyTypeObject pyrf_cpu_map__type = { 566 PyVarObject_HEAD_INIT(NULL, 0) 567 .tp_name = "perf.cpu_map", 568 .tp_basicsize = sizeof(struct pyrf_cpu_map), 569 .tp_dealloc = (destructor)pyrf_cpu_map__delete, 570 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 571 .tp_doc = pyrf_cpu_map__doc, 572 .tp_as_sequence = &pyrf_cpu_map__sequence_methods, 573 .tp_init = (initproc)pyrf_cpu_map__init, 574 }; 575 576 static int pyrf_cpu_map__setup_types(void) 577 { 578 pyrf_cpu_map__type.tp_new = PyType_GenericNew; 579 return PyType_Ready(&pyrf_cpu_map__type); 580 } 581 582 struct pyrf_thread_map { 583 PyObject_HEAD 584 585 struct perf_thread_map *threads; 586 }; 587 588 static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 589 PyObject *args, PyObject *kwargs) 590 { 591 static char *kwlist[] = { "pid", "tid", NULL }; 592 int pid = -1, tid = -1; 593 594 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 595 kwlist, &pid, &tid)) 596 return -1; 597 598 pthreads->threads = thread_map__new(pid, tid); 599 if (pthreads->threads == NULL) 600 return -1; 601 return 0; 602 } 603 604 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads) 605 { 606 perf_thread_map__put(pthreads->threads); 607 Py_TYPE(pthreads)->tp_free((PyObject*)pthreads); 608 } 609 610 static Py_ssize_t pyrf_thread_map__length(PyObject *obj) 611 { 612 struct pyrf_thread_map *pthreads = (void *)obj; 613 614 return perf_thread_map__nr(pthreads->threads); 615 } 616 617 static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i) 618 { 619 struct pyrf_thread_map *pthreads = (void *)obj; 620 621 if (i >= perf_thread_map__nr(pthreads->threads)) { 622 PyErr_SetString(PyExc_IndexError, "Index out of range"); 623 return NULL; 624 } 625 626 return Py_BuildValue("i", perf_thread_map__pid(pthreads->threads, i)); 627 } 628 629 static PySequenceMethods pyrf_thread_map__sequence_methods = { 630 .sq_length = pyrf_thread_map__length, 631 .sq_item = pyrf_thread_map__item, 632 }; 633 634 static const char pyrf_thread_map__doc[] = PyDoc_STR("thread map object."); 635 636 static PyTypeObject pyrf_thread_map__type = { 637 PyVarObject_HEAD_INIT(NULL, 0) 638 .tp_name = "perf.thread_map", 639 .tp_basicsize = sizeof(struct pyrf_thread_map), 640 .tp_dealloc = (destructor)pyrf_thread_map__delete, 641 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 642 .tp_doc = pyrf_thread_map__doc, 643 .tp_as_sequence = &pyrf_thread_map__sequence_methods, 644 .tp_init = (initproc)pyrf_thread_map__init, 645 }; 646 647 static int pyrf_thread_map__setup_types(void) 648 { 649 pyrf_thread_map__type.tp_new = PyType_GenericNew; 650 return PyType_Ready(&pyrf_thread_map__type); 651 } 652 653 /** 654 * A python wrapper for perf_pmus that are globally owned by the pmus.c code. 655 */ 656 struct pyrf_pmu { 657 PyObject_HEAD 658 659 struct perf_pmu *pmu; 660 }; 661 662 static void pyrf_pmu__delete(struct pyrf_pmu *ppmu) 663 { 664 Py_TYPE(ppmu)->tp_free((PyObject *)ppmu); 665 } 666 667 static PyObject *pyrf_pmu__name(PyObject *self) 668 { 669 struct pyrf_pmu *ppmu = (void *)self; 670 671 return PyUnicode_FromString(ppmu->pmu->name); 672 } 673 674 static bool add_to_dict(PyObject *dict, const char *key, const char *value) 675 { 676 PyObject *pkey, *pvalue; 677 bool ret; 678 679 if (value == NULL) 680 return true; 681 682 pkey = PyUnicode_FromString(key); 683 pvalue = PyUnicode_FromString(value); 684 685 ret = pkey && pvalue && PyDict_SetItem(dict, pkey, pvalue) == 0; 686 Py_XDECREF(pkey); 687 Py_XDECREF(pvalue); 688 return ret; 689 } 690 691 static int pyrf_pmu__events_cb(void *state, struct pmu_event_info *info) 692 { 693 PyObject *py_list = state; 694 PyObject *dict = PyDict_New(); 695 696 if (!dict) 697 return -ENOMEM; 698 699 if (!add_to_dict(dict, "name", info->name) || 700 !add_to_dict(dict, "alias", info->alias) || 701 !add_to_dict(dict, "scale_unit", info->scale_unit) || 702 !add_to_dict(dict, "desc", info->desc) || 703 !add_to_dict(dict, "long_desc", info->long_desc) || 704 !add_to_dict(dict, "encoding_desc", info->encoding_desc) || 705 !add_to_dict(dict, "topic", info->topic) || 706 !add_to_dict(dict, "event_type_desc", info->event_type_desc) || 707 !add_to_dict(dict, "str", info->str) || 708 !add_to_dict(dict, "deprecated", info->deprecated ? "deprecated" : NULL) || 709 PyList_Append(py_list, dict) != 0) { 710 Py_DECREF(dict); 711 return -ENOMEM; 712 } 713 Py_DECREF(dict); 714 return 0; 715 } 716 717 static PyObject *pyrf_pmu__events(PyObject *self) 718 { 719 struct pyrf_pmu *ppmu = (void *)self; 720 PyObject *py_list = PyList_New(0); 721 int ret; 722 723 if (!py_list) 724 return NULL; 725 726 ret = perf_pmu__for_each_event(ppmu->pmu, 727 /*skip_duplicate_pmus=*/false, 728 py_list, 729 pyrf_pmu__events_cb); 730 if (ret) { 731 Py_DECREF(py_list); 732 errno = -ret; 733 PyErr_SetFromErrno(PyExc_OSError); 734 return NULL; 735 } 736 return py_list; 737 } 738 739 static PyObject *pyrf_pmu__repr(PyObject *self) 740 { 741 struct pyrf_pmu *ppmu = (void *)self; 742 743 return PyUnicode_FromFormat("pmu(%s)", ppmu->pmu->name); 744 } 745 746 static const char pyrf_pmu__doc[] = PyDoc_STR("perf Performance Monitoring Unit (PMU) object."); 747 748 static PyMethodDef pyrf_pmu__methods[] = { 749 { 750 .ml_name = "events", 751 .ml_meth = (PyCFunction)pyrf_pmu__events, 752 .ml_flags = METH_NOARGS, 753 .ml_doc = PyDoc_STR("Returns a sequence of events encoded as a dictionaries.") 754 }, 755 { 756 .ml_name = "name", 757 .ml_meth = (PyCFunction)pyrf_pmu__name, 758 .ml_flags = METH_NOARGS, 759 .ml_doc = PyDoc_STR("Name of the PMU including suffixes.") 760 }, 761 { .ml_name = NULL, } 762 }; 763 764 /** The python type for a perf.pmu. */ 765 static PyTypeObject pyrf_pmu__type = { 766 PyVarObject_HEAD_INIT(NULL, 0) 767 .tp_name = "perf.pmu", 768 .tp_basicsize = sizeof(struct pyrf_pmu), 769 .tp_dealloc = (destructor)pyrf_pmu__delete, 770 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 771 .tp_doc = pyrf_pmu__doc, 772 .tp_methods = pyrf_pmu__methods, 773 .tp_str = pyrf_pmu__name, 774 .tp_repr = pyrf_pmu__repr, 775 }; 776 777 static int pyrf_pmu__setup_types(void) 778 { 779 pyrf_pmu__type.tp_new = PyType_GenericNew; 780 return PyType_Ready(&pyrf_pmu__type); 781 } 782 783 784 /** A python iterator for pmus that has no equivalent in the C code. */ 785 struct pyrf_pmu_iterator { 786 PyObject_HEAD 787 struct perf_pmu *pmu; 788 }; 789 790 static void pyrf_pmu_iterator__dealloc(struct pyrf_pmu_iterator *self) 791 { 792 Py_TYPE(self)->tp_free((PyObject *) self); 793 } 794 795 static PyObject *pyrf_pmu_iterator__new(PyTypeObject *type, PyObject *args __maybe_unused, 796 PyObject *kwds __maybe_unused) 797 { 798 struct pyrf_pmu_iterator *itr = (void *)type->tp_alloc(type, 0); 799 800 if (itr != NULL) 801 itr->pmu = perf_pmus__scan(/*pmu=*/NULL); 802 803 return (PyObject *) itr; 804 } 805 806 static PyObject *pyrf_pmu_iterator__iter(PyObject *self) 807 { 808 Py_INCREF(self); 809 return self; 810 } 811 812 static PyObject *pyrf_pmu_iterator__iternext(PyObject *self) 813 { 814 struct pyrf_pmu_iterator *itr = (void *)self; 815 struct pyrf_pmu *ppmu; 816 817 if (itr->pmu == NULL) { 818 PyErr_SetNone(PyExc_StopIteration); 819 return NULL; 820 } 821 // Create object to return. 822 ppmu = PyObject_New(struct pyrf_pmu, &pyrf_pmu__type); 823 if (ppmu) { 824 ppmu->pmu = itr->pmu; 825 // Advance iterator. 826 itr->pmu = perf_pmus__scan(itr->pmu); 827 } 828 return (PyObject *)ppmu; 829 } 830 831 /** The python type for the PMU iterator. */ 832 static PyTypeObject pyrf_pmu_iterator__type = { 833 PyVarObject_HEAD_INIT(NULL, 0) 834 .tp_name = "pmus.iterator", 835 .tp_doc = "Iterator for the pmus string sequence.", 836 .tp_basicsize = sizeof(struct pyrf_pmu_iterator), 837 .tp_itemsize = 0, 838 .tp_flags = Py_TPFLAGS_DEFAULT, 839 .tp_new = pyrf_pmu_iterator__new, 840 .tp_dealloc = (destructor) pyrf_pmu_iterator__dealloc, 841 .tp_iter = pyrf_pmu_iterator__iter, 842 .tp_iternext = pyrf_pmu_iterator__iternext, 843 }; 844 845 static int pyrf_pmu_iterator__setup_types(void) 846 { 847 return PyType_Ready(&pyrf_pmu_iterator__type); 848 } 849 850 static PyObject *pyrf__pmus(PyObject *self, PyObject *args) 851 { 852 // Calling the class creates an instance of the iterator. 853 return PyObject_CallObject((PyObject *) &pyrf_pmu_iterator__type, /*args=*/NULL); 854 } 855 856 struct pyrf_counts_values { 857 PyObject_HEAD 858 859 struct perf_counts_values values; 860 }; 861 862 static const char pyrf_counts_values__doc[] = PyDoc_STR("perf counts values object."); 863 864 static void pyrf_counts_values__delete(struct pyrf_counts_values *pcounts_values) 865 { 866 Py_TYPE(pcounts_values)->tp_free((PyObject *)pcounts_values); 867 } 868 869 #define counts_values_member_def(member, ptype, help) \ 870 { #member, ptype, \ 871 offsetof(struct pyrf_counts_values, values.member), \ 872 0, help } 873 874 static PyMemberDef pyrf_counts_values_members[] = { 875 counts_values_member_def(val, T_ULONG, "Value of event"), 876 counts_values_member_def(ena, T_ULONG, "Time for which enabled"), 877 counts_values_member_def(run, T_ULONG, "Time for which running"), 878 counts_values_member_def(id, T_ULONG, "Unique ID for an event"), 879 counts_values_member_def(lost, T_ULONG, "Num of lost samples"), 880 { .name = NULL, }, 881 }; 882 883 static PyObject *pyrf_counts_values_get_values(struct pyrf_counts_values *self, void *closure) 884 { 885 PyObject *vals = PyList_New(5); 886 887 if (!vals) 888 return NULL; 889 for (int i = 0; i < 5; i++) 890 PyList_SetItem(vals, i, PyLong_FromLong(self->values.values[i])); 891 892 return vals; 893 } 894 895 static int pyrf_counts_values_set_values(struct pyrf_counts_values *self, PyObject *list, 896 void *closure) 897 { 898 Py_ssize_t size; 899 PyObject *item = NULL; 900 901 if (!PyList_Check(list)) { 902 PyErr_SetString(PyExc_TypeError, "Value assigned must be a list"); 903 return -1; 904 } 905 906 size = PyList_Size(list); 907 for (Py_ssize_t i = 0; i < size; i++) { 908 item = PyList_GetItem(list, i); 909 if (!PyLong_Check(item)) { 910 PyErr_SetString(PyExc_TypeError, "List members should be numbers"); 911 return -1; 912 } 913 self->values.values[i] = PyLong_AsLong(item); 914 } 915 916 return 0; 917 } 918 919 static PyGetSetDef pyrf_counts_values_getset[] = { 920 {"values", (getter)pyrf_counts_values_get_values, (setter)pyrf_counts_values_set_values, 921 "Name field", NULL}, 922 { .name = NULL, }, 923 }; 924 925 static PyTypeObject pyrf_counts_values__type = { 926 PyVarObject_HEAD_INIT(NULL, 0) 927 .tp_name = "perf.counts_values", 928 .tp_basicsize = sizeof(struct pyrf_counts_values), 929 .tp_dealloc = (destructor)pyrf_counts_values__delete, 930 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 931 .tp_doc = pyrf_counts_values__doc, 932 .tp_members = pyrf_counts_values_members, 933 .tp_getset = pyrf_counts_values_getset, 934 }; 935 936 static int pyrf_counts_values__setup_types(void) 937 { 938 pyrf_counts_values__type.tp_new = PyType_GenericNew; 939 return PyType_Ready(&pyrf_counts_values__type); 940 } 941 942 struct pyrf_evsel { 943 PyObject_HEAD 944 945 struct evsel evsel; 946 }; 947 948 static int pyrf_evsel__init(struct pyrf_evsel *pevsel, 949 PyObject *args, PyObject *kwargs) 950 { 951 struct perf_event_attr attr = { 952 .type = PERF_TYPE_HARDWARE, 953 .config = PERF_COUNT_HW_CPU_CYCLES, 954 .sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID, 955 }; 956 static char *kwlist[] = { 957 "type", 958 "config", 959 "sample_freq", 960 "sample_period", 961 "sample_type", 962 "read_format", 963 "disabled", 964 "inherit", 965 "pinned", 966 "exclusive", 967 "exclude_user", 968 "exclude_kernel", 969 "exclude_hv", 970 "exclude_idle", 971 "mmap", 972 "context_switch", 973 "comm", 974 "freq", 975 "inherit_stat", 976 "enable_on_exec", 977 "task", 978 "watermark", 979 "precise_ip", 980 "mmap_data", 981 "sample_id_all", 982 "wakeup_events", 983 "bp_type", 984 "bp_addr", 985 "bp_len", 986 NULL 987 }; 988 u64 sample_period = 0; 989 u32 disabled = 0, 990 inherit = 0, 991 pinned = 0, 992 exclusive = 0, 993 exclude_user = 0, 994 exclude_kernel = 0, 995 exclude_hv = 0, 996 exclude_idle = 0, 997 mmap = 0, 998 context_switch = 0, 999 comm = 0, 1000 freq = 1, 1001 inherit_stat = 0, 1002 enable_on_exec = 0, 1003 task = 0, 1004 watermark = 0, 1005 precise_ip = 0, 1006 mmap_data = 0, 1007 sample_id_all = 1; 1008 int idx = 0; 1009 1010 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 1011 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist, 1012 &attr.type, &attr.config, &attr.sample_freq, 1013 &sample_period, &attr.sample_type, 1014 &attr.read_format, &disabled, &inherit, 1015 &pinned, &exclusive, &exclude_user, 1016 &exclude_kernel, &exclude_hv, &exclude_idle, 1017 &mmap, &context_switch, &comm, &freq, &inherit_stat, 1018 &enable_on_exec, &task, &watermark, 1019 &precise_ip, &mmap_data, &sample_id_all, 1020 &attr.wakeup_events, &attr.bp_type, 1021 &attr.bp_addr, &attr.bp_len, &idx)) 1022 return -1; 1023 1024 /* union... */ 1025 if (sample_period != 0) { 1026 if (attr.sample_freq != 0) 1027 return -1; /* FIXME: throw right exception */ 1028 attr.sample_period = sample_period; 1029 } 1030 1031 /* Bitfields */ 1032 attr.disabled = disabled; 1033 attr.inherit = inherit; 1034 attr.pinned = pinned; 1035 attr.exclusive = exclusive; 1036 attr.exclude_user = exclude_user; 1037 attr.exclude_kernel = exclude_kernel; 1038 attr.exclude_hv = exclude_hv; 1039 attr.exclude_idle = exclude_idle; 1040 attr.mmap = mmap; 1041 attr.context_switch = context_switch; 1042 attr.comm = comm; 1043 attr.freq = freq; 1044 attr.inherit_stat = inherit_stat; 1045 attr.enable_on_exec = enable_on_exec; 1046 attr.task = task; 1047 attr.watermark = watermark; 1048 attr.precise_ip = precise_ip; 1049 attr.mmap_data = mmap_data; 1050 attr.sample_id_all = sample_id_all; 1051 attr.size = sizeof(attr); 1052 1053 evsel__init(&pevsel->evsel, &attr, idx); 1054 return 0; 1055 } 1056 1057 static void pyrf_evsel__delete(struct pyrf_evsel *pevsel) 1058 { 1059 evsel__exit(&pevsel->evsel); 1060 Py_TYPE(pevsel)->tp_free((PyObject*)pevsel); 1061 } 1062 1063 static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, 1064 PyObject *args, PyObject *kwargs) 1065 { 1066 struct evsel *evsel = &pevsel->evsel; 1067 struct perf_cpu_map *cpus = NULL; 1068 struct perf_thread_map *threads = NULL; 1069 PyObject *pcpus = NULL, *pthreads = NULL; 1070 int group = 0, inherit = 0; 1071 static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL }; 1072 1073 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, 1074 &pcpus, &pthreads, &group, &inherit)) 1075 return NULL; 1076 1077 if (pthreads != NULL) 1078 threads = ((struct pyrf_thread_map *)pthreads)->threads; 1079 1080 if (pcpus != NULL) 1081 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 1082 1083 evsel->core.attr.inherit = inherit; 1084 /* 1085 * This will group just the fds for this single evsel, to group 1086 * multiple events, use evlist.open(). 1087 */ 1088 if (evsel__open(evsel, cpus, threads) < 0) { 1089 PyErr_SetFromErrno(PyExc_OSError); 1090 return NULL; 1091 } 1092 1093 Py_INCREF(Py_None); 1094 return Py_None; 1095 } 1096 1097 static PyObject *pyrf_evsel__cpus(struct pyrf_evsel *pevsel) 1098 { 1099 struct pyrf_cpu_map *pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type); 1100 1101 if (pcpu_map) 1102 pcpu_map->cpus = perf_cpu_map__get(pevsel->evsel.core.cpus); 1103 1104 return (PyObject *)pcpu_map; 1105 } 1106 1107 static PyObject *pyrf_evsel__threads(struct pyrf_evsel *pevsel) 1108 { 1109 struct pyrf_thread_map *pthread_map = 1110 PyObject_New(struct pyrf_thread_map, &pyrf_thread_map__type); 1111 1112 if (pthread_map) 1113 pthread_map->threads = perf_thread_map__get(pevsel->evsel.core.threads); 1114 1115 return (PyObject *)pthread_map; 1116 } 1117 1118 /* 1119 * Ensure evsel's counts and prev_raw_counts are allocated, the latter 1120 * used by tool PMUs to compute the cumulative count as expected by 1121 * stat's process_counter_values. 1122 */ 1123 static int evsel__ensure_counts(struct evsel *evsel) 1124 { 1125 int nthreads, ncpus; 1126 1127 if (evsel->counts != NULL) 1128 return 0; 1129 1130 nthreads = perf_thread_map__nr(evsel->core.threads); 1131 ncpus = perf_cpu_map__nr(evsel->core.cpus); 1132 1133 evsel->counts = perf_counts__new(ncpus, nthreads); 1134 if (evsel->counts == NULL) 1135 return -ENOMEM; 1136 1137 evsel->prev_raw_counts = perf_counts__new(ncpus, nthreads); 1138 if (evsel->prev_raw_counts == NULL) 1139 return -ENOMEM; 1140 1141 return 0; 1142 } 1143 1144 static PyObject *pyrf_evsel__read(struct pyrf_evsel *pevsel, 1145 PyObject *args, PyObject *kwargs) 1146 { 1147 struct evsel *evsel = &pevsel->evsel; 1148 int cpu = 0, cpu_idx, thread = 0, thread_idx; 1149 struct perf_counts_values *old_count, *new_count; 1150 struct pyrf_counts_values *count_values = PyObject_New(struct pyrf_counts_values, 1151 &pyrf_counts_values__type); 1152 1153 if (!count_values) 1154 return NULL; 1155 1156 if (!PyArg_ParseTuple(args, "ii", &cpu, &thread)) 1157 return NULL; 1158 1159 cpu_idx = perf_cpu_map__idx(evsel->core.cpus, (struct perf_cpu){.cpu = cpu}); 1160 if (cpu_idx < 0) { 1161 PyErr_Format(PyExc_TypeError, "CPU %d is not part of evsel's CPUs", cpu); 1162 return NULL; 1163 } 1164 thread_idx = perf_thread_map__idx(evsel->core.threads, thread); 1165 if (thread_idx < 0) { 1166 PyErr_Format(PyExc_TypeError, "Thread %d is not part of evsel's threads", 1167 thread); 1168 return NULL; 1169 } 1170 1171 if (evsel__ensure_counts(evsel)) 1172 return PyErr_NoMemory(); 1173 1174 /* Set up pointers to the old and newly read counter values. */ 1175 old_count = perf_counts(evsel->prev_raw_counts, cpu_idx, thread_idx); 1176 new_count = perf_counts(evsel->counts, cpu_idx, thread_idx); 1177 /* Update the value in evsel->counts. */ 1178 evsel__read_counter(evsel, cpu_idx, thread_idx); 1179 /* Copy the value and turn it into the delta from old_count. */ 1180 count_values->values = *new_count; 1181 count_values->values.val -= old_count->val; 1182 count_values->values.ena -= old_count->ena; 1183 count_values->values.run -= old_count->run; 1184 /* Save the new count over the old_count for the next read. */ 1185 *old_count = *new_count; 1186 return (PyObject *)count_values; 1187 } 1188 1189 static PyObject *pyrf_evsel__str(PyObject *self) 1190 { 1191 struct pyrf_evsel *pevsel = (void *)self; 1192 struct evsel *evsel = &pevsel->evsel; 1193 1194 return PyUnicode_FromFormat("evsel(%s/%s/)", evsel__pmu_name(evsel), evsel__name(evsel)); 1195 } 1196 1197 static PyMethodDef pyrf_evsel__methods[] = { 1198 { 1199 .ml_name = "open", 1200 .ml_meth = (PyCFunction)pyrf_evsel__open, 1201 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1202 .ml_doc = PyDoc_STR("open the event selector file descriptor table.") 1203 }, 1204 { 1205 .ml_name = "cpus", 1206 .ml_meth = (PyCFunction)pyrf_evsel__cpus, 1207 .ml_flags = METH_NOARGS, 1208 .ml_doc = PyDoc_STR("CPUs the event is to be used with.") 1209 }, 1210 { 1211 .ml_name = "threads", 1212 .ml_meth = (PyCFunction)pyrf_evsel__threads, 1213 .ml_flags = METH_NOARGS, 1214 .ml_doc = PyDoc_STR("threads the event is to be used with.") 1215 }, 1216 { 1217 .ml_name = "read", 1218 .ml_meth = (PyCFunction)pyrf_evsel__read, 1219 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1220 .ml_doc = PyDoc_STR("read counters") 1221 }, 1222 { .ml_name = NULL, } 1223 }; 1224 1225 #define evsel_member_def(member, ptype, help) \ 1226 { #member, ptype, \ 1227 offsetof(struct pyrf_evsel, evsel.member), \ 1228 0, help } 1229 1230 #define evsel_attr_member_def(member, ptype, help) \ 1231 { #member, ptype, \ 1232 offsetof(struct pyrf_evsel, evsel.core.attr.member), \ 1233 0, help } 1234 1235 static PyMemberDef pyrf_evsel__members[] = { 1236 evsel_member_def(tracking, T_BOOL, "tracking event."), 1237 evsel_attr_member_def(type, T_UINT, "attribute type."), 1238 evsel_attr_member_def(size, T_UINT, "attribute size."), 1239 evsel_attr_member_def(config, T_ULONGLONG, "attribute config."), 1240 evsel_attr_member_def(sample_period, T_ULONGLONG, "attribute sample_period."), 1241 evsel_attr_member_def(sample_type, T_ULONGLONG, "attribute sample_type."), 1242 evsel_attr_member_def(read_format, T_ULONGLONG, "attribute read_format."), 1243 evsel_attr_member_def(wakeup_events, T_UINT, "attribute wakeup_events."), 1244 { .name = NULL, }, 1245 }; 1246 1247 static const char pyrf_evsel__doc[] = PyDoc_STR("perf event selector list object."); 1248 1249 static PyTypeObject pyrf_evsel__type = { 1250 PyVarObject_HEAD_INIT(NULL, 0) 1251 .tp_name = "perf.evsel", 1252 .tp_basicsize = sizeof(struct pyrf_evsel), 1253 .tp_dealloc = (destructor)pyrf_evsel__delete, 1254 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1255 .tp_doc = pyrf_evsel__doc, 1256 .tp_members = pyrf_evsel__members, 1257 .tp_methods = pyrf_evsel__methods, 1258 .tp_init = (initproc)pyrf_evsel__init, 1259 .tp_str = pyrf_evsel__str, 1260 .tp_repr = pyrf_evsel__str, 1261 }; 1262 1263 static int pyrf_evsel__setup_types(void) 1264 { 1265 pyrf_evsel__type.tp_new = PyType_GenericNew; 1266 return PyType_Ready(&pyrf_evsel__type); 1267 } 1268 1269 struct pyrf_evlist { 1270 PyObject_HEAD 1271 1272 struct evlist evlist; 1273 }; 1274 1275 static int pyrf_evlist__init(struct pyrf_evlist *pevlist, 1276 PyObject *args, PyObject *kwargs __maybe_unused) 1277 { 1278 PyObject *pcpus = NULL, *pthreads = NULL; 1279 struct perf_cpu_map *cpus; 1280 struct perf_thread_map *threads; 1281 1282 if (!PyArg_ParseTuple(args, "OO", &pcpus, &pthreads)) 1283 return -1; 1284 1285 threads = ((struct pyrf_thread_map *)pthreads)->threads; 1286 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 1287 evlist__init(&pevlist->evlist, cpus, threads); 1288 return 0; 1289 } 1290 1291 static void pyrf_evlist__delete(struct pyrf_evlist *pevlist) 1292 { 1293 evlist__exit(&pevlist->evlist); 1294 Py_TYPE(pevlist)->tp_free((PyObject*)pevlist); 1295 } 1296 1297 static PyObject *pyrf_evlist__all_cpus(struct pyrf_evlist *pevlist) 1298 { 1299 struct pyrf_cpu_map *pcpu_map = PyObject_New(struct pyrf_cpu_map, &pyrf_cpu_map__type); 1300 1301 if (pcpu_map) 1302 pcpu_map->cpus = perf_cpu_map__get(pevlist->evlist.core.all_cpus); 1303 1304 return (PyObject *)pcpu_map; 1305 } 1306 1307 static PyObject *pyrf_evlist__metrics(struct pyrf_evlist *pevlist) 1308 { 1309 PyObject *list = PyList_New(/*len=*/0); 1310 struct rb_node *node; 1311 1312 if (!list) 1313 return NULL; 1314 1315 for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node; 1316 node = rb_next(node)) { 1317 struct metric_event *me = container_of(node, struct metric_event, nd); 1318 struct list_head *pos; 1319 1320 list_for_each(pos, &me->head) { 1321 struct metric_expr *expr = container_of(pos, struct metric_expr, nd); 1322 PyObject *str = PyUnicode_FromString(expr->metric_name); 1323 1324 if (!str || PyList_Append(list, str) != 0) { 1325 Py_DECREF(list); 1326 return NULL; 1327 } 1328 Py_DECREF(str); 1329 } 1330 } 1331 return list; 1332 } 1333 1334 static int prepare_metric(const struct metric_expr *mexp, 1335 const struct evsel *evsel, 1336 struct expr_parse_ctx *pctx, 1337 int cpu_idx, int thread_idx) 1338 { 1339 struct evsel * const *metric_events = mexp->metric_events; 1340 struct metric_ref *metric_refs = mexp->metric_refs; 1341 1342 for (int i = 0; metric_events[i]; i++) { 1343 char *n = strdup(evsel__metric_id(metric_events[i])); 1344 double val, ena, run; 1345 int source_count = evsel__source_count(metric_events[i]); 1346 int ret; 1347 struct perf_counts_values *old_count, *new_count; 1348 1349 if (!n) 1350 return -ENOMEM; 1351 1352 if (source_count == 0) 1353 source_count = 1; 1354 1355 ret = evsel__ensure_counts(metric_events[i]); 1356 if (ret) 1357 return ret; 1358 1359 /* Set up pointers to the old and newly read counter values. */ 1360 old_count = perf_counts(metric_events[i]->prev_raw_counts, cpu_idx, thread_idx); 1361 new_count = perf_counts(metric_events[i]->counts, cpu_idx, thread_idx); 1362 /* Update the value in metric_events[i]->counts. */ 1363 evsel__read_counter(metric_events[i], cpu_idx, thread_idx); 1364 1365 val = new_count->val - old_count->val; 1366 ena = new_count->ena - old_count->ena; 1367 run = new_count->run - old_count->run; 1368 1369 if (ena != run && run != 0) 1370 val = val * ena / run; 1371 ret = expr__add_id_val_source_count(pctx, n, val, source_count); 1372 if (ret) 1373 return ret; 1374 } 1375 1376 for (int i = 0; metric_refs && metric_refs[i].metric_name; i++) { 1377 int ret = expr__add_ref(pctx, &metric_refs[i]); 1378 1379 if (ret) 1380 return ret; 1381 } 1382 1383 return 0; 1384 } 1385 1386 static PyObject *pyrf_evlist__compute_metric(struct pyrf_evlist *pevlist, 1387 PyObject *args, PyObject *kwargs) 1388 { 1389 int ret, cpu = 0, cpu_idx = 0, thread = 0, thread_idx = 0; 1390 const char *metric; 1391 struct rb_node *node; 1392 struct metric_expr *mexp = NULL; 1393 struct expr_parse_ctx *pctx; 1394 double result = 0; 1395 1396 if (!PyArg_ParseTuple(args, "sii", &metric, &cpu, &thread)) 1397 return NULL; 1398 1399 for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); 1400 mexp == NULL && node; 1401 node = rb_next(node)) { 1402 struct metric_event *me = container_of(node, struct metric_event, nd); 1403 struct list_head *pos; 1404 1405 list_for_each(pos, &me->head) { 1406 struct metric_expr *e = container_of(pos, struct metric_expr, nd); 1407 1408 if (strcmp(e->metric_name, metric)) 1409 continue; 1410 1411 if (e->metric_events[0] == NULL) 1412 continue; 1413 1414 cpu_idx = perf_cpu_map__idx(e->metric_events[0]->core.cpus, 1415 (struct perf_cpu){.cpu = cpu}); 1416 if (cpu_idx < 0) 1417 continue; 1418 1419 thread_idx = perf_thread_map__idx(e->metric_events[0]->core.threads, 1420 thread); 1421 if (thread_idx < 0) 1422 continue; 1423 1424 mexp = e; 1425 break; 1426 } 1427 } 1428 if (!mexp) { 1429 PyErr_Format(PyExc_TypeError, "Unknown metric '%s' for CPU '%d' and thread '%d'", 1430 metric, cpu, thread); 1431 return NULL; 1432 } 1433 1434 pctx = expr__ctx_new(); 1435 if (!pctx) 1436 return PyErr_NoMemory(); 1437 1438 ret = prepare_metric(mexp, mexp->metric_events[0], pctx, cpu_idx, thread_idx); 1439 if (ret) { 1440 expr__ctx_free(pctx); 1441 errno = -ret; 1442 PyErr_SetFromErrno(PyExc_OSError); 1443 return NULL; 1444 } 1445 if (expr__parse(&result, pctx, mexp->metric_expr)) 1446 result = 0.0; 1447 1448 expr__ctx_free(pctx); 1449 return PyFloat_FromDouble(result); 1450 } 1451 1452 static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist, 1453 PyObject *args, PyObject *kwargs) 1454 { 1455 struct evlist *evlist = &pevlist->evlist; 1456 static char *kwlist[] = { "pages", "overwrite", NULL }; 1457 int pages = 128, overwrite = false; 1458 1459 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist, 1460 &pages, &overwrite)) 1461 return NULL; 1462 1463 if (evlist__mmap(evlist, pages) < 0) { 1464 PyErr_SetFromErrno(PyExc_OSError); 1465 return NULL; 1466 } 1467 1468 Py_INCREF(Py_None); 1469 return Py_None; 1470 } 1471 1472 static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist, 1473 PyObject *args, PyObject *kwargs) 1474 { 1475 struct evlist *evlist = &pevlist->evlist; 1476 static char *kwlist[] = { "timeout", NULL }; 1477 int timeout = -1, n; 1478 1479 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout)) 1480 return NULL; 1481 1482 n = evlist__poll(evlist, timeout); 1483 if (n < 0) { 1484 PyErr_SetFromErrno(PyExc_OSError); 1485 return NULL; 1486 } 1487 1488 return Py_BuildValue("i", n); 1489 } 1490 1491 static PyObject *pyrf_evlist__get_pollfd(struct pyrf_evlist *pevlist, 1492 PyObject *args __maybe_unused, 1493 PyObject *kwargs __maybe_unused) 1494 { 1495 struct evlist *evlist = &pevlist->evlist; 1496 PyObject *list = PyList_New(0); 1497 int i; 1498 1499 for (i = 0; i < evlist->core.pollfd.nr; ++i) { 1500 PyObject *file; 1501 file = PyFile_FromFd(evlist->core.pollfd.entries[i].fd, "perf", "r", -1, 1502 NULL, NULL, NULL, 0); 1503 if (file == NULL) 1504 goto free_list; 1505 1506 if (PyList_Append(list, file) != 0) { 1507 Py_DECREF(file); 1508 goto free_list; 1509 } 1510 1511 Py_DECREF(file); 1512 } 1513 1514 return list; 1515 free_list: 1516 return PyErr_NoMemory(); 1517 } 1518 1519 1520 static PyObject *pyrf_evlist__add(struct pyrf_evlist *pevlist, 1521 PyObject *args, 1522 PyObject *kwargs __maybe_unused) 1523 { 1524 struct evlist *evlist = &pevlist->evlist; 1525 PyObject *pevsel; 1526 struct evsel *evsel; 1527 1528 if (!PyArg_ParseTuple(args, "O", &pevsel)) 1529 return NULL; 1530 1531 Py_INCREF(pevsel); 1532 evsel = &((struct pyrf_evsel *)pevsel)->evsel; 1533 evsel->core.idx = evlist->core.nr_entries; 1534 evlist__add(evlist, evsel); 1535 1536 return Py_BuildValue("i", evlist->core.nr_entries); 1537 } 1538 1539 static struct mmap *get_md(struct evlist *evlist, int cpu) 1540 { 1541 int i; 1542 1543 for (i = 0; i < evlist->core.nr_mmaps; i++) { 1544 struct mmap *md = &evlist->mmap[i]; 1545 1546 if (md->core.cpu.cpu == cpu) 1547 return md; 1548 } 1549 1550 return NULL; 1551 } 1552 1553 static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist, 1554 PyObject *args, PyObject *kwargs) 1555 { 1556 struct evlist *evlist = &pevlist->evlist; 1557 union perf_event *event; 1558 int sample_id_all = 1, cpu; 1559 static char *kwlist[] = { "cpu", "sample_id_all", NULL }; 1560 struct mmap *md; 1561 int err; 1562 1563 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist, 1564 &cpu, &sample_id_all)) 1565 return NULL; 1566 1567 md = get_md(evlist, cpu); 1568 if (!md) { 1569 PyErr_Format(PyExc_TypeError, "Unknown CPU '%d'", cpu); 1570 return NULL; 1571 } 1572 1573 if (perf_mmap__read_init(&md->core) < 0) 1574 goto end; 1575 1576 event = perf_mmap__read_event(&md->core); 1577 if (event != NULL) { 1578 PyObject *pyevent = pyrf_event__new(event); 1579 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 1580 struct evsel *evsel; 1581 1582 if (pyevent == NULL) 1583 return PyErr_NoMemory(); 1584 1585 evsel = evlist__event2evsel(evlist, event); 1586 if (!evsel) { 1587 Py_DECREF(pyevent); 1588 Py_INCREF(Py_None); 1589 return Py_None; 1590 } 1591 1592 pevent->evsel = evsel; 1593 1594 perf_mmap__consume(&md->core); 1595 1596 err = evsel__parse_sample(evsel, &pevent->event, &pevent->sample); 1597 if (err) { 1598 Py_DECREF(pyevent); 1599 return PyErr_Format(PyExc_OSError, 1600 "perf: can't parse sample, err=%d", err); 1601 } 1602 1603 return pyevent; 1604 } 1605 end: 1606 Py_INCREF(Py_None); 1607 return Py_None; 1608 } 1609 1610 static PyObject *pyrf_evlist__open(struct pyrf_evlist *pevlist, 1611 PyObject *args, PyObject *kwargs) 1612 { 1613 struct evlist *evlist = &pevlist->evlist; 1614 1615 if (evlist__open(evlist) < 0) { 1616 PyErr_SetFromErrno(PyExc_OSError); 1617 return NULL; 1618 } 1619 1620 Py_INCREF(Py_None); 1621 return Py_None; 1622 } 1623 1624 static PyObject *pyrf_evlist__close(struct pyrf_evlist *pevlist) 1625 { 1626 struct evlist *evlist = &pevlist->evlist; 1627 1628 evlist__close(evlist); 1629 1630 Py_INCREF(Py_None); 1631 return Py_None; 1632 } 1633 1634 static PyObject *pyrf_evlist__config(struct pyrf_evlist *pevlist) 1635 { 1636 struct record_opts opts = { 1637 .sample_time = true, 1638 .mmap_pages = UINT_MAX, 1639 .user_freq = UINT_MAX, 1640 .user_interval = ULLONG_MAX, 1641 .freq = 4000, 1642 .target = { 1643 .uses_mmap = true, 1644 .default_per_cpu = true, 1645 }, 1646 .nr_threads_synthesize = 1, 1647 .ctl_fd = -1, 1648 .ctl_fd_ack = -1, 1649 .no_buffering = true, 1650 .no_inherit = true, 1651 }; 1652 struct evlist *evlist = &pevlist->evlist; 1653 1654 evlist__config(evlist, &opts, &callchain_param); 1655 Py_INCREF(Py_None); 1656 return Py_None; 1657 } 1658 1659 static PyObject *pyrf_evlist__disable(struct pyrf_evlist *pevlist) 1660 { 1661 evlist__disable(&pevlist->evlist); 1662 Py_INCREF(Py_None); 1663 return Py_None; 1664 } 1665 1666 static PyObject *pyrf_evlist__enable(struct pyrf_evlist *pevlist) 1667 { 1668 evlist__enable(&pevlist->evlist); 1669 Py_INCREF(Py_None); 1670 return Py_None; 1671 } 1672 1673 static PyMethodDef pyrf_evlist__methods[] = { 1674 { 1675 .ml_name = "all_cpus", 1676 .ml_meth = (PyCFunction)pyrf_evlist__all_cpus, 1677 .ml_flags = METH_NOARGS, 1678 .ml_doc = PyDoc_STR("CPU map union of all evsel CPU maps.") 1679 }, 1680 { 1681 .ml_name = "metrics", 1682 .ml_meth = (PyCFunction)pyrf_evlist__metrics, 1683 .ml_flags = METH_NOARGS, 1684 .ml_doc = PyDoc_STR("List of metric names within the evlist.") 1685 }, 1686 { 1687 .ml_name = "compute_metric", 1688 .ml_meth = (PyCFunction)pyrf_evlist__compute_metric, 1689 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1690 .ml_doc = PyDoc_STR("compute metric for given name, cpu and thread") 1691 }, 1692 { 1693 .ml_name = "mmap", 1694 .ml_meth = (PyCFunction)pyrf_evlist__mmap, 1695 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1696 .ml_doc = PyDoc_STR("mmap the file descriptor table.") 1697 }, 1698 { 1699 .ml_name = "open", 1700 .ml_meth = (PyCFunction)pyrf_evlist__open, 1701 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1702 .ml_doc = PyDoc_STR("open the file descriptors.") 1703 }, 1704 { 1705 .ml_name = "close", 1706 .ml_meth = (PyCFunction)pyrf_evlist__close, 1707 .ml_flags = METH_NOARGS, 1708 .ml_doc = PyDoc_STR("close the file descriptors.") 1709 }, 1710 { 1711 .ml_name = "poll", 1712 .ml_meth = (PyCFunction)pyrf_evlist__poll, 1713 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1714 .ml_doc = PyDoc_STR("poll the file descriptor table.") 1715 }, 1716 { 1717 .ml_name = "get_pollfd", 1718 .ml_meth = (PyCFunction)pyrf_evlist__get_pollfd, 1719 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1720 .ml_doc = PyDoc_STR("get the poll file descriptor table.") 1721 }, 1722 { 1723 .ml_name = "add", 1724 .ml_meth = (PyCFunction)pyrf_evlist__add, 1725 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1726 .ml_doc = PyDoc_STR("adds an event selector to the list.") 1727 }, 1728 { 1729 .ml_name = "read_on_cpu", 1730 .ml_meth = (PyCFunction)pyrf_evlist__read_on_cpu, 1731 .ml_flags = METH_VARARGS | METH_KEYWORDS, 1732 .ml_doc = PyDoc_STR("reads an event.") 1733 }, 1734 { 1735 .ml_name = "config", 1736 .ml_meth = (PyCFunction)pyrf_evlist__config, 1737 .ml_flags = METH_NOARGS, 1738 .ml_doc = PyDoc_STR("Apply default record options to the evlist.") 1739 }, 1740 { 1741 .ml_name = "disable", 1742 .ml_meth = (PyCFunction)pyrf_evlist__disable, 1743 .ml_flags = METH_NOARGS, 1744 .ml_doc = PyDoc_STR("Disable the evsels in the evlist.") 1745 }, 1746 { 1747 .ml_name = "enable", 1748 .ml_meth = (PyCFunction)pyrf_evlist__enable, 1749 .ml_flags = METH_NOARGS, 1750 .ml_doc = PyDoc_STR("Enable the evsels in the evlist.") 1751 }, 1752 { .ml_name = NULL, } 1753 }; 1754 1755 static Py_ssize_t pyrf_evlist__length(PyObject *obj) 1756 { 1757 struct pyrf_evlist *pevlist = (void *)obj; 1758 1759 return pevlist->evlist.core.nr_entries; 1760 } 1761 1762 static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i) 1763 { 1764 struct pyrf_evlist *pevlist = (void *)obj; 1765 struct evsel *pos; 1766 1767 if (i >= pevlist->evlist.core.nr_entries) { 1768 PyErr_SetString(PyExc_IndexError, "Index out of range"); 1769 return NULL; 1770 } 1771 1772 evlist__for_each_entry(&pevlist->evlist, pos) { 1773 if (i-- == 0) 1774 break; 1775 } 1776 1777 return Py_BuildValue("O", container_of(pos, struct pyrf_evsel, evsel)); 1778 } 1779 1780 static PyObject *pyrf_evlist__str(PyObject *self) 1781 { 1782 struct pyrf_evlist *pevlist = (void *)self; 1783 struct evsel *pos; 1784 struct strbuf sb = STRBUF_INIT; 1785 bool first = true; 1786 PyObject *result; 1787 1788 strbuf_addstr(&sb, "evlist(["); 1789 evlist__for_each_entry(&pevlist->evlist, pos) { 1790 if (!first) 1791 strbuf_addch(&sb, ','); 1792 if (!pos->pmu) 1793 strbuf_addstr(&sb, evsel__name(pos)); 1794 else 1795 strbuf_addf(&sb, "%s/%s/", pos->pmu->name, evsel__name(pos)); 1796 first = false; 1797 } 1798 strbuf_addstr(&sb, "])"); 1799 result = PyUnicode_FromString(sb.buf); 1800 strbuf_release(&sb); 1801 return result; 1802 } 1803 1804 static PySequenceMethods pyrf_evlist__sequence_methods = { 1805 .sq_length = pyrf_evlist__length, 1806 .sq_item = pyrf_evlist__item, 1807 }; 1808 1809 static const char pyrf_evlist__doc[] = PyDoc_STR("perf event selector list object."); 1810 1811 static PyTypeObject pyrf_evlist__type = { 1812 PyVarObject_HEAD_INIT(NULL, 0) 1813 .tp_name = "perf.evlist", 1814 .tp_basicsize = sizeof(struct pyrf_evlist), 1815 .tp_dealloc = (destructor)pyrf_evlist__delete, 1816 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1817 .tp_as_sequence = &pyrf_evlist__sequence_methods, 1818 .tp_doc = pyrf_evlist__doc, 1819 .tp_methods = pyrf_evlist__methods, 1820 .tp_init = (initproc)pyrf_evlist__init, 1821 .tp_repr = pyrf_evlist__str, 1822 .tp_str = pyrf_evlist__str, 1823 }; 1824 1825 static int pyrf_evlist__setup_types(void) 1826 { 1827 pyrf_evlist__type.tp_new = PyType_GenericNew; 1828 return PyType_Ready(&pyrf_evlist__type); 1829 } 1830 1831 #define PERF_CONST(name) { #name, PERF_##name } 1832 1833 struct perf_constant { 1834 const char *name; 1835 int value; 1836 }; 1837 1838 static const struct perf_constant perf__constants[] = { 1839 PERF_CONST(TYPE_HARDWARE), 1840 PERF_CONST(TYPE_SOFTWARE), 1841 PERF_CONST(TYPE_TRACEPOINT), 1842 PERF_CONST(TYPE_HW_CACHE), 1843 PERF_CONST(TYPE_RAW), 1844 PERF_CONST(TYPE_BREAKPOINT), 1845 1846 PERF_CONST(COUNT_HW_CPU_CYCLES), 1847 PERF_CONST(COUNT_HW_INSTRUCTIONS), 1848 PERF_CONST(COUNT_HW_CACHE_REFERENCES), 1849 PERF_CONST(COUNT_HW_CACHE_MISSES), 1850 PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS), 1851 PERF_CONST(COUNT_HW_BRANCH_MISSES), 1852 PERF_CONST(COUNT_HW_BUS_CYCLES), 1853 PERF_CONST(COUNT_HW_CACHE_L1D), 1854 PERF_CONST(COUNT_HW_CACHE_L1I), 1855 PERF_CONST(COUNT_HW_CACHE_LL), 1856 PERF_CONST(COUNT_HW_CACHE_DTLB), 1857 PERF_CONST(COUNT_HW_CACHE_ITLB), 1858 PERF_CONST(COUNT_HW_CACHE_BPU), 1859 PERF_CONST(COUNT_HW_CACHE_OP_READ), 1860 PERF_CONST(COUNT_HW_CACHE_OP_WRITE), 1861 PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH), 1862 PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS), 1863 PERF_CONST(COUNT_HW_CACHE_RESULT_MISS), 1864 1865 PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND), 1866 PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND), 1867 1868 PERF_CONST(COUNT_SW_CPU_CLOCK), 1869 PERF_CONST(COUNT_SW_TASK_CLOCK), 1870 PERF_CONST(COUNT_SW_PAGE_FAULTS), 1871 PERF_CONST(COUNT_SW_CONTEXT_SWITCHES), 1872 PERF_CONST(COUNT_SW_CPU_MIGRATIONS), 1873 PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN), 1874 PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ), 1875 PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS), 1876 PERF_CONST(COUNT_SW_EMULATION_FAULTS), 1877 PERF_CONST(COUNT_SW_DUMMY), 1878 1879 PERF_CONST(SAMPLE_IP), 1880 PERF_CONST(SAMPLE_TID), 1881 PERF_CONST(SAMPLE_TIME), 1882 PERF_CONST(SAMPLE_ADDR), 1883 PERF_CONST(SAMPLE_READ), 1884 PERF_CONST(SAMPLE_CALLCHAIN), 1885 PERF_CONST(SAMPLE_ID), 1886 PERF_CONST(SAMPLE_CPU), 1887 PERF_CONST(SAMPLE_PERIOD), 1888 PERF_CONST(SAMPLE_STREAM_ID), 1889 PERF_CONST(SAMPLE_RAW), 1890 1891 PERF_CONST(FORMAT_TOTAL_TIME_ENABLED), 1892 PERF_CONST(FORMAT_TOTAL_TIME_RUNNING), 1893 PERF_CONST(FORMAT_ID), 1894 PERF_CONST(FORMAT_GROUP), 1895 1896 PERF_CONST(RECORD_MMAP), 1897 PERF_CONST(RECORD_LOST), 1898 PERF_CONST(RECORD_COMM), 1899 PERF_CONST(RECORD_EXIT), 1900 PERF_CONST(RECORD_THROTTLE), 1901 PERF_CONST(RECORD_UNTHROTTLE), 1902 PERF_CONST(RECORD_FORK), 1903 PERF_CONST(RECORD_READ), 1904 PERF_CONST(RECORD_SAMPLE), 1905 PERF_CONST(RECORD_MMAP2), 1906 PERF_CONST(RECORD_AUX), 1907 PERF_CONST(RECORD_ITRACE_START), 1908 PERF_CONST(RECORD_LOST_SAMPLES), 1909 PERF_CONST(RECORD_SWITCH), 1910 PERF_CONST(RECORD_SWITCH_CPU_WIDE), 1911 1912 PERF_CONST(RECORD_MISC_SWITCH_OUT), 1913 { .name = NULL, }, 1914 }; 1915 1916 static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel, 1917 PyObject *args, PyObject *kwargs) 1918 { 1919 static char *kwlist[] = { "sys", "name", NULL }; 1920 char *sys = NULL; 1921 char *name = NULL; 1922 1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist, 1924 &sys, &name)) 1925 return NULL; 1926 1927 return PyLong_FromLong(tp_pmu__id(sys, name)); 1928 } 1929 1930 static PyObject *pyrf_evsel__from_evsel(struct evsel *evsel) 1931 { 1932 struct pyrf_evsel *pevsel = PyObject_New(struct pyrf_evsel, &pyrf_evsel__type); 1933 1934 if (!pevsel) 1935 return NULL; 1936 1937 memset(&pevsel->evsel, 0, sizeof(pevsel->evsel)); 1938 evsel__init(&pevsel->evsel, &evsel->core.attr, evsel->core.idx); 1939 1940 evsel__clone(&pevsel->evsel, evsel); 1941 if (evsel__is_group_leader(evsel)) 1942 evsel__set_leader(&pevsel->evsel, &pevsel->evsel); 1943 return (PyObject *)pevsel; 1944 } 1945 1946 static int evlist__pos(struct evlist *evlist, struct evsel *evsel) 1947 { 1948 struct evsel *pos; 1949 int idx = 0; 1950 1951 evlist__for_each_entry(evlist, pos) { 1952 if (evsel == pos) 1953 return idx; 1954 idx++; 1955 } 1956 return -1; 1957 } 1958 1959 static struct evsel *evlist__at(struct evlist *evlist, int idx) 1960 { 1961 struct evsel *pos; 1962 int idx2 = 0; 1963 1964 evlist__for_each_entry(evlist, pos) { 1965 if (idx == idx2) 1966 return pos; 1967 idx2++; 1968 } 1969 return NULL; 1970 } 1971 1972 static PyObject *pyrf_evlist__from_evlist(struct evlist *evlist) 1973 { 1974 struct pyrf_evlist *pevlist = PyObject_New(struct pyrf_evlist, &pyrf_evlist__type); 1975 struct evsel *pos; 1976 struct rb_node *node; 1977 1978 if (!pevlist) 1979 return NULL; 1980 1981 memset(&pevlist->evlist, 0, sizeof(pevlist->evlist)); 1982 evlist__init(&pevlist->evlist, evlist->core.all_cpus, evlist->core.threads); 1983 evlist__for_each_entry(evlist, pos) { 1984 struct pyrf_evsel *pevsel = (void *)pyrf_evsel__from_evsel(pos); 1985 1986 evlist__add(&pevlist->evlist, &pevsel->evsel); 1987 } 1988 evlist__for_each_entry(&pevlist->evlist, pos) { 1989 struct evsel *leader = evsel__leader(pos); 1990 1991 if (pos != leader) { 1992 int idx = evlist__pos(evlist, leader); 1993 1994 if (idx >= 0) 1995 evsel__set_leader(pos, evlist__at(&pevlist->evlist, idx)); 1996 else if (leader == NULL) 1997 evsel__set_leader(pos, pos); 1998 } 1999 } 2000 metricgroup__copy_metric_events(&pevlist->evlist, /*cgrp=*/NULL, 2001 &pevlist->evlist.metric_events, 2002 &evlist->metric_events); 2003 for (node = rb_first_cached(&pevlist->evlist.metric_events.entries); node; 2004 node = rb_next(node)) { 2005 struct metric_event *me = container_of(node, struct metric_event, nd); 2006 struct list_head *mpos; 2007 int idx = evlist__pos(evlist, me->evsel); 2008 2009 if (idx >= 0) 2010 me->evsel = evlist__at(&pevlist->evlist, idx); 2011 list_for_each(mpos, &me->head) { 2012 struct metric_expr *e = container_of(mpos, struct metric_expr, nd); 2013 2014 for (int j = 0; e->metric_events[j]; j++) { 2015 idx = evlist__pos(evlist, e->metric_events[j]); 2016 if (idx >= 0) 2017 e->metric_events[j] = evlist__at(&pevlist->evlist, idx); 2018 } 2019 } 2020 } 2021 return (PyObject *)pevlist; 2022 } 2023 2024 static PyObject *pyrf__parse_events(PyObject *self, PyObject *args) 2025 { 2026 const char *input; 2027 struct evlist evlist = {}; 2028 struct parse_events_error err; 2029 PyObject *result; 2030 PyObject *pcpus = NULL, *pthreads = NULL; 2031 struct perf_cpu_map *cpus; 2032 struct perf_thread_map *threads; 2033 2034 if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) 2035 return NULL; 2036 2037 threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL; 2038 cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; 2039 2040 parse_events_error__init(&err); 2041 evlist__init(&evlist, cpus, threads); 2042 if (parse_events(&evlist, input, &err)) { 2043 parse_events_error__print(&err, input); 2044 PyErr_SetFromErrno(PyExc_OSError); 2045 return NULL; 2046 } 2047 result = pyrf_evlist__from_evlist(&evlist); 2048 evlist__exit(&evlist); 2049 return result; 2050 } 2051 2052 static PyObject *pyrf__parse_metrics(PyObject *self, PyObject *args) 2053 { 2054 const char *input; 2055 struct evlist evlist = {}; 2056 PyObject *result; 2057 PyObject *pcpus = NULL, *pthreads = NULL; 2058 struct perf_cpu_map *cpus; 2059 struct perf_thread_map *threads; 2060 int ret; 2061 2062 if (!PyArg_ParseTuple(args, "s|OO", &input, &pcpus, &pthreads)) 2063 return NULL; 2064 2065 threads = pthreads ? ((struct pyrf_thread_map *)pthreads)->threads : NULL; 2066 cpus = pcpus ? ((struct pyrf_cpu_map *)pcpus)->cpus : NULL; 2067 2068 evlist__init(&evlist, cpus, threads); 2069 ret = metricgroup__parse_groups(&evlist, /*pmu=*/"all", input, 2070 /*metric_no_group=*/ false, 2071 /*metric_no_merge=*/ false, 2072 /*metric_no_threshold=*/ true, 2073 /*user_requested_cpu_list=*/ NULL, 2074 /*system_wide=*/true, 2075 /*hardware_aware_grouping=*/ false); 2076 if (ret) { 2077 errno = -ret; 2078 PyErr_SetFromErrno(PyExc_OSError); 2079 return NULL; 2080 } 2081 result = pyrf_evlist__from_evlist(&evlist); 2082 evlist__exit(&evlist); 2083 return result; 2084 } 2085 2086 static PyObject *pyrf__metrics_groups(const struct pmu_metric *pm) 2087 { 2088 PyObject *groups = PyList_New(/*len=*/0); 2089 const char *mg = pm->metric_group; 2090 2091 if (!groups) 2092 return NULL; 2093 2094 while (mg) { 2095 PyObject *val = NULL; 2096 const char *sep = strchr(mg, ';'); 2097 size_t len = sep ? (size_t)(sep - mg) : strlen(mg); 2098 2099 if (len > 0) { 2100 val = PyUnicode_FromStringAndSize(mg, len); 2101 if (val) 2102 PyList_Append(groups, val); 2103 2104 Py_XDECREF(val); 2105 } 2106 mg = sep ? sep + 1 : NULL; 2107 } 2108 return groups; 2109 } 2110 2111 static int pyrf__metrics_cb(const struct pmu_metric *pm, 2112 const struct pmu_metrics_table *table __maybe_unused, 2113 void *vdata) 2114 { 2115 PyObject *py_list = vdata; 2116 PyObject *dict = PyDict_New(); 2117 PyObject *key = dict ? PyUnicode_FromString("MetricGroup") : NULL; 2118 PyObject *value = key ? pyrf__metrics_groups(pm) : NULL; 2119 2120 if (!value || PyDict_SetItem(dict, key, value) != 0) { 2121 Py_XDECREF(key); 2122 Py_XDECREF(value); 2123 Py_XDECREF(dict); 2124 return -ENOMEM; 2125 } 2126 2127 if (!add_to_dict(dict, "MetricName", pm->metric_name) || 2128 !add_to_dict(dict, "PMU", pm->pmu) || 2129 !add_to_dict(dict, "MetricExpr", pm->metric_expr) || 2130 !add_to_dict(dict, "MetricThreshold", pm->metric_threshold) || 2131 !add_to_dict(dict, "ScaleUnit", pm->unit) || 2132 !add_to_dict(dict, "Compat", pm->compat) || 2133 !add_to_dict(dict, "BriefDescription", pm->desc) || 2134 !add_to_dict(dict, "PublicDescription", pm->long_desc) || 2135 PyList_Append(py_list, dict) != 0) { 2136 Py_DECREF(dict); 2137 return -ENOMEM; 2138 } 2139 Py_DECREF(dict); 2140 return 0; 2141 } 2142 2143 static PyObject *pyrf__metrics(PyObject *self, PyObject *args) 2144 { 2145 const struct pmu_metrics_table *table = pmu_metrics_table__find(); 2146 PyObject *list = PyList_New(/*len=*/0); 2147 int ret; 2148 2149 if (!list) 2150 return NULL; 2151 2152 ret = pmu_metrics_table__for_each_metric(table, pyrf__metrics_cb, list); 2153 if (!ret) 2154 ret = pmu_for_each_sys_metric(pyrf__metrics_cb, list); 2155 2156 if (ret) { 2157 Py_DECREF(list); 2158 errno = -ret; 2159 PyErr_SetFromErrno(PyExc_OSError); 2160 return NULL; 2161 } 2162 return list; 2163 } 2164 2165 static PyMethodDef perf__methods[] = { 2166 { 2167 .ml_name = "metrics", 2168 .ml_meth = (PyCFunction) pyrf__metrics, 2169 .ml_flags = METH_NOARGS, 2170 .ml_doc = PyDoc_STR( 2171 "Returns a list of metrics represented as string values in dictionaries.") 2172 }, 2173 { 2174 .ml_name = "tracepoint", 2175 .ml_meth = (PyCFunction) pyrf__tracepoint, 2176 .ml_flags = METH_VARARGS | METH_KEYWORDS, 2177 .ml_doc = PyDoc_STR("Get tracepoint config.") 2178 }, 2179 { 2180 .ml_name = "parse_events", 2181 .ml_meth = (PyCFunction) pyrf__parse_events, 2182 .ml_flags = METH_VARARGS, 2183 .ml_doc = PyDoc_STR("Parse a string of events and return an evlist.") 2184 }, 2185 { 2186 .ml_name = "parse_metrics", 2187 .ml_meth = (PyCFunction) pyrf__parse_metrics, 2188 .ml_flags = METH_VARARGS, 2189 .ml_doc = PyDoc_STR( 2190 "Parse a string of metrics or metric groups and return an evlist.") 2191 }, 2192 { 2193 .ml_name = "pmus", 2194 .ml_meth = (PyCFunction) pyrf__pmus, 2195 .ml_flags = METH_NOARGS, 2196 .ml_doc = PyDoc_STR("Returns a sequence of pmus.") 2197 }, 2198 { .ml_name = NULL, } 2199 }; 2200 2201 PyMODINIT_FUNC PyInit_perf(void) 2202 { 2203 PyObject *obj; 2204 int i; 2205 PyObject *dict; 2206 static struct PyModuleDef moduledef = { 2207 PyModuleDef_HEAD_INIT, 2208 "perf", /* m_name */ 2209 "", /* m_doc */ 2210 -1, /* m_size */ 2211 perf__methods, /* m_methods */ 2212 NULL, /* m_reload */ 2213 NULL, /* m_traverse */ 2214 NULL, /* m_clear */ 2215 NULL, /* m_free */ 2216 }; 2217 PyObject *module = PyModule_Create(&moduledef); 2218 2219 if (module == NULL || 2220 pyrf_event__setup_types() < 0 || 2221 pyrf_evlist__setup_types() < 0 || 2222 pyrf_evsel__setup_types() < 0 || 2223 pyrf_thread_map__setup_types() < 0 || 2224 pyrf_cpu_map__setup_types() < 0 || 2225 pyrf_pmu_iterator__setup_types() < 0 || 2226 pyrf_pmu__setup_types() < 0 || 2227 pyrf_counts_values__setup_types() < 0) 2228 return module; 2229 2230 /* The page_size is placed in util object. */ 2231 page_size = sysconf(_SC_PAGE_SIZE); 2232 2233 Py_INCREF(&pyrf_evlist__type); 2234 PyModule_AddObject(module, "evlist", (PyObject*)&pyrf_evlist__type); 2235 2236 Py_INCREF(&pyrf_evsel__type); 2237 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); 2238 2239 Py_INCREF(&pyrf_mmap_event__type); 2240 PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type); 2241 2242 Py_INCREF(&pyrf_lost_event__type); 2243 PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type); 2244 2245 Py_INCREF(&pyrf_comm_event__type); 2246 PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type); 2247 2248 Py_INCREF(&pyrf_task_event__type); 2249 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); 2250 2251 Py_INCREF(&pyrf_throttle_event__type); 2252 PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type); 2253 2254 Py_INCREF(&pyrf_task_event__type); 2255 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type); 2256 2257 Py_INCREF(&pyrf_read_event__type); 2258 PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type); 2259 2260 Py_INCREF(&pyrf_sample_event__type); 2261 PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type); 2262 2263 Py_INCREF(&pyrf_context_switch_event__type); 2264 PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type); 2265 2266 Py_INCREF(&pyrf_thread_map__type); 2267 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); 2268 2269 Py_INCREF(&pyrf_cpu_map__type); 2270 PyModule_AddObject(module, "cpu_map", (PyObject*)&pyrf_cpu_map__type); 2271 2272 Py_INCREF(&pyrf_counts_values__type); 2273 PyModule_AddObject(module, "counts_values", (PyObject *)&pyrf_counts_values__type); 2274 2275 dict = PyModule_GetDict(module); 2276 if (dict == NULL) 2277 goto error; 2278 2279 for (i = 0; perf__constants[i].name != NULL; i++) { 2280 obj = PyLong_FromLong(perf__constants[i].value); 2281 if (obj == NULL) 2282 goto error; 2283 PyDict_SetItemString(dict, perf__constants[i].name, obj); 2284 Py_DECREF(obj); 2285 } 2286 2287 error: 2288 if (PyErr_Occurred()) 2289 PyErr_SetString(PyExc_ImportError, "perf: Init failed!"); 2290 return module; 2291 } 2292