// SPDX-License-Identifier: GPL-2.0#include <Python.h>#include <structmember.h>#include <inttypes.h>#include <poll.h>#include <linux/err.h>#include "evlist.h"#include "callchain.h"#include "evsel.h"#include "event.h"#include "cpumap.h"#include "print_binary.h"#include "thread_map.h" /* * Provide these two so that we don't have to link against callchain.c and * start dragging hist.c, etc. */struct callchain_param callchain_param; int parse_callchain_record(const char *arg __maybe_unused, struct callchain_param *param __maybe_unused){ return 0;} /* * Support debug printing even though util/debug.c is not linked. That means * implementing 'verbose' and 'eprintf'. */int verbose; int eprintf(int level, int var, const char *fmt, ...){ va_list args; int ret = 0; if (var >= level) { va_start(args, fmt); ret = vfprintf(stderr, fmt, args); va_end(args); } return ret;} /* Define PyVarObject_HEAD_INIT for python 2.5 */#ifndef PyVarObject_HEAD_INIT# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,#endif PyMODINIT_FUNC initperf(void); #define member_def(type, member, ptype, help) \ { #member, ptype, \ offsetof(struct pyrf_event, event) + offsetof(struct type, member), \ 0, help } #define sample_member_def(name, member, ptype, help) \ { #name, ptype, \ offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \ 0, help } struct pyrf_event { PyObject_HEAD struct perf_evsel *evsel; struct perf_sample sample; union perf_event event;}; #define sample_members \ sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \ sample_member_def(sample_pid, pid, T_INT, "event pid"), \ sample_member_def(sample_tid, tid, T_INT, "event tid"), \ sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \ sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \ sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \ sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \ sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); static PyMemberDef pyrf_mmap_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(perf_event_header, misc, T_UINT, "event misc"), member_def(mmap_event, pid, T_UINT, "event pid"), member_def(mmap_event, tid, T_UINT, "event tid"), member_def(mmap_event, start, T_ULONGLONG, "start of the map"), member_def(mmap_event, len, T_ULONGLONG, "map length"), member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"), member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"), { .name = NULL, },}; static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent){ PyObject *ret; char *s; if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", " "length: %#" PRIx64 ", offset: %#" PRIx64 ", " "filename: %s }", pevent->event.mmap.pid, pevent->event.mmap.tid, pevent->event.mmap.start, pevent->event.mmap.len, pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret;} static PyTypeObject pyrf_mmap_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.mmap_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_mmap_event__doc, .tp_members = pyrf_mmap_event__members, .tp_repr = (reprfunc)pyrf_mmap_event__repr,}; static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); static PyMemberDef pyrf_task_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(fork_event, pid, T_UINT, "event pid"), member_def(fork_event, ppid, T_UINT, "event ppid"), member_def(fork_event, tid, T_UINT, "event tid"), member_def(fork_event, ptid, T_UINT, "event ptid"), member_def(fork_event, time, T_ULONGLONG, "timestamp"), { .name = NULL, },}; static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent){ return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " "ptid: %u, time: %" PRIu64 "}", pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", pevent->event.fork.pid, pevent->event.fork.ppid, pevent->event.fork.tid, pevent->event.fork.ptid, pevent->event.fork.time);} static PyTypeObject pyrf_task_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.task_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_task_event__doc, .tp_members = pyrf_task_event__members, .tp_repr = (reprfunc)pyrf_task_event__repr,}; static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); static PyMemberDef pyrf_comm_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(comm_event, pid, T_UINT, "event pid"), member_def(comm_event, tid, T_UINT, "event tid"), member_def(comm_event, comm, T_STRING_INPLACE, "process name"), { .name = NULL, },}; static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent){ return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", pevent->event.comm.pid, pevent->event.comm.tid, pevent->event.comm.comm);} static PyTypeObject pyrf_comm_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.comm_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_comm_event__doc, .tp_members = pyrf_comm_event__members, .tp_repr = (reprfunc)pyrf_comm_event__repr,}; static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); static PyMemberDef pyrf_throttle_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(throttle_event, time, T_ULONGLONG, "timestamp"), member_def(throttle_event, id, T_ULONGLONG, "event id"), member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"), { .name = NULL, },}; static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent){ struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 ", stream_id: %" PRIu64 " }", pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", te->time, te->id, te->stream_id);} static PyTypeObject pyrf_throttle_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.throttle_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_throttle_event__doc, .tp_members = pyrf_throttle_event__members, .tp_repr = (reprfunc)pyrf_throttle_event__repr,}; static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); static PyMemberDef pyrf_lost_event__members[] = { sample_members member_def(lost_event, id, T_ULONGLONG, "event id"), member_def(lost_event, lost, T_ULONGLONG, "number of lost events"), { .name = NULL, },}; static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent){ PyObject *ret; char *s; if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", " "lost: %#" PRIx64 " }", pevent->event.lost.id, pevent->event.lost.lost) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret;} static PyTypeObject pyrf_lost_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.lost_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_lost_event__doc, .tp_members = pyrf_lost_event__members, .tp_repr = (reprfunc)pyrf_lost_event__repr,}; static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object."); static PyMemberDef pyrf_read_event__members[] = { sample_members member_def(read_event, pid, T_UINT, "event pid"), member_def(read_event, tid, T_UINT, "event tid"), { .name = NULL, },}; static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent){ return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", pevent->event.read.pid, pevent->event.read.tid); /* * FIXME: return the array of read values, * making this method useful ;-) */} static PyTypeObject pyrf_read_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.read_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_read_event__doc, .tp_members = pyrf_read_event__members, .tp_repr = (reprfunc)pyrf_read_event__repr,}; static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object."); static PyMemberDef pyrf_sample_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), { .name = NULL, },}; static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent){ PyObject *ret; char *s; if (asprintf(&s, "{ type: sample }") < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret;} static bool is_tracepoint(struct pyrf_event *pevent){ return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT;} static PyObject*tracepoint_field(struct pyrf_event *pe, struct format_field *field){ struct pevent *pevent = field->event->pevent; void *data = pe->sample.raw_data; PyObject *ret = NULL; unsigned long long val; unsigned int offset, len; if (field->flags & FIELD_IS_ARRAY) { offset = field->offset; len = field->size; if (field->flags & FIELD_IS_DYNAMIC) { val = pevent_read_number(pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } if (field->flags & FIELD_IS_STRING && is_printable_array(data + offset, len)) { ret = PyString_FromString((char *)data + offset); } else { ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); field->flags &= ~FIELD_IS_STRING; } } else { val = pevent_read_number(pevent, data + field->offset, field->size); if (field->flags & FIELD_IS_POINTER) ret = PyLong_FromUnsignedLong((unsigned long) val); else if (field->flags & FIELD_IS_SIGNED) ret = PyLong_FromLong((long) val); else ret = PyLong_FromUnsignedLong((unsigned long) val); } return ret;} static PyObject*get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name){ const char *str = PyString_AsString(PyObject_Str(attr_name)); struct perf_evsel *evsel = pevent->evsel; struct format_field *field; if (!evsel->tp_format) { struct event_format *tp_format; tp_format = trace_event__tp_format_id(evsel->attr.config); if (!tp_format) return NULL; evsel->tp_format = tp_format; } field = pevent_find_any_field(evsel->tp_format, str); if (!field) return NULL; return tracepoint_field(pevent, field);} static PyObject*pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name){ PyObject *obj = NULL; if (is_tracepoint(pevent)) obj = get_tracepoint_field(pevent, attr_name); return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);} static PyTypeObject pyrf_sample_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.sample_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_sample_event__doc, .tp_members = pyrf_sample_event__members, .tp_repr = (reprfunc)pyrf_sample_event__repr, .tp_getattro = (getattrofunc) pyrf_sample_event__getattro,}; static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); static PyMemberDef pyrf_context_switch_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"), member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"), { .name = NULL, },}; static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent){ PyObject *ret; char *s; if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }", pevent->event.context_switch.next_prev_pid, pevent->event.context_switch.next_prev_tid, !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret;} static PyTypeObject pyrf_context_switch_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.context_switch_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_context_switch_event__doc, .tp_members = pyrf_context_switch_event__members, .tp_repr = (reprfunc)pyrf_context_switch_event__repr,}; static int pyrf_event__setup_types(void){ int err; pyrf_mmap_event__type.tp_new = pyrf_task_event__type.tp_new = pyrf_comm_event__type.tp_new = pyrf_lost_event__type.tp_new = pyrf_read_event__type.tp_new = pyrf_sample_event__type.tp_new = pyrf_context_switch_event__type.tp_new = pyrf_throttle_event__type.tp_new = PyType_GenericNew; err = PyType_Ready(&pyrf_mmap_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_lost_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_task_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_comm_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_throttle_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_read_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_sample_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_context_switch_event__type); if (err < 0) goto out;out: return err;} static PyTypeObject *pyrf_event__type[] = { [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, [PERF_RECORD_LOST] = &pyrf_lost_event__type, [PERF_RECORD_COMM] = &pyrf_comm_event__type, [PERF_RECORD_EXIT] = &pyrf_task_event__type, [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, [PERF_RECORD_FORK] = &pyrf_task_event__type, [PERF_RECORD_READ] = &pyrf_read_event__type, [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type, [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type,}; static PyObject *pyrf_event__new(union perf_event *event){ struct pyrf_event *pevent; PyTypeObject *ptype; if ((event->header.type < PERF_RECORD_MMAP || event->header.type > PERF_RECORD_SAMPLE) && !(event->header.type == PERF_RECORD_SWITCH || event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) return NULL; ptype = pyrf_event__type[event->header.type]; pevent = PyObject_New(struct pyrf_event, ptype);Lines 1–500 of 1292. Load more
// SPDX-License-Identifier: GPL-2.0 #include <Python.h> #include <structmember.h> #include <inttypes.h> #include <poll.h> #include <linux/err.h> #include "evlist.h" #include "callchain.h" #include "evsel.h" #include "event.h" #include "cpumap.h" #include "print_binary.h" #include "thread_map.h" /* * Provide these two so that we don't have to link against callchain.c and * start dragging hist.c, etc. */ struct callchain_param callchain_param; int parse_callchain_record(const char *arg __maybe_unused, struct callchain_param *param __maybe_unused) { return 0; } /* * Support debug printing even though util/debug.c is not linked. That means * implementing 'verbose' and 'eprintf'. */ int verbose; int eprintf(int level, int var, const char *fmt, ...) { va_list args; int ret = 0; if (var >= level) { va_start(args, fmt); ret = vfprintf(stderr, fmt, args); va_end(args); } return ret; } /* Define PyVarObject_HEAD_INIT for python 2.5 */ #ifndef PyVarObject_HEAD_INIT # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, #endif PyMODINIT_FUNC initperf(void); #define member_def(type, member, ptype, help) \ { #member, ptype, \ offsetof(struct pyrf_event, event) + offsetof(struct type, member), \ 0, help } #define sample_member_def(name, member, ptype, help) \ { #name, ptype, \ offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \ 0, help } struct pyrf_event { PyObject_HEAD struct perf_evsel *evsel; struct perf_sample sample; union perf_event event; }; #define sample_members \ sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \ sample_member_def(sample_pid, pid, T_INT, "event pid"), \ sample_member_def(sample_tid, tid, T_INT, "event tid"), \ sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \ sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \ sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \ sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \ sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \ sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"), static char pyrf_mmap_event__doc[] = PyDoc_STR("perf mmap event object."); static PyMemberDef pyrf_mmap_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(perf_event_header, misc, T_UINT, "event misc"), member_def(mmap_event, pid, T_UINT, "event pid"), member_def(mmap_event, tid, T_UINT, "event tid"), member_def(mmap_event, start, T_ULONGLONG, "start of the map"), member_def(mmap_event, len, T_ULONGLONG, "map length"), member_def(mmap_event, pgoff, T_ULONGLONG, "page offset"), member_def(mmap_event, filename, T_STRING_INPLACE, "backing store"), { .name = NULL, }, }; static PyObject *pyrf_mmap_event__repr(struct pyrf_event *pevent) { PyObject *ret; char *s; if (asprintf(&s, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64 ", " "length: %#" PRIx64 ", offset: %#" PRIx64 ", " "filename: %s }", pevent->event.mmap.pid, pevent->event.mmap.tid, pevent->event.mmap.start, pevent->event.mmap.len, pevent->event.mmap.pgoff, pevent->event.mmap.filename) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret; } static PyTypeObject pyrf_mmap_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.mmap_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_mmap_event__doc, .tp_members = pyrf_mmap_event__members, .tp_repr = (reprfunc)pyrf_mmap_event__repr, }; static char pyrf_task_event__doc[] = PyDoc_STR("perf task (fork/exit) event object."); static PyMemberDef pyrf_task_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(fork_event, pid, T_UINT, "event pid"), member_def(fork_event, ppid, T_UINT, "event ppid"), member_def(fork_event, tid, T_UINT, "event tid"), member_def(fork_event, ptid, T_UINT, "event ptid"), member_def(fork_event, time, T_ULONGLONG, "timestamp"), { .name = NULL, }, }; static PyObject *pyrf_task_event__repr(struct pyrf_event *pevent) { return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, " "ptid: %u, time: %" PRIu64 "}", pevent->event.header.type == PERF_RECORD_FORK ? "fork" : "exit", pevent->event.fork.pid, pevent->event.fork.ppid, pevent->event.fork.tid, pevent->event.fork.ptid, pevent->event.fork.time); } static PyTypeObject pyrf_task_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.task_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_task_event__doc, .tp_members = pyrf_task_event__members, .tp_repr = (reprfunc)pyrf_task_event__repr, }; static char pyrf_comm_event__doc[] = PyDoc_STR("perf comm event object."); static PyMemberDef pyrf_comm_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(comm_event, pid, T_UINT, "event pid"), member_def(comm_event, tid, T_UINT, "event tid"), member_def(comm_event, comm, T_STRING_INPLACE, "process name"), { .name = NULL, }, }; static PyObject *pyrf_comm_event__repr(struct pyrf_event *pevent) { return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }", pevent->event.comm.pid, pevent->event.comm.tid, pevent->event.comm.comm); } static PyTypeObject pyrf_comm_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.comm_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_comm_event__doc, .tp_members = pyrf_comm_event__members, .tp_repr = (reprfunc)pyrf_comm_event__repr, }; static char pyrf_throttle_event__doc[] = PyDoc_STR("perf throttle event object."); static PyMemberDef pyrf_throttle_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(throttle_event, time, T_ULONGLONG, "timestamp"), member_def(throttle_event, id, T_ULONGLONG, "event id"), member_def(throttle_event, stream_id, T_ULONGLONG, "event stream id"), { .name = NULL, }, }; static PyObject *pyrf_throttle_event__repr(struct pyrf_event *pevent) { struct throttle_event *te = (struct throttle_event *)(&pevent->event.header + 1); return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64 ", id: %" PRIu64 ", stream_id: %" PRIu64 " }", pevent->event.header.type == PERF_RECORD_THROTTLE ? "" : "un", te->time, te->id, te->stream_id); } static PyTypeObject pyrf_throttle_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.throttle_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_throttle_event__doc, .tp_members = pyrf_throttle_event__members, .tp_repr = (reprfunc)pyrf_throttle_event__repr, }; static char pyrf_lost_event__doc[] = PyDoc_STR("perf lost event object."); static PyMemberDef pyrf_lost_event__members[] = { sample_members member_def(lost_event, id, T_ULONGLONG, "event id"), member_def(lost_event, lost, T_ULONGLONG, "number of lost events"), { .name = NULL, }, }; static PyObject *pyrf_lost_event__repr(struct pyrf_event *pevent) { PyObject *ret; char *s; if (asprintf(&s, "{ type: lost, id: %#" PRIx64 ", " "lost: %#" PRIx64 " }", pevent->event.lost.id, pevent->event.lost.lost) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret; } static PyTypeObject pyrf_lost_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.lost_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_lost_event__doc, .tp_members = pyrf_lost_event__members, .tp_repr = (reprfunc)pyrf_lost_event__repr, }; static char pyrf_read_event__doc[] = PyDoc_STR("perf read event object."); static PyMemberDef pyrf_read_event__members[] = { sample_members member_def(read_event, pid, T_UINT, "event pid"), member_def(read_event, tid, T_UINT, "event tid"), { .name = NULL, }, }; static PyObject *pyrf_read_event__repr(struct pyrf_event *pevent) { return PyString_FromFormat("{ type: read, pid: %u, tid: %u }", pevent->event.read.pid, pevent->event.read.tid); /* * FIXME: return the array of read values, * making this method useful ;-) */ } static PyTypeObject pyrf_read_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.read_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_read_event__doc, .tp_members = pyrf_read_event__members, .tp_repr = (reprfunc)pyrf_read_event__repr, }; static char pyrf_sample_event__doc[] = PyDoc_STR("perf sample event object."); static PyMemberDef pyrf_sample_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), { .name = NULL, }, }; static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent) { PyObject *ret; char *s; if (asprintf(&s, "{ type: sample }") < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret; } static bool is_tracepoint(struct pyrf_event *pevent) { return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT; } static PyObject* tracepoint_field(struct pyrf_event *pe, struct format_field *field) { struct pevent *pevent = field->event->pevent; void *data = pe->sample.raw_data; PyObject *ret = NULL; unsigned long long val; unsigned int offset, len; if (field->flags & FIELD_IS_ARRAY) { offset = field->offset; len = field->size; if (field->flags & FIELD_IS_DYNAMIC) { val = pevent_read_number(pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } if (field->flags & FIELD_IS_STRING && is_printable_array(data + offset, len)) { ret = PyString_FromString((char *)data + offset); } else { ret = PyByteArray_FromStringAndSize((const char *) data + offset, len); field->flags &= ~FIELD_IS_STRING; } } else { val = pevent_read_number(pevent, data + field->offset, field->size); if (field->flags & FIELD_IS_POINTER) ret = PyLong_FromUnsignedLong((unsigned long) val); else if (field->flags & FIELD_IS_SIGNED) ret = PyLong_FromLong((long) val); else ret = PyLong_FromUnsignedLong((unsigned long) val); } return ret; } static PyObject* get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name) { const char *str = PyString_AsString(PyObject_Str(attr_name)); struct perf_evsel *evsel = pevent->evsel; struct format_field *field; if (!evsel->tp_format) { struct event_format *tp_format; tp_format = trace_event__tp_format_id(evsel->attr.config); if (!tp_format) return NULL; evsel->tp_format = tp_format; } field = pevent_find_any_field(evsel->tp_format, str); if (!field) return NULL; return tracepoint_field(pevent, field); } static PyObject* pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name) { PyObject *obj = NULL; if (is_tracepoint(pevent)) obj = get_tracepoint_field(pevent, attr_name); return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name); } static PyTypeObject pyrf_sample_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.sample_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_sample_event__doc, .tp_members = pyrf_sample_event__members, .tp_repr = (reprfunc)pyrf_sample_event__repr, .tp_getattro = (getattrofunc) pyrf_sample_event__getattro, }; static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); static PyMemberDef pyrf_context_switch_event__members[] = { sample_members member_def(perf_event_header, type, T_UINT, "event type"), member_def(context_switch_event, next_prev_pid, T_UINT, "next/prev pid"), member_def(context_switch_event, next_prev_tid, T_UINT, "next/prev tid"), { .name = NULL, }, }; static PyObject *pyrf_context_switch_event__repr(struct pyrf_event *pevent) { PyObject *ret; char *s; if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }", pevent->event.context_switch.next_prev_pid, pevent->event.context_switch.next_prev_tid, !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) { ret = PyErr_NoMemory(); } else { ret = PyString_FromString(s); free(s); } return ret; } static PyTypeObject pyrf_context_switch_event__type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "perf.context_switch_event", .tp_basicsize = sizeof(struct pyrf_event), .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, .tp_doc = pyrf_context_switch_event__doc, .tp_members = pyrf_context_switch_event__members, .tp_repr = (reprfunc)pyrf_context_switch_event__repr, }; static int pyrf_event__setup_types(void) { int err; pyrf_mmap_event__type.tp_new = pyrf_task_event__type.tp_new = pyrf_comm_event__type.tp_new = pyrf_lost_event__type.tp_new = pyrf_read_event__type.tp_new = pyrf_sample_event__type.tp_new = pyrf_context_switch_event__type.tp_new = pyrf_throttle_event__type.tp_new = PyType_GenericNew; err = PyType_Ready(&pyrf_mmap_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_lost_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_task_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_comm_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_throttle_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_read_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_sample_event__type); if (err < 0) goto out; err = PyType_Ready(&pyrf_context_switch_event__type); if (err < 0) goto out; out: return err; } static PyTypeObject *pyrf_event__type[] = { [PERF_RECORD_MMAP] = &pyrf_mmap_event__type, [PERF_RECORD_LOST] = &pyrf_lost_event__type, [PERF_RECORD_COMM] = &pyrf_comm_event__type, [PERF_RECORD_EXIT] = &pyrf_task_event__type, [PERF_RECORD_THROTTLE] = &pyrf_throttle_event__type, [PERF_RECORD_UNTHROTTLE] = &pyrf_throttle_event__type, [PERF_RECORD_FORK] = &pyrf_task_event__type, [PERF_RECORD_READ] = &pyrf_read_event__type, [PERF_RECORD_SAMPLE] = &pyrf_sample_event__type, [PERF_RECORD_SWITCH] = &pyrf_context_switch_event__type, [PERF_RECORD_SWITCH_CPU_WIDE] = &pyrf_context_switch_event__type, }; static PyObject *pyrf_event__new(union perf_event *event) { struct pyrf_event *pevent; PyTypeObject *ptype; if ((event->header.type < PERF_RECORD_MMAP || event->header.type > PERF_RECORD_SAMPLE) && !(event->header.type == PERF_RECORD_SWITCH || event->header.type == PERF_RECORD_SWITCH_CPU_WIDE)) return NULL; ptype = pyrf_event__type[event->header.type]; pevent = PyObject_New(struct pyrf_event, ptype);