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