1 // SPDX-License-Identifier: GPL-2.0
3 #include <structmember.h>
12 #include "print_binary.h"
13 #include "thread_map.h"
15 #if PY_MAJOR_VERSION < 3
16 #define _PyUnicode_FromString(arg) \
17 PyString_FromString(arg)
18 #define _PyUnicode_AsString(arg) \
19 PyString_AsString(arg)
20 #define _PyUnicode_FromFormat(...) \
21 PyString_FromFormat(__VA_ARGS__)
22 #define _PyLong_FromLong(arg) \
27 #define _PyUnicode_FromString(arg) \
28 PyUnicode_FromString(arg)
29 #define _PyUnicode_FromFormat(...) \
30 PyUnicode_FromFormat(__VA_ARGS__)
31 #define _PyLong_FromLong(arg) \
36 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
40 * Provide these two so that we don't have to link against callchain.c and
41 * start dragging hist.c, etc.
43 struct callchain_param callchain_param
;
45 int parse_callchain_record(const char *arg __maybe_unused
,
46 struct callchain_param
*param __maybe_unused
)
52 * Support debug printing even though util/debug.c is not linked. That means
53 * implementing 'verbose' and 'eprintf'.
57 int eprintf(int level
, int var
, const char *fmt
, ...)
64 ret
= vfprintf(stderr
, fmt
, args
);
71 /* Define PyVarObject_HEAD_INIT for python 2.5 */
72 #ifndef PyVarObject_HEAD_INIT
73 # define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
76 #if PY_MAJOR_VERSION < 3
77 PyMODINIT_FUNC
initperf(void);
79 PyMODINIT_FUNC
PyInit_perf(void);
82 #define member_def(type, member, ptype, help) \
84 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
87 #define sample_member_def(name, member, ptype, help) \
89 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
94 struct perf_evsel
*evsel
;
95 struct perf_sample sample
;
96 union perf_event event
;
99 #define sample_members \
100 sample_member_def(sample_ip, ip, T_ULONGLONG, "event type"), \
101 sample_member_def(sample_pid, pid, T_INT, "event pid"), \
102 sample_member_def(sample_tid, tid, T_INT, "event tid"), \
103 sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
104 sample_member_def(sample_addr, addr, T_ULONGLONG, "event addr"), \
105 sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
106 sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
107 sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
108 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
110 static char pyrf_mmap_event__doc
[] = PyDoc_STR("perf mmap event object.");
112 static PyMemberDef pyrf_mmap_event__members
[] = {
114 member_def(perf_event_header
, type
, T_UINT
, "event type"),
115 member_def(perf_event_header
, misc
, T_UINT
, "event misc"),
116 member_def(mmap_event
, pid
, T_UINT
, "event pid"),
117 member_def(mmap_event
, tid
, T_UINT
, "event tid"),
118 member_def(mmap_event
, start
, T_ULONGLONG
, "start of the map"),
119 member_def(mmap_event
, len
, T_ULONGLONG
, "map length"),
120 member_def(mmap_event
, pgoff
, T_ULONGLONG
, "page offset"),
121 member_def(mmap_event
, filename
, T_STRING_INPLACE
, "backing store"),
125 static PyObject
*pyrf_mmap_event__repr(struct pyrf_event
*pevent
)
130 if (asprintf(&s
, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64
", "
131 "length: %#" PRIx64
", offset: %#" PRIx64
", "
133 pevent
->event
.mmap
.pid
, pevent
->event
.mmap
.tid
,
134 pevent
->event
.mmap
.start
, pevent
->event
.mmap
.len
,
135 pevent
->event
.mmap
.pgoff
, pevent
->event
.mmap
.filename
) < 0) {
136 ret
= PyErr_NoMemory();
138 ret
= _PyUnicode_FromString(s
);
144 static PyTypeObject pyrf_mmap_event__type
= {
145 PyVarObject_HEAD_INIT(NULL
, 0)
146 .tp_name
= "perf.mmap_event",
147 .tp_basicsize
= sizeof(struct pyrf_event
),
148 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
149 .tp_doc
= pyrf_mmap_event__doc
,
150 .tp_members
= pyrf_mmap_event__members
,
151 .tp_repr
= (reprfunc
)pyrf_mmap_event__repr
,
154 static char pyrf_task_event__doc
[] = PyDoc_STR("perf task (fork/exit) event object.");
156 static PyMemberDef pyrf_task_event__members
[] = {
158 member_def(perf_event_header
, type
, T_UINT
, "event type"),
159 member_def(fork_event
, pid
, T_UINT
, "event pid"),
160 member_def(fork_event
, ppid
, T_UINT
, "event ppid"),
161 member_def(fork_event
, tid
, T_UINT
, "event tid"),
162 member_def(fork_event
, ptid
, T_UINT
, "event ptid"),
163 member_def(fork_event
, time
, T_ULONGLONG
, "timestamp"),
167 static PyObject
*pyrf_task_event__repr(struct pyrf_event
*pevent
)
169 return _PyUnicode_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
170 "ptid: %u, time: %" PRIu64
"}",
171 pevent
->event
.header
.type
== PERF_RECORD_FORK
? "fork" : "exit",
172 pevent
->event
.fork
.pid
,
173 pevent
->event
.fork
.ppid
,
174 pevent
->event
.fork
.tid
,
175 pevent
->event
.fork
.ptid
,
176 pevent
->event
.fork
.time
);
179 static PyTypeObject pyrf_task_event__type
= {
180 PyVarObject_HEAD_INIT(NULL
, 0)
181 .tp_name
= "perf.task_event",
182 .tp_basicsize
= sizeof(struct pyrf_event
),
183 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
184 .tp_doc
= pyrf_task_event__doc
,
185 .tp_members
= pyrf_task_event__members
,
186 .tp_repr
= (reprfunc
)pyrf_task_event__repr
,
189 static char pyrf_comm_event__doc
[] = PyDoc_STR("perf comm event object.");
191 static PyMemberDef pyrf_comm_event__members
[] = {
193 member_def(perf_event_header
, type
, T_UINT
, "event type"),
194 member_def(comm_event
, pid
, T_UINT
, "event pid"),
195 member_def(comm_event
, tid
, T_UINT
, "event tid"),
196 member_def(comm_event
, comm
, T_STRING_INPLACE
, "process name"),
200 static PyObject
*pyrf_comm_event__repr(struct pyrf_event
*pevent
)
202 return _PyUnicode_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
203 pevent
->event
.comm
.pid
,
204 pevent
->event
.comm
.tid
,
205 pevent
->event
.comm
.comm
);
208 static PyTypeObject pyrf_comm_event__type
= {
209 PyVarObject_HEAD_INIT(NULL
, 0)
210 .tp_name
= "perf.comm_event",
211 .tp_basicsize
= sizeof(struct pyrf_event
),
212 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
213 .tp_doc
= pyrf_comm_event__doc
,
214 .tp_members
= pyrf_comm_event__members
,
215 .tp_repr
= (reprfunc
)pyrf_comm_event__repr
,
218 static char pyrf_throttle_event__doc
[] = PyDoc_STR("perf throttle event object.");
220 static PyMemberDef pyrf_throttle_event__members
[] = {
222 member_def(perf_event_header
, type
, T_UINT
, "event type"),
223 member_def(throttle_event
, time
, T_ULONGLONG
, "timestamp"),
224 member_def(throttle_event
, id
, T_ULONGLONG
, "event id"),
225 member_def(throttle_event
, stream_id
, T_ULONGLONG
, "event stream id"),
229 static PyObject
*pyrf_throttle_event__repr(struct pyrf_event
*pevent
)
231 struct throttle_event
*te
= (struct throttle_event
*)(&pevent
->event
.header
+ 1);
233 return _PyUnicode_FromFormat("{ type: %sthrottle, time: %" PRIu64
", id: %" PRIu64
234 ", stream_id: %" PRIu64
" }",
235 pevent
->event
.header
.type
== PERF_RECORD_THROTTLE
? "" : "un",
236 te
->time
, te
->id
, te
->stream_id
);
239 static PyTypeObject pyrf_throttle_event__type
= {
240 PyVarObject_HEAD_INIT(NULL
, 0)
241 .tp_name
= "perf.throttle_event",
242 .tp_basicsize
= sizeof(struct pyrf_event
),
243 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
244 .tp_doc
= pyrf_throttle_event__doc
,
245 .tp_members
= pyrf_throttle_event__members
,
246 .tp_repr
= (reprfunc
)pyrf_throttle_event__repr
,
249 static char pyrf_lost_event__doc
[] = PyDoc_STR("perf lost event object.");
251 static PyMemberDef pyrf_lost_event__members
[] = {
253 member_def(lost_event
, id
, T_ULONGLONG
, "event id"),
254 member_def(lost_event
, lost
, T_ULONGLONG
, "number of lost events"),
258 static PyObject
*pyrf_lost_event__repr(struct pyrf_event
*pevent
)
263 if (asprintf(&s
, "{ type: lost, id: %#" PRIx64
", "
264 "lost: %#" PRIx64
" }",
265 pevent
->event
.lost
.id
, pevent
->event
.lost
.lost
) < 0) {
266 ret
= PyErr_NoMemory();
268 ret
= _PyUnicode_FromString(s
);
274 static PyTypeObject pyrf_lost_event__type
= {
275 PyVarObject_HEAD_INIT(NULL
, 0)
276 .tp_name
= "perf.lost_event",
277 .tp_basicsize
= sizeof(struct pyrf_event
),
278 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
279 .tp_doc
= pyrf_lost_event__doc
,
280 .tp_members
= pyrf_lost_event__members
,
281 .tp_repr
= (reprfunc
)pyrf_lost_event__repr
,
284 static char pyrf_read_event__doc
[] = PyDoc_STR("perf read event object.");
286 static PyMemberDef pyrf_read_event__members
[] = {
288 member_def(read_event
, pid
, T_UINT
, "event pid"),
289 member_def(read_event
, tid
, T_UINT
, "event tid"),
293 static PyObject
*pyrf_read_event__repr(struct pyrf_event
*pevent
)
295 return _PyUnicode_FromFormat("{ type: read, pid: %u, tid: %u }",
296 pevent
->event
.read
.pid
,
297 pevent
->event
.read
.tid
);
299 * FIXME: return the array of read values,
300 * making this method useful ;-)
304 static PyTypeObject pyrf_read_event__type
= {
305 PyVarObject_HEAD_INIT(NULL
, 0)
306 .tp_name
= "perf.read_event",
307 .tp_basicsize
= sizeof(struct pyrf_event
),
308 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
309 .tp_doc
= pyrf_read_event__doc
,
310 .tp_members
= pyrf_read_event__members
,
311 .tp_repr
= (reprfunc
)pyrf_read_event__repr
,
314 static char pyrf_sample_event__doc
[] = PyDoc_STR("perf sample event object.");
316 static PyMemberDef pyrf_sample_event__members
[] = {
318 member_def(perf_event_header
, type
, T_UINT
, "event type"),
322 static PyObject
*pyrf_sample_event__repr(struct pyrf_event
*pevent
)
327 if (asprintf(&s
, "{ type: sample }") < 0) {
328 ret
= PyErr_NoMemory();
330 ret
= _PyUnicode_FromString(s
);
336 static bool is_tracepoint(struct pyrf_event
*pevent
)
338 return pevent
->evsel
->attr
.type
== PERF_TYPE_TRACEPOINT
;
342 tracepoint_field(struct pyrf_event
*pe
, struct format_field
*field
)
344 struct pevent
*pevent
= field
->event
->pevent
;
345 void *data
= pe
->sample
.raw_data
;
346 PyObject
*ret
= NULL
;
347 unsigned long long val
;
348 unsigned int offset
, len
;
350 if (field
->flags
& FIELD_IS_ARRAY
) {
351 offset
= field
->offset
;
353 if (field
->flags
& FIELD_IS_DYNAMIC
) {
354 val
= pevent_read_number(pevent
, data
+ offset
, len
);
359 if (field
->flags
& FIELD_IS_STRING
&&
360 is_printable_array(data
+ offset
, len
)) {
361 ret
= _PyUnicode_FromString((char *)data
+ offset
);
363 ret
= PyByteArray_FromStringAndSize((const char *) data
+ offset
, len
);
364 field
->flags
&= ~FIELD_IS_STRING
;
367 val
= pevent_read_number(pevent
, data
+ field
->offset
,
369 if (field
->flags
& FIELD_IS_POINTER
)
370 ret
= PyLong_FromUnsignedLong((unsigned long) val
);
371 else if (field
->flags
& FIELD_IS_SIGNED
)
372 ret
= PyLong_FromLong((long) val
);
374 ret
= PyLong_FromUnsignedLong((unsigned long) val
);
381 get_tracepoint_field(struct pyrf_event
*pevent
, PyObject
*attr_name
)
383 const char *str
= _PyUnicode_AsString(PyObject_Str(attr_name
));
384 struct perf_evsel
*evsel
= pevent
->evsel
;
385 struct format_field
*field
;
387 if (!evsel
->tp_format
) {
388 struct event_format
*tp_format
;
390 tp_format
= trace_event__tp_format_id(evsel
->attr
.config
);
394 evsel
->tp_format
= tp_format
;
397 field
= pevent_find_any_field(evsel
->tp_format
, str
);
401 return tracepoint_field(pevent
, field
);
405 pyrf_sample_event__getattro(struct pyrf_event
*pevent
, PyObject
*attr_name
)
407 PyObject
*obj
= NULL
;
409 if (is_tracepoint(pevent
))
410 obj
= get_tracepoint_field(pevent
, attr_name
);
412 return obj
?: PyObject_GenericGetAttr((PyObject
*) pevent
, attr_name
);
415 static PyTypeObject pyrf_sample_event__type
= {
416 PyVarObject_HEAD_INIT(NULL
, 0)
417 .tp_name
= "perf.sample_event",
418 .tp_basicsize
= sizeof(struct pyrf_event
),
419 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
420 .tp_doc
= pyrf_sample_event__doc
,
421 .tp_members
= pyrf_sample_event__members
,
422 .tp_repr
= (reprfunc
)pyrf_sample_event__repr
,
423 .tp_getattro
= (getattrofunc
) pyrf_sample_event__getattro
,
426 static char pyrf_context_switch_event__doc
[] = PyDoc_STR("perf context_switch event object.");
428 static PyMemberDef pyrf_context_switch_event__members
[] = {
430 member_def(perf_event_header
, type
, T_UINT
, "event type"),
431 member_def(context_switch_event
, next_prev_pid
, T_UINT
, "next/prev pid"),
432 member_def(context_switch_event
, next_prev_tid
, T_UINT
, "next/prev tid"),
436 static PyObject
*pyrf_context_switch_event__repr(struct pyrf_event
*pevent
)
441 if (asprintf(&s
, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
442 pevent
->event
.context_switch
.next_prev_pid
,
443 pevent
->event
.context_switch
.next_prev_tid
,
444 !!(pevent
->event
.header
.misc
& PERF_RECORD_MISC_SWITCH_OUT
)) < 0) {
445 ret
= PyErr_NoMemory();
447 ret
= _PyUnicode_FromString(s
);
453 static PyTypeObject pyrf_context_switch_event__type
= {
454 PyVarObject_HEAD_INIT(NULL
, 0)
455 .tp_name
= "perf.context_switch_event",
456 .tp_basicsize
= sizeof(struct pyrf_event
),
457 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
458 .tp_doc
= pyrf_context_switch_event__doc
,
459 .tp_members
= pyrf_context_switch_event__members
,
460 .tp_repr
= (reprfunc
)pyrf_context_switch_event__repr
,
463 static int pyrf_event__setup_types(void)
466 pyrf_mmap_event__type
.tp_new
=
467 pyrf_task_event__type
.tp_new
=
468 pyrf_comm_event__type
.tp_new
=
469 pyrf_lost_event__type
.tp_new
=
470 pyrf_read_event__type
.tp_new
=
471 pyrf_sample_event__type
.tp_new
=
472 pyrf_context_switch_event__type
.tp_new
=
473 pyrf_throttle_event__type
.tp_new
= PyType_GenericNew
;
474 err
= PyType_Ready(&pyrf_mmap_event__type
);
477 err
= PyType_Ready(&pyrf_lost_event__type
);
480 err
= PyType_Ready(&pyrf_task_event__type
);
483 err
= PyType_Ready(&pyrf_comm_event__type
);
486 err
= PyType_Ready(&pyrf_throttle_event__type
);
489 err
= PyType_Ready(&pyrf_read_event__type
);
492 err
= PyType_Ready(&pyrf_sample_event__type
);
495 err
= PyType_Ready(&pyrf_context_switch_event__type
);
502 static PyTypeObject
*pyrf_event__type
[] = {
503 [PERF_RECORD_MMAP
] = &pyrf_mmap_event__type
,
504 [PERF_RECORD_LOST
] = &pyrf_lost_event__type
,
505 [PERF_RECORD_COMM
] = &pyrf_comm_event__type
,
506 [PERF_RECORD_EXIT
] = &pyrf_task_event__type
,
507 [PERF_RECORD_THROTTLE
] = &pyrf_throttle_event__type
,
508 [PERF_RECORD_UNTHROTTLE
] = &pyrf_throttle_event__type
,
509 [PERF_RECORD_FORK
] = &pyrf_task_event__type
,
510 [PERF_RECORD_READ
] = &pyrf_read_event__type
,
511 [PERF_RECORD_SAMPLE
] = &pyrf_sample_event__type
,
512 [PERF_RECORD_SWITCH
] = &pyrf_context_switch_event__type
,
513 [PERF_RECORD_SWITCH_CPU_WIDE
] = &pyrf_context_switch_event__type
,
516 static PyObject
*pyrf_event__new(union perf_event
*event
)
518 struct pyrf_event
*pevent
;
521 if ((event
->header
.type
< PERF_RECORD_MMAP
||
522 event
->header
.type
> PERF_RECORD_SAMPLE
) &&
523 !(event
->header
.type
== PERF_RECORD_SWITCH
||
524 event
->header
.type
== PERF_RECORD_SWITCH_CPU_WIDE
))
527 ptype
= pyrf_event__type
[event
->header
.type
];
528 pevent
= PyObject_New(struct pyrf_event
, ptype
);
530 memcpy(&pevent
->event
, event
, event
->header
.size
);
531 return (PyObject
*)pevent
;
534 struct pyrf_cpu_map
{
537 struct cpu_map
*cpus
;
540 static int pyrf_cpu_map__init(struct pyrf_cpu_map
*pcpus
,
541 PyObject
*args
, PyObject
*kwargs
)
543 static char *kwlist
[] = { "cpustr", NULL
};
546 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s",
550 pcpus
->cpus
= cpu_map__new(cpustr
);
551 if (pcpus
->cpus
== NULL
)
556 static void pyrf_cpu_map__delete(struct pyrf_cpu_map
*pcpus
)
558 cpu_map__put(pcpus
->cpus
);
559 Py_TYPE(pcpus
)->tp_free((PyObject
*)pcpus
);
562 static Py_ssize_t
pyrf_cpu_map__length(PyObject
*obj
)
564 struct pyrf_cpu_map
*pcpus
= (void *)obj
;
566 return pcpus
->cpus
->nr
;
569 static PyObject
*pyrf_cpu_map__item(PyObject
*obj
, Py_ssize_t i
)
571 struct pyrf_cpu_map
*pcpus
= (void *)obj
;
573 if (i
>= pcpus
->cpus
->nr
)
576 return Py_BuildValue("i", pcpus
->cpus
->map
[i
]);
579 static PySequenceMethods pyrf_cpu_map__sequence_methods
= {
580 .sq_length
= pyrf_cpu_map__length
,
581 .sq_item
= pyrf_cpu_map__item
,
584 static char pyrf_cpu_map__doc
[] = PyDoc_STR("cpu map object.");
586 static PyTypeObject pyrf_cpu_map__type
= {
587 PyVarObject_HEAD_INIT(NULL
, 0)
588 .tp_name
= "perf.cpu_map",
589 .tp_basicsize
= sizeof(struct pyrf_cpu_map
),
590 .tp_dealloc
= (destructor
)pyrf_cpu_map__delete
,
591 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
592 .tp_doc
= pyrf_cpu_map__doc
,
593 .tp_as_sequence
= &pyrf_cpu_map__sequence_methods
,
594 .tp_init
= (initproc
)pyrf_cpu_map__init
,
597 static int pyrf_cpu_map__setup_types(void)
599 pyrf_cpu_map__type
.tp_new
= PyType_GenericNew
;
600 return PyType_Ready(&pyrf_cpu_map__type
);
603 struct pyrf_thread_map
{
606 struct thread_map
*threads
;
609 static int pyrf_thread_map__init(struct pyrf_thread_map
*pthreads
,
610 PyObject
*args
, PyObject
*kwargs
)
612 static char *kwlist
[] = { "pid", "tid", "uid", NULL
};
613 int pid
= -1, tid
= -1, uid
= UINT_MAX
;
615 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|iii",
616 kwlist
, &pid
, &tid
, &uid
))
619 pthreads
->threads
= thread_map__new(pid
, tid
, uid
);
620 if (pthreads
->threads
== NULL
)
625 static void pyrf_thread_map__delete(struct pyrf_thread_map
*pthreads
)
627 thread_map__put(pthreads
->threads
);
628 Py_TYPE(pthreads
)->tp_free((PyObject
*)pthreads
);
631 static Py_ssize_t
pyrf_thread_map__length(PyObject
*obj
)
633 struct pyrf_thread_map
*pthreads
= (void *)obj
;
635 return pthreads
->threads
->nr
;
638 static PyObject
*pyrf_thread_map__item(PyObject
*obj
, Py_ssize_t i
)
640 struct pyrf_thread_map
*pthreads
= (void *)obj
;
642 if (i
>= pthreads
->threads
->nr
)
645 return Py_BuildValue("i", pthreads
->threads
->map
[i
]);
648 static PySequenceMethods pyrf_thread_map__sequence_methods
= {
649 .sq_length
= pyrf_thread_map__length
,
650 .sq_item
= pyrf_thread_map__item
,
653 static char pyrf_thread_map__doc
[] = PyDoc_STR("thread map object.");
655 static PyTypeObject pyrf_thread_map__type
= {
656 PyVarObject_HEAD_INIT(NULL
, 0)
657 .tp_name
= "perf.thread_map",
658 .tp_basicsize
= sizeof(struct pyrf_thread_map
),
659 .tp_dealloc
= (destructor
)pyrf_thread_map__delete
,
660 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
661 .tp_doc
= pyrf_thread_map__doc
,
662 .tp_as_sequence
= &pyrf_thread_map__sequence_methods
,
663 .tp_init
= (initproc
)pyrf_thread_map__init
,
666 static int pyrf_thread_map__setup_types(void)
668 pyrf_thread_map__type
.tp_new
= PyType_GenericNew
;
669 return PyType_Ready(&pyrf_thread_map__type
);
675 struct perf_evsel evsel
;
678 static int pyrf_evsel__init(struct pyrf_evsel
*pevsel
,
679 PyObject
*args
, PyObject
*kwargs
)
681 struct perf_event_attr attr
= {
682 .type
= PERF_TYPE_HARDWARE
,
683 .config
= PERF_COUNT_HW_CPU_CYCLES
,
684 .sample_type
= PERF_SAMPLE_PERIOD
| PERF_SAMPLE_TID
,
686 static char *kwlist
[] = {
718 u64 sample_period
= 0;
740 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,
741 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", kwlist
,
742 &attr
.type
, &attr
.config
, &attr
.sample_freq
,
743 &sample_period
, &attr
.sample_type
,
744 &attr
.read_format
, &disabled
, &inherit
,
745 &pinned
, &exclusive
, &exclude_user
,
746 &exclude_kernel
, &exclude_hv
, &exclude_idle
,
747 &mmap
, &context_switch
, &comm
, &freq
, &inherit_stat
,
748 &enable_on_exec
, &task
, &watermark
,
749 &precise_ip
, &mmap_data
, &sample_id_all
,
750 &attr
.wakeup_events
, &attr
.bp_type
,
751 &attr
.bp_addr
, &attr
.bp_len
, &idx
))
755 if (sample_period
!= 0) {
756 if (attr
.sample_freq
!= 0)
757 return -1; /* FIXME: throw right exception */
758 attr
.sample_period
= sample_period
;
762 attr
.disabled
= disabled
;
763 attr
.inherit
= inherit
;
764 attr
.pinned
= pinned
;
765 attr
.exclusive
= exclusive
;
766 attr
.exclude_user
= exclude_user
;
767 attr
.exclude_kernel
= exclude_kernel
;
768 attr
.exclude_hv
= exclude_hv
;
769 attr
.exclude_idle
= exclude_idle
;
771 attr
.context_switch
= context_switch
;
774 attr
.inherit_stat
= inherit_stat
;
775 attr
.enable_on_exec
= enable_on_exec
;
777 attr
.watermark
= watermark
;
778 attr
.precise_ip
= precise_ip
;
779 attr
.mmap_data
= mmap_data
;
780 attr
.sample_id_all
= sample_id_all
;
781 attr
.size
= sizeof(attr
);
783 perf_evsel__init(&pevsel
->evsel
, &attr
, idx
);
787 static void pyrf_evsel__delete(struct pyrf_evsel
*pevsel
)
789 perf_evsel__exit(&pevsel
->evsel
);
790 Py_TYPE(pevsel
)->tp_free((PyObject
*)pevsel
);
793 static PyObject
*pyrf_evsel__open(struct pyrf_evsel
*pevsel
,
794 PyObject
*args
, PyObject
*kwargs
)
796 struct perf_evsel
*evsel
= &pevsel
->evsel
;
797 struct cpu_map
*cpus
= NULL
;
798 struct thread_map
*threads
= NULL
;
799 PyObject
*pcpus
= NULL
, *pthreads
= NULL
;
800 int group
= 0, inherit
= 0;
801 static char *kwlist
[] = { "cpus", "threads", "group", "inherit", NULL
};
803 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOii", kwlist
,
804 &pcpus
, &pthreads
, &group
, &inherit
))
807 if (pthreads
!= NULL
)
808 threads
= ((struct pyrf_thread_map
*)pthreads
)->threads
;
811 cpus
= ((struct pyrf_cpu_map
*)pcpus
)->cpus
;
813 evsel
->attr
.inherit
= inherit
;
815 * This will group just the fds for this single evsel, to group
816 * multiple events, use evlist.open().
818 if (perf_evsel__open(evsel
, cpus
, threads
) < 0) {
819 PyErr_SetFromErrno(PyExc_OSError
);
827 static PyMethodDef pyrf_evsel__methods
[] = {
830 .ml_meth
= (PyCFunction
)pyrf_evsel__open
,
831 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
832 .ml_doc
= PyDoc_STR("open the event selector file descriptor table.")
837 static char pyrf_evsel__doc
[] = PyDoc_STR("perf event selector list object.");
839 static PyTypeObject pyrf_evsel__type
= {
840 PyVarObject_HEAD_INIT(NULL
, 0)
841 .tp_name
= "perf.evsel",
842 .tp_basicsize
= sizeof(struct pyrf_evsel
),
843 .tp_dealloc
= (destructor
)pyrf_evsel__delete
,
844 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
845 .tp_doc
= pyrf_evsel__doc
,
846 .tp_methods
= pyrf_evsel__methods
,
847 .tp_init
= (initproc
)pyrf_evsel__init
,
850 static int pyrf_evsel__setup_types(void)
852 pyrf_evsel__type
.tp_new
= PyType_GenericNew
;
853 return PyType_Ready(&pyrf_evsel__type
);
859 struct perf_evlist evlist
;
862 static int pyrf_evlist__init(struct pyrf_evlist
*pevlist
,
863 PyObject
*args
, PyObject
*kwargs __maybe_unused
)
865 PyObject
*pcpus
= NULL
, *pthreads
= NULL
;
866 struct cpu_map
*cpus
;
867 struct thread_map
*threads
;
869 if (!PyArg_ParseTuple(args
, "OO", &pcpus
, &pthreads
))
872 threads
= ((struct pyrf_thread_map
*)pthreads
)->threads
;
873 cpus
= ((struct pyrf_cpu_map
*)pcpus
)->cpus
;
874 perf_evlist__init(&pevlist
->evlist
, cpus
, threads
);
878 static void pyrf_evlist__delete(struct pyrf_evlist
*pevlist
)
880 perf_evlist__exit(&pevlist
->evlist
);
881 Py_TYPE(pevlist
)->tp_free((PyObject
*)pevlist
);
884 static PyObject
*pyrf_evlist__mmap(struct pyrf_evlist
*pevlist
,
885 PyObject
*args
, PyObject
*kwargs
)
887 struct perf_evlist
*evlist
= &pevlist
->evlist
;
888 static char *kwlist
[] = { "pages", "overwrite", NULL
};
889 int pages
= 128, overwrite
= false;
891 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|ii", kwlist
,
895 if (perf_evlist__mmap(evlist
, pages
) < 0) {
896 PyErr_SetFromErrno(PyExc_OSError
);
904 static PyObject
*pyrf_evlist__poll(struct pyrf_evlist
*pevlist
,
905 PyObject
*args
, PyObject
*kwargs
)
907 struct perf_evlist
*evlist
= &pevlist
->evlist
;
908 static char *kwlist
[] = { "timeout", NULL
};
911 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i", kwlist
, &timeout
))
914 n
= perf_evlist__poll(evlist
, timeout
);
916 PyErr_SetFromErrno(PyExc_OSError
);
920 return Py_BuildValue("i", n
);
923 static PyObject
*pyrf_evlist__get_pollfd(struct pyrf_evlist
*pevlist
,
924 PyObject
*args __maybe_unused
,
925 PyObject
*kwargs __maybe_unused
)
927 struct perf_evlist
*evlist
= &pevlist
->evlist
;
928 PyObject
*list
= PyList_New(0);
931 for (i
= 0; i
< evlist
->pollfd
.nr
; ++i
) {
933 #if PY_MAJOR_VERSION < 3
934 FILE *fp
= fdopen(evlist
->pollfd
.entries
[i
].fd
, "r");
939 file
= PyFile_FromFile(fp
, "perf", "r", NULL
);
941 file
= PyFile_FromFd(evlist
->pollfd
.entries
[i
].fd
, "perf", "r", -1, NULL
, NULL
, NULL
, 1);
946 if (PyList_Append(list
, file
) != 0) {
956 return PyErr_NoMemory();
960 static PyObject
*pyrf_evlist__add(struct pyrf_evlist
*pevlist
,
962 PyObject
*kwargs __maybe_unused
)
964 struct perf_evlist
*evlist
= &pevlist
->evlist
;
966 struct perf_evsel
*evsel
;
968 if (!PyArg_ParseTuple(args
, "O", &pevsel
))
972 evsel
= &((struct pyrf_evsel
*)pevsel
)->evsel
;
973 evsel
->idx
= evlist
->nr_entries
;
974 perf_evlist__add(evlist
, evsel
);
976 return Py_BuildValue("i", evlist
->nr_entries
);
979 static PyObject
*pyrf_evlist__read_on_cpu(struct pyrf_evlist
*pevlist
,
980 PyObject
*args
, PyObject
*kwargs
)
982 struct perf_evlist
*evlist
= &pevlist
->evlist
;
983 union perf_event
*event
;
984 int sample_id_all
= 1, cpu
;
985 static char *kwlist
[] = { "cpu", "sample_id_all", NULL
};
986 struct perf_mmap
*md
;
989 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|i", kwlist
,
990 &cpu
, &sample_id_all
))
993 md
= &evlist
->mmap
[cpu
];
994 if (perf_mmap__read_init(md
) < 0)
997 event
= perf_mmap__read_event(md
);
999 PyObject
*pyevent
= pyrf_event__new(event
);
1000 struct pyrf_event
*pevent
= (struct pyrf_event
*)pyevent
;
1001 struct perf_evsel
*evsel
;
1003 if (pyevent
== NULL
)
1004 return PyErr_NoMemory();
1006 evsel
= perf_evlist__event2evsel(evlist
, event
);
1012 pevent
->evsel
= evsel
;
1014 err
= perf_evsel__parse_sample(evsel
, event
, &pevent
->sample
);
1016 /* Consume the even only after we parsed it out. */
1017 perf_mmap__consume(md
);
1020 return PyErr_Format(PyExc_OSError
,
1021 "perf: can't parse sample, err=%d", err
);
1029 static PyObject
*pyrf_evlist__open(struct pyrf_evlist
*pevlist
,
1030 PyObject
*args
, PyObject
*kwargs
)
1032 struct perf_evlist
*evlist
= &pevlist
->evlist
;
1034 static char *kwlist
[] = { "group", NULL
};
1036 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOii", kwlist
, &group
))
1040 perf_evlist__set_leader(evlist
);
1042 if (perf_evlist__open(evlist
) < 0) {
1043 PyErr_SetFromErrno(PyExc_OSError
);
1051 static PyMethodDef pyrf_evlist__methods
[] = {
1054 .ml_meth
= (PyCFunction
)pyrf_evlist__mmap
,
1055 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1056 .ml_doc
= PyDoc_STR("mmap the file descriptor table.")
1060 .ml_meth
= (PyCFunction
)pyrf_evlist__open
,
1061 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1062 .ml_doc
= PyDoc_STR("open the file descriptors.")
1066 .ml_meth
= (PyCFunction
)pyrf_evlist__poll
,
1067 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1068 .ml_doc
= PyDoc_STR("poll the file descriptor table.")
1071 .ml_name
= "get_pollfd",
1072 .ml_meth
= (PyCFunction
)pyrf_evlist__get_pollfd
,
1073 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1074 .ml_doc
= PyDoc_STR("get the poll file descriptor table.")
1078 .ml_meth
= (PyCFunction
)pyrf_evlist__add
,
1079 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1080 .ml_doc
= PyDoc_STR("adds an event selector to the list.")
1083 .ml_name
= "read_on_cpu",
1084 .ml_meth
= (PyCFunction
)pyrf_evlist__read_on_cpu
,
1085 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1086 .ml_doc
= PyDoc_STR("reads an event.")
1088 { .ml_name
= NULL
, }
1091 static Py_ssize_t
pyrf_evlist__length(PyObject
*obj
)
1093 struct pyrf_evlist
*pevlist
= (void *)obj
;
1095 return pevlist
->evlist
.nr_entries
;
1098 static PyObject
*pyrf_evlist__item(PyObject
*obj
, Py_ssize_t i
)
1100 struct pyrf_evlist
*pevlist
= (void *)obj
;
1101 struct perf_evsel
*pos
;
1103 if (i
>= pevlist
->evlist
.nr_entries
)
1106 evlist__for_each_entry(&pevlist
->evlist
, pos
) {
1111 return Py_BuildValue("O", container_of(pos
, struct pyrf_evsel
, evsel
));
1114 static PySequenceMethods pyrf_evlist__sequence_methods
= {
1115 .sq_length
= pyrf_evlist__length
,
1116 .sq_item
= pyrf_evlist__item
,
1119 static char pyrf_evlist__doc
[] = PyDoc_STR("perf event selector list object.");
1121 static PyTypeObject pyrf_evlist__type
= {
1122 PyVarObject_HEAD_INIT(NULL
, 0)
1123 .tp_name
= "perf.evlist",
1124 .tp_basicsize
= sizeof(struct pyrf_evlist
),
1125 .tp_dealloc
= (destructor
)pyrf_evlist__delete
,
1126 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
1127 .tp_as_sequence
= &pyrf_evlist__sequence_methods
,
1128 .tp_doc
= pyrf_evlist__doc
,
1129 .tp_methods
= pyrf_evlist__methods
,
1130 .tp_init
= (initproc
)pyrf_evlist__init
,
1133 static int pyrf_evlist__setup_types(void)
1135 pyrf_evlist__type
.tp_new
= PyType_GenericNew
;
1136 return PyType_Ready(&pyrf_evlist__type
);
1139 #define PERF_CONST(name) { #name, PERF_##name }
1144 } perf__constants
[] = {
1145 PERF_CONST(TYPE_HARDWARE
),
1146 PERF_CONST(TYPE_SOFTWARE
),
1147 PERF_CONST(TYPE_TRACEPOINT
),
1148 PERF_CONST(TYPE_HW_CACHE
),
1149 PERF_CONST(TYPE_RAW
),
1150 PERF_CONST(TYPE_BREAKPOINT
),
1152 PERF_CONST(COUNT_HW_CPU_CYCLES
),
1153 PERF_CONST(COUNT_HW_INSTRUCTIONS
),
1154 PERF_CONST(COUNT_HW_CACHE_REFERENCES
),
1155 PERF_CONST(COUNT_HW_CACHE_MISSES
),
1156 PERF_CONST(COUNT_HW_BRANCH_INSTRUCTIONS
),
1157 PERF_CONST(COUNT_HW_BRANCH_MISSES
),
1158 PERF_CONST(COUNT_HW_BUS_CYCLES
),
1159 PERF_CONST(COUNT_HW_CACHE_L1D
),
1160 PERF_CONST(COUNT_HW_CACHE_L1I
),
1161 PERF_CONST(COUNT_HW_CACHE_LL
),
1162 PERF_CONST(COUNT_HW_CACHE_DTLB
),
1163 PERF_CONST(COUNT_HW_CACHE_ITLB
),
1164 PERF_CONST(COUNT_HW_CACHE_BPU
),
1165 PERF_CONST(COUNT_HW_CACHE_OP_READ
),
1166 PERF_CONST(COUNT_HW_CACHE_OP_WRITE
),
1167 PERF_CONST(COUNT_HW_CACHE_OP_PREFETCH
),
1168 PERF_CONST(COUNT_HW_CACHE_RESULT_ACCESS
),
1169 PERF_CONST(COUNT_HW_CACHE_RESULT_MISS
),
1171 PERF_CONST(COUNT_HW_STALLED_CYCLES_FRONTEND
),
1172 PERF_CONST(COUNT_HW_STALLED_CYCLES_BACKEND
),
1174 PERF_CONST(COUNT_SW_CPU_CLOCK
),
1175 PERF_CONST(COUNT_SW_TASK_CLOCK
),
1176 PERF_CONST(COUNT_SW_PAGE_FAULTS
),
1177 PERF_CONST(COUNT_SW_CONTEXT_SWITCHES
),
1178 PERF_CONST(COUNT_SW_CPU_MIGRATIONS
),
1179 PERF_CONST(COUNT_SW_PAGE_FAULTS_MIN
),
1180 PERF_CONST(COUNT_SW_PAGE_FAULTS_MAJ
),
1181 PERF_CONST(COUNT_SW_ALIGNMENT_FAULTS
),
1182 PERF_CONST(COUNT_SW_EMULATION_FAULTS
),
1183 PERF_CONST(COUNT_SW_DUMMY
),
1185 PERF_CONST(SAMPLE_IP
),
1186 PERF_CONST(SAMPLE_TID
),
1187 PERF_CONST(SAMPLE_TIME
),
1188 PERF_CONST(SAMPLE_ADDR
),
1189 PERF_CONST(SAMPLE_READ
),
1190 PERF_CONST(SAMPLE_CALLCHAIN
),
1191 PERF_CONST(SAMPLE_ID
),
1192 PERF_CONST(SAMPLE_CPU
),
1193 PERF_CONST(SAMPLE_PERIOD
),
1194 PERF_CONST(SAMPLE_STREAM_ID
),
1195 PERF_CONST(SAMPLE_RAW
),
1197 PERF_CONST(FORMAT_TOTAL_TIME_ENABLED
),
1198 PERF_CONST(FORMAT_TOTAL_TIME_RUNNING
),
1199 PERF_CONST(FORMAT_ID
),
1200 PERF_CONST(FORMAT_GROUP
),
1202 PERF_CONST(RECORD_MMAP
),
1203 PERF_CONST(RECORD_LOST
),
1204 PERF_CONST(RECORD_COMM
),
1205 PERF_CONST(RECORD_EXIT
),
1206 PERF_CONST(RECORD_THROTTLE
),
1207 PERF_CONST(RECORD_UNTHROTTLE
),
1208 PERF_CONST(RECORD_FORK
),
1209 PERF_CONST(RECORD_READ
),
1210 PERF_CONST(RECORD_SAMPLE
),
1211 PERF_CONST(RECORD_MMAP2
),
1212 PERF_CONST(RECORD_AUX
),
1213 PERF_CONST(RECORD_ITRACE_START
),
1214 PERF_CONST(RECORD_LOST_SAMPLES
),
1215 PERF_CONST(RECORD_SWITCH
),
1216 PERF_CONST(RECORD_SWITCH_CPU_WIDE
),
1218 PERF_CONST(RECORD_MISC_SWITCH_OUT
),
1222 static PyObject
*pyrf__tracepoint(struct pyrf_evsel
*pevsel
,
1223 PyObject
*args
, PyObject
*kwargs
)
1225 struct event_format
*tp_format
;
1226 static char *kwlist
[] = { "sys", "name", NULL
};
1230 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|ss", kwlist
,
1234 tp_format
= trace_event__tp_format(sys
, name
);
1235 if (IS_ERR(tp_format
))
1236 return _PyLong_FromLong(-1);
1238 return _PyLong_FromLong(tp_format
->id
);
1241 static PyMethodDef perf__methods
[] = {
1243 .ml_name
= "tracepoint",
1244 .ml_meth
= (PyCFunction
) pyrf__tracepoint
,
1245 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
1246 .ml_doc
= PyDoc_STR("Get tracepoint config.")
1248 { .ml_name
= NULL
, }
1251 #if PY_MAJOR_VERSION < 3
1252 PyMODINIT_FUNC
initperf(void)
1254 PyMODINIT_FUNC
PyInit_perf(void)
1260 #if PY_MAJOR_VERSION < 3
1261 PyObject
*module
= Py_InitModule("perf", perf__methods
);
1263 static struct PyModuleDef moduledef
= {
1264 PyModuleDef_HEAD_INIT
,
1265 "perf", /* m_name */
1268 perf__methods
, /* m_methods */
1269 NULL
, /* m_reload */
1270 NULL
, /* m_traverse */
1274 PyObject
*module
= PyModule_Create(&moduledef
);
1277 if (module
== NULL
||
1278 pyrf_event__setup_types() < 0 ||
1279 pyrf_evlist__setup_types() < 0 ||
1280 pyrf_evsel__setup_types() < 0 ||
1281 pyrf_thread_map__setup_types() < 0 ||
1282 pyrf_cpu_map__setup_types() < 0)
1283 #if PY_MAJOR_VERSION < 3
1289 /* The page_size is placed in util object. */
1290 page_size
= sysconf(_SC_PAGE_SIZE
);
1292 Py_INCREF(&pyrf_evlist__type
);
1293 PyModule_AddObject(module
, "evlist", (PyObject
*)&pyrf_evlist__type
);
1295 Py_INCREF(&pyrf_evsel__type
);
1296 PyModule_AddObject(module
, "evsel", (PyObject
*)&pyrf_evsel__type
);
1298 Py_INCREF(&pyrf_mmap_event__type
);
1299 PyModule_AddObject(module
, "mmap_event", (PyObject
*)&pyrf_mmap_event__type
);
1301 Py_INCREF(&pyrf_lost_event__type
);
1302 PyModule_AddObject(module
, "lost_event", (PyObject
*)&pyrf_lost_event__type
);
1304 Py_INCREF(&pyrf_comm_event__type
);
1305 PyModule_AddObject(module
, "comm_event", (PyObject
*)&pyrf_comm_event__type
);
1307 Py_INCREF(&pyrf_task_event__type
);
1308 PyModule_AddObject(module
, "task_event", (PyObject
*)&pyrf_task_event__type
);
1310 Py_INCREF(&pyrf_throttle_event__type
);
1311 PyModule_AddObject(module
, "throttle_event", (PyObject
*)&pyrf_throttle_event__type
);
1313 Py_INCREF(&pyrf_task_event__type
);
1314 PyModule_AddObject(module
, "task_event", (PyObject
*)&pyrf_task_event__type
);
1316 Py_INCREF(&pyrf_read_event__type
);
1317 PyModule_AddObject(module
, "read_event", (PyObject
*)&pyrf_read_event__type
);
1319 Py_INCREF(&pyrf_sample_event__type
);
1320 PyModule_AddObject(module
, "sample_event", (PyObject
*)&pyrf_sample_event__type
);
1322 Py_INCREF(&pyrf_context_switch_event__type
);
1323 PyModule_AddObject(module
, "switch_event", (PyObject
*)&pyrf_context_switch_event__type
);
1325 Py_INCREF(&pyrf_thread_map__type
);
1326 PyModule_AddObject(module
, "thread_map", (PyObject
*)&pyrf_thread_map__type
);
1328 Py_INCREF(&pyrf_cpu_map__type
);
1329 PyModule_AddObject(module
, "cpu_map", (PyObject
*)&pyrf_cpu_map__type
);
1331 dict
= PyModule_GetDict(module
);
1335 for (i
= 0; perf__constants
[i
].name
!= NULL
; i
++) {
1336 obj
= _PyLong_FromLong(perf__constants
[i
].value
);
1339 PyDict_SetItemString(dict
, perf__constants
[i
].name
, obj
);
1344 if (PyErr_Occurred())
1345 PyErr_SetString(PyExc_ImportError
, "perf: Init failed!");
1346 #if PY_MAJOR_VERSION >= 3
1352 * Dummy, to avoid dragging all the test_attr infrastructure in the python
1355 void test_attr__open(struct perf_event_attr
*attr
, pid_t pid
, int cpu
,
1356 int fd
, int group_fd
, unsigned long flags
)