2 #include <structmember.h>
9 #include "thread_map.h"
11 struct throttle_event
{
12 struct perf_event_header header
;
18 #define member_def(type, member, ptype, help) \
20 offsetof(struct pyrf_event, event) + offsetof(struct type, member), \
23 #define sample_member_def(name, member, ptype, help) \
25 offsetof(struct pyrf_event, sample) + offsetof(struct perf_sample, member), \
30 struct perf_sample sample
;
31 union perf_event event
;
34 #define T_ULONG_LONG T_ULONG
36 #define sample_members \
37 sample_member_def(sample_ip, ip, T_ULONG_LONG, "event type"), \
38 sample_member_def(sample_pid, pid, T_INT, "event pid"), \
39 sample_member_def(sample_tid, tid, T_INT, "event tid"), \
40 sample_member_def(sample_time, time, T_ULONG_LONG, "event timestamp"), \
41 sample_member_def(sample_addr, addr, T_ULONG_LONG, "event addr"), \
42 sample_member_def(sample_id, id, T_ULONG_LONG, "event id"), \
43 sample_member_def(sample_stream_id, stream_id, T_ULONG_LONG, "event stream id"), \
44 sample_member_def(sample_period, period, T_ULONG_LONG, "event period"), \
45 sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
47 static char pyrf_mmap_event__doc
[] = PyDoc_STR("perf mmap event object.");
49 static PyMemberDef pyrf_mmap_event__members
[] = {
51 member_def(perf_event_header
, type
, T_UINT
, "event type"),
52 member_def(mmap_event
, pid
, T_UINT
, "event pid"),
53 member_def(mmap_event
, tid
, T_UINT
, "event tid"),
54 member_def(mmap_event
, start
, T_ULONG_LONG
, "start of the map"),
55 member_def(mmap_event
, len
, T_ULONG_LONG
, "map length"),
56 member_def(mmap_event
, pgoff
, T_ULONG_LONG
, "page offset"),
57 member_def(mmap_event
, filename
, T_STRING_INPLACE
, "backing store"),
61 static PyObject
*pyrf_mmap_event__repr(struct pyrf_event
*pevent
)
66 if (asprintf(&s
, "{ type: mmap, pid: %u, tid: %u, start: %#" PRIx64
", "
67 "length: %#" PRIx64
", offset: %#" PRIx64
", "
69 pevent
->event
.mmap
.pid
, pevent
->event
.mmap
.tid
,
70 pevent
->event
.mmap
.start
, pevent
->event
.mmap
.len
,
71 pevent
->event
.mmap
.pgoff
, pevent
->event
.mmap
.filename
) < 0) {
72 ret
= PyErr_NoMemory();
74 ret
= PyString_FromString(s
);
80 static PyTypeObject pyrf_mmap_event__type
= {
81 PyVarObject_HEAD_INIT(NULL
, 0)
82 .tp_name
= "perf.mmap_event",
83 .tp_basicsize
= sizeof(struct pyrf_event
),
84 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
85 .tp_doc
= pyrf_mmap_event__doc
,
86 .tp_members
= pyrf_mmap_event__members
,
87 .tp_repr
= (reprfunc
)pyrf_mmap_event__repr
,
90 static char pyrf_task_event__doc
[] = PyDoc_STR("perf task (fork/exit) event object.");
92 static PyMemberDef pyrf_task_event__members
[] = {
94 member_def(perf_event_header
, type
, T_UINT
, "event type"),
95 member_def(fork_event
, pid
, T_UINT
, "event pid"),
96 member_def(fork_event
, ppid
, T_UINT
, "event ppid"),
97 member_def(fork_event
, tid
, T_UINT
, "event tid"),
98 member_def(fork_event
, ptid
, T_UINT
, "event ptid"),
99 member_def(fork_event
, time
, T_ULONG_LONG
, "timestamp"),
103 static PyObject
*pyrf_task_event__repr(struct pyrf_event
*pevent
)
105 return PyString_FromFormat("{ type: %s, pid: %u, ppid: %u, tid: %u, "
106 "ptid: %u, time: %" PRIu64
"}",
107 pevent
->event
.header
.type
== PERF_RECORD_FORK
? "fork" : "exit",
108 pevent
->event
.fork
.pid
,
109 pevent
->event
.fork
.ppid
,
110 pevent
->event
.fork
.tid
,
111 pevent
->event
.fork
.ptid
,
112 pevent
->event
.fork
.time
);
115 static PyTypeObject pyrf_task_event__type
= {
116 PyVarObject_HEAD_INIT(NULL
, 0)
117 .tp_name
= "perf.task_event",
118 .tp_basicsize
= sizeof(struct pyrf_event
),
119 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
120 .tp_doc
= pyrf_task_event__doc
,
121 .tp_members
= pyrf_task_event__members
,
122 .tp_repr
= (reprfunc
)pyrf_task_event__repr
,
125 static char pyrf_comm_event__doc
[] = PyDoc_STR("perf comm event object.");
127 static PyMemberDef pyrf_comm_event__members
[] = {
129 member_def(perf_event_header
, type
, T_UINT
, "event type"),
130 member_def(comm_event
, pid
, T_UINT
, "event pid"),
131 member_def(comm_event
, tid
, T_UINT
, "event tid"),
132 member_def(comm_event
, comm
, T_STRING_INPLACE
, "process name"),
136 static PyObject
*pyrf_comm_event__repr(struct pyrf_event
*pevent
)
138 return PyString_FromFormat("{ type: comm, pid: %u, tid: %u, comm: %s }",
139 pevent
->event
.comm
.pid
,
140 pevent
->event
.comm
.tid
,
141 pevent
->event
.comm
.comm
);
144 static PyTypeObject pyrf_comm_event__type
= {
145 PyVarObject_HEAD_INIT(NULL
, 0)
146 .tp_name
= "perf.comm_event",
147 .tp_basicsize
= sizeof(struct pyrf_event
),
148 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
149 .tp_doc
= pyrf_comm_event__doc
,
150 .tp_members
= pyrf_comm_event__members
,
151 .tp_repr
= (reprfunc
)pyrf_comm_event__repr
,
154 static char pyrf_throttle_event__doc
[] = PyDoc_STR("perf throttle event object.");
156 static PyMemberDef pyrf_throttle_event__members
[] = {
158 member_def(perf_event_header
, type
, T_UINT
, "event type"),
159 member_def(throttle_event
, time
, T_ULONG_LONG
, "timestamp"),
160 member_def(throttle_event
, id
, T_ULONG_LONG
, "event id"),
161 member_def(throttle_event
, stream_id
, T_ULONG_LONG
, "event stream id"),
165 static PyObject
*pyrf_throttle_event__repr(struct pyrf_event
*pevent
)
167 struct throttle_event
*te
= (struct throttle_event
*)(&pevent
->event
.header
+ 1);
169 return PyString_FromFormat("{ type: %sthrottle, time: %" PRIu64
", id: %" PRIu64
170 ", stream_id: %" PRIu64
" }",
171 pevent
->event
.header
.type
== PERF_RECORD_THROTTLE
? "" : "un",
172 te
->time
, te
->id
, te
->stream_id
);
175 static PyTypeObject pyrf_throttle_event__type
= {
176 PyVarObject_HEAD_INIT(NULL
, 0)
177 .tp_name
= "perf.throttle_event",
178 .tp_basicsize
= sizeof(struct pyrf_event
),
179 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
180 .tp_doc
= pyrf_throttle_event__doc
,
181 .tp_members
= pyrf_throttle_event__members
,
182 .tp_repr
= (reprfunc
)pyrf_throttle_event__repr
,
185 static int pyrf_event__setup_types(void)
188 pyrf_mmap_event__type
.tp_new
=
189 pyrf_task_event__type
.tp_new
=
190 pyrf_comm_event__type
.tp_new
=
191 pyrf_throttle_event__type
.tp_new
= PyType_GenericNew
;
192 err
= PyType_Ready(&pyrf_mmap_event__type
);
195 err
= PyType_Ready(&pyrf_task_event__type
);
198 err
= PyType_Ready(&pyrf_comm_event__type
);
201 err
= PyType_Ready(&pyrf_throttle_event__type
);
208 static PyTypeObject
*pyrf_event__type
[] = {
209 [PERF_RECORD_MMAP
] = &pyrf_mmap_event__type
,
210 [PERF_RECORD_LOST
] = &pyrf_mmap_event__type
,
211 [PERF_RECORD_COMM
] = &pyrf_comm_event__type
,
212 [PERF_RECORD_EXIT
] = &pyrf_task_event__type
,
213 [PERF_RECORD_THROTTLE
] = &pyrf_throttle_event__type
,
214 [PERF_RECORD_UNTHROTTLE
] = &pyrf_throttle_event__type
,
215 [PERF_RECORD_FORK
] = &pyrf_task_event__type
,
216 [PERF_RECORD_READ
] = &pyrf_mmap_event__type
,
217 [PERF_RECORD_SAMPLE
] = &pyrf_mmap_event__type
,
220 static PyObject
*pyrf_event__new(union perf_event
*event
)
222 struct pyrf_event
*pevent
;
225 if (event
->header
.type
< PERF_RECORD_MMAP
||
226 event
->header
.type
> PERF_RECORD_SAMPLE
)
229 ptype
= pyrf_event__type
[event
->header
.type
];
230 pevent
= PyObject_New(struct pyrf_event
, ptype
);
232 memcpy(&pevent
->event
, event
, event
->header
.size
);
233 return (PyObject
*)pevent
;
236 struct pyrf_cpu_map
{
239 struct cpu_map
*cpus
;
242 static int pyrf_cpu_map__init(struct pyrf_cpu_map
*pcpus
,
243 PyObject
*args
, PyObject
*kwargs
)
245 static char *kwlist
[] = { "cpustr", NULL
, NULL
, };
248 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|s",
252 pcpus
->cpus
= cpu_map__new(cpustr
);
253 if (pcpus
->cpus
== NULL
)
258 static void pyrf_cpu_map__delete(struct pyrf_cpu_map
*pcpus
)
260 cpu_map__delete(pcpus
->cpus
);
261 pcpus
->ob_type
->tp_free((PyObject
*)pcpus
);
264 static Py_ssize_t
pyrf_cpu_map__length(PyObject
*obj
)
266 struct pyrf_cpu_map
*pcpus
= (void *)obj
;
268 return pcpus
->cpus
->nr
;
271 static PyObject
*pyrf_cpu_map__item(PyObject
*obj
, Py_ssize_t i
)
273 struct pyrf_cpu_map
*pcpus
= (void *)obj
;
275 if (i
>= pcpus
->cpus
->nr
)
278 return Py_BuildValue("i", pcpus
->cpus
->map
[i
]);
281 static PySequenceMethods pyrf_cpu_map__sequence_methods
= {
282 .sq_length
= pyrf_cpu_map__length
,
283 .sq_item
= pyrf_cpu_map__item
,
286 static char pyrf_cpu_map__doc
[] = PyDoc_STR("cpu map object.");
288 static PyTypeObject pyrf_cpu_map__type
= {
289 PyVarObject_HEAD_INIT(NULL
, 0)
290 .tp_name
= "perf.cpu_map",
291 .tp_basicsize
= sizeof(struct pyrf_cpu_map
),
292 .tp_dealloc
= (destructor
)pyrf_cpu_map__delete
,
293 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
294 .tp_doc
= pyrf_cpu_map__doc
,
295 .tp_as_sequence
= &pyrf_cpu_map__sequence_methods
,
296 .tp_init
= (initproc
)pyrf_cpu_map__init
,
299 static int pyrf_cpu_map__setup_types(void)
301 pyrf_cpu_map__type
.tp_new
= PyType_GenericNew
;
302 return PyType_Ready(&pyrf_cpu_map__type
);
305 struct pyrf_thread_map
{
308 struct thread_map
*threads
;
311 static int pyrf_thread_map__init(struct pyrf_thread_map
*pthreads
,
312 PyObject
*args
, PyObject
*kwargs
)
314 static char *kwlist
[] = { "pid", "tid", NULL
, NULL
, };
315 int pid
= -1, tid
= -1;
317 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|ii",
321 pthreads
->threads
= thread_map__new(pid
, tid
);
322 if (pthreads
->threads
== NULL
)
327 static void pyrf_thread_map__delete(struct pyrf_thread_map
*pthreads
)
329 thread_map__delete(pthreads
->threads
);
330 pthreads
->ob_type
->tp_free((PyObject
*)pthreads
);
333 static Py_ssize_t
pyrf_thread_map__length(PyObject
*obj
)
335 struct pyrf_thread_map
*pthreads
= (void *)obj
;
337 return pthreads
->threads
->nr
;
340 static PyObject
*pyrf_thread_map__item(PyObject
*obj
, Py_ssize_t i
)
342 struct pyrf_thread_map
*pthreads
= (void *)obj
;
344 if (i
>= pthreads
->threads
->nr
)
347 return Py_BuildValue("i", pthreads
->threads
->map
[i
]);
350 static PySequenceMethods pyrf_thread_map__sequence_methods
= {
351 .sq_length
= pyrf_thread_map__length
,
352 .sq_item
= pyrf_thread_map__item
,
355 static char pyrf_thread_map__doc
[] = PyDoc_STR("thread map object.");
357 static PyTypeObject pyrf_thread_map__type
= {
358 PyVarObject_HEAD_INIT(NULL
, 0)
359 .tp_name
= "perf.thread_map",
360 .tp_basicsize
= sizeof(struct pyrf_thread_map
),
361 .tp_dealloc
= (destructor
)pyrf_thread_map__delete
,
362 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
363 .tp_doc
= pyrf_thread_map__doc
,
364 .tp_as_sequence
= &pyrf_thread_map__sequence_methods
,
365 .tp_init
= (initproc
)pyrf_thread_map__init
,
368 static int pyrf_thread_map__setup_types(void)
370 pyrf_thread_map__type
.tp_new
= PyType_GenericNew
;
371 return PyType_Ready(&pyrf_thread_map__type
);
377 struct perf_evsel evsel
;
380 static int pyrf_evsel__init(struct pyrf_evsel
*pevsel
,
381 PyObject
*args
, PyObject
*kwargs
)
383 struct perf_event_attr attr
= {
384 .type
= PERF_TYPE_HARDWARE
,
385 .config
= PERF_COUNT_HW_CPU_CYCLES
,
386 .sample_type
= PERF_SAMPLE_PERIOD
| PERF_SAMPLE_TID
,
388 static char *kwlist
[] = {
416 "bp_len", NULL
, NULL
, };
417 u64 sample_period
= 0;
438 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,
439 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist
,
440 &attr
.type
, &attr
.config
, &attr
.sample_freq
,
441 &sample_period
, &attr
.sample_type
,
442 &attr
.read_format
, &disabled
, &inherit
,
443 &pinned
, &exclusive
, &exclude_user
,
444 &exclude_kernel
, &exclude_hv
, &exclude_idle
,
445 &mmap
, &comm
, &freq
, &inherit_stat
,
446 &enable_on_exec
, &task
, &watermark
,
447 &precise_ip
, &mmap_data
, &sample_id_all
,
448 &attr
.wakeup_events
, &attr
.bp_type
,
449 &attr
.bp_addr
, &attr
.bp_len
, &idx
))
453 if (sample_period
!= 0) {
454 if (attr
.sample_freq
!= 0)
455 return -1; /* FIXME: throw right exception */
456 attr
.sample_period
= sample_period
;
460 attr
.disabled
= disabled
;
461 attr
.inherit
= inherit
;
462 attr
.pinned
= pinned
;
463 attr
.exclusive
= exclusive
;
464 attr
.exclude_user
= exclude_user
;
465 attr
.exclude_kernel
= exclude_kernel
;
466 attr
.exclude_hv
= exclude_hv
;
467 attr
.exclude_idle
= exclude_idle
;
471 attr
.inherit_stat
= inherit_stat
;
472 attr
.enable_on_exec
= enable_on_exec
;
474 attr
.watermark
= watermark
;
475 attr
.precise_ip
= precise_ip
;
476 attr
.mmap_data
= mmap_data
;
477 attr
.sample_id_all
= sample_id_all
;
479 perf_evsel__init(&pevsel
->evsel
, &attr
, idx
);
483 static void pyrf_evsel__delete(struct pyrf_evsel
*pevsel
)
485 perf_evsel__exit(&pevsel
->evsel
);
486 pevsel
->ob_type
->tp_free((PyObject
*)pevsel
);
489 static PyObject
*pyrf_evsel__open(struct pyrf_evsel
*pevsel
,
490 PyObject
*args
, PyObject
*kwargs
)
492 struct perf_evsel
*evsel
= &pevsel
->evsel
;
493 struct cpu_map
*cpus
= NULL
;
494 struct thread_map
*threads
= NULL
;
495 PyObject
*pcpus
= NULL
, *pthreads
= NULL
;
496 int group
= 0, overwrite
= 0;
497 static char *kwlist
[] = {"cpus", "threads", "group", "overwrite", NULL
, NULL
};
499 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|OOii", kwlist
,
500 &pcpus
, &pthreads
, &group
, &overwrite
))
503 if (pthreads
!= NULL
)
504 threads
= ((struct pyrf_thread_map
*)pthreads
)->threads
;
507 cpus
= ((struct pyrf_cpu_map
*)pcpus
)->cpus
;
509 if (perf_evsel__open(evsel
, cpus
, threads
, group
, overwrite
) < 0) {
510 PyErr_SetFromErrno(PyExc_OSError
);
518 static PyMethodDef pyrf_evsel__methods
[] = {
521 .ml_meth
= (PyCFunction
)pyrf_evsel__open
,
522 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
523 .ml_doc
= PyDoc_STR("open the event selector file descriptor table.")
528 static char pyrf_evsel__doc
[] = PyDoc_STR("perf event selector list object.");
530 static PyTypeObject pyrf_evsel__type
= {
531 PyVarObject_HEAD_INIT(NULL
, 0)
532 .tp_name
= "perf.evsel",
533 .tp_basicsize
= sizeof(struct pyrf_evsel
),
534 .tp_dealloc
= (destructor
)pyrf_evsel__delete
,
535 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
536 .tp_doc
= pyrf_evsel__doc
,
537 .tp_methods
= pyrf_evsel__methods
,
538 .tp_init
= (initproc
)pyrf_evsel__init
,
541 static int pyrf_evsel__setup_types(void)
543 pyrf_evsel__type
.tp_new
= PyType_GenericNew
;
544 return PyType_Ready(&pyrf_evsel__type
);
550 struct perf_evlist evlist
;
553 static int pyrf_evlist__init(struct pyrf_evlist
*pevlist
,
554 PyObject
*args
, PyObject
*kwargs
)
556 perf_evlist__init(&pevlist
->evlist
);
560 static void pyrf_evlist__delete(struct pyrf_evlist
*pevlist
)
562 perf_evlist__exit(&pevlist
->evlist
);
563 pevlist
->ob_type
->tp_free((PyObject
*)pevlist
);
566 static PyObject
*pyrf_evlist__mmap(struct pyrf_evlist
*pevlist
,
567 PyObject
*args
, PyObject
*kwargs
)
569 struct perf_evlist
*evlist
= &pevlist
->evlist
;
570 PyObject
*pcpus
= NULL
, *pthreads
= NULL
;
571 struct cpu_map
*cpus
= NULL
;
572 struct thread_map
*threads
= NULL
;
573 static char *kwlist
[] = {"cpus", "threads", "pages", "overwrite",
575 int pages
= 128, overwrite
= false;
577 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|ii", kwlist
,
578 &pcpus
, &pthreads
, &pages
, &overwrite
))
581 threads
= ((struct pyrf_thread_map
*)pthreads
)->threads
;
582 cpus
= ((struct pyrf_cpu_map
*)pcpus
)->cpus
;
584 if (perf_evlist__mmap(evlist
, cpus
, threads
, pages
, overwrite
) < 0) {
585 PyErr_SetFromErrno(PyExc_OSError
);
593 static PyObject
*pyrf_evlist__poll(struct pyrf_evlist
*pevlist
,
594 PyObject
*args
, PyObject
*kwargs
)
596 struct perf_evlist
*evlist
= &pevlist
->evlist
;
597 static char *kwlist
[] = {"timeout", NULL
, NULL
};
600 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i", kwlist
, &timeout
))
603 n
= poll(evlist
->pollfd
, evlist
->nr_fds
, timeout
);
605 PyErr_SetFromErrno(PyExc_OSError
);
609 return Py_BuildValue("i", n
);
612 static PyObject
*pyrf_evlist__get_pollfd(struct pyrf_evlist
*pevlist
,
613 PyObject
*args
, PyObject
*kwargs
)
615 struct perf_evlist
*evlist
= &pevlist
->evlist
;
616 PyObject
*list
= PyList_New(0);
619 for (i
= 0; i
< evlist
->nr_fds
; ++i
) {
621 FILE *fp
= fdopen(evlist
->pollfd
[i
].fd
, "r");
626 file
= PyFile_FromFile(fp
, "perf", "r", NULL
);
630 if (PyList_Append(list
, file
) != 0) {
640 return PyErr_NoMemory();
644 static PyObject
*pyrf_evlist__add(struct pyrf_evlist
*pevlist
,
645 PyObject
*args
, PyObject
*kwargs
)
647 struct perf_evlist
*evlist
= &pevlist
->evlist
;
649 struct perf_evsel
*evsel
;
651 if (!PyArg_ParseTuple(args
, "O", &pevsel
))
655 evsel
= &((struct pyrf_evsel
*)pevsel
)->evsel
;
656 evsel
->idx
= evlist
->nr_entries
;
657 perf_evlist__add(evlist
, evsel
);
659 return Py_BuildValue("i", evlist
->nr_entries
);
662 static PyObject
*pyrf_evlist__read_on_cpu(struct pyrf_evlist
*pevlist
,
663 PyObject
*args
, PyObject
*kwargs
)
665 struct perf_evlist
*evlist
= &pevlist
->evlist
;
666 union perf_event
*event
;
667 int sample_id_all
= 1, cpu
;
668 static char *kwlist
[] = {"sample_id_all", NULL
, NULL
};
670 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|i", kwlist
,
671 &cpu
, &sample_id_all
))
674 event
= perf_evlist__read_on_cpu(evlist
, cpu
);
676 struct perf_evsel
*first
;
677 PyObject
*pyevent
= pyrf_event__new(event
);
678 struct pyrf_event
*pevent
= (struct pyrf_event
*)pyevent
;
681 return PyErr_NoMemory();
683 first
= list_entry(evlist
->entries
.next
, struct perf_evsel
, node
);
684 perf_event__parse_sample(event
, first
->attr
.sample_type
, sample_id_all
,
693 static PyMethodDef pyrf_evlist__methods
[] = {
696 .ml_meth
= (PyCFunction
)pyrf_evlist__mmap
,
697 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
698 .ml_doc
= PyDoc_STR("mmap the file descriptor table.")
702 .ml_meth
= (PyCFunction
)pyrf_evlist__poll
,
703 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
704 .ml_doc
= PyDoc_STR("poll the file descriptor table.")
707 .ml_name
= "get_pollfd",
708 .ml_meth
= (PyCFunction
)pyrf_evlist__get_pollfd
,
709 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
710 .ml_doc
= PyDoc_STR("get the poll file descriptor table.")
714 .ml_meth
= (PyCFunction
)pyrf_evlist__add
,
715 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
716 .ml_doc
= PyDoc_STR("adds an event selector to the list.")
719 .ml_name
= "read_on_cpu",
720 .ml_meth
= (PyCFunction
)pyrf_evlist__read_on_cpu
,
721 .ml_flags
= METH_VARARGS
| METH_KEYWORDS
,
722 .ml_doc
= PyDoc_STR("reads an event.")
727 static Py_ssize_t
pyrf_evlist__length(PyObject
*obj
)
729 struct pyrf_evlist
*pevlist
= (void *)obj
;
731 return pevlist
->evlist
.nr_entries
;
734 static PyObject
*pyrf_evlist__item(PyObject
*obj
, Py_ssize_t i
)
736 struct pyrf_evlist
*pevlist
= (void *)obj
;
737 struct perf_evsel
*pos
;
739 if (i
>= pevlist
->evlist
.nr_entries
)
742 list_for_each_entry(pos
, &pevlist
->evlist
.entries
, node
)
746 return Py_BuildValue("O", container_of(pos
, struct pyrf_evsel
, evsel
));
749 static PySequenceMethods pyrf_evlist__sequence_methods
= {
750 .sq_length
= pyrf_evlist__length
,
751 .sq_item
= pyrf_evlist__item
,
754 static char pyrf_evlist__doc
[] = PyDoc_STR("perf event selector list object.");
756 static PyTypeObject pyrf_evlist__type
= {
757 PyVarObject_HEAD_INIT(NULL
, 0)
758 .tp_name
= "perf.evlist",
759 .tp_basicsize
= sizeof(struct pyrf_evlist
),
760 .tp_dealloc
= (destructor
)pyrf_evlist__delete
,
761 .tp_flags
= Py_TPFLAGS_DEFAULT
|Py_TPFLAGS_BASETYPE
,
762 .tp_as_sequence
= &pyrf_evlist__sequence_methods
,
763 .tp_doc
= pyrf_evlist__doc
,
764 .tp_methods
= pyrf_evlist__methods
,
765 .tp_init
= (initproc
)pyrf_evlist__init
,
768 static int pyrf_evlist__setup_types(void)
770 pyrf_evlist__type
.tp_new
= PyType_GenericNew
;
771 return PyType_Ready(&pyrf_evlist__type
);
777 } perf__constants
[] = {
778 { "TYPE_HARDWARE", PERF_TYPE_HARDWARE
},
779 { "TYPE_SOFTWARE", PERF_TYPE_SOFTWARE
},
780 { "TYPE_TRACEPOINT", PERF_TYPE_TRACEPOINT
},
781 { "TYPE_HW_CACHE", PERF_TYPE_HW_CACHE
},
782 { "TYPE_RAW", PERF_TYPE_RAW
},
783 { "TYPE_BREAKPOINT", PERF_TYPE_BREAKPOINT
},
785 { "COUNT_HW_CPU_CYCLES", PERF_COUNT_HW_CPU_CYCLES
},
786 { "COUNT_HW_INSTRUCTIONS", PERF_COUNT_HW_INSTRUCTIONS
},
787 { "COUNT_HW_CACHE_REFERENCES", PERF_COUNT_HW_CACHE_REFERENCES
},
788 { "COUNT_HW_CACHE_MISSES", PERF_COUNT_HW_CACHE_MISSES
},
789 { "COUNT_HW_BRANCH_INSTRUCTIONS", PERF_COUNT_HW_BRANCH_INSTRUCTIONS
},
790 { "COUNT_HW_BRANCH_MISSES", PERF_COUNT_HW_BRANCH_MISSES
},
791 { "COUNT_HW_BUS_CYCLES", PERF_COUNT_HW_BUS_CYCLES
},
792 { "COUNT_HW_CACHE_L1D", PERF_COUNT_HW_CACHE_L1D
},
793 { "COUNT_HW_CACHE_L1I", PERF_COUNT_HW_CACHE_L1I
},
794 { "COUNT_HW_CACHE_LL", PERF_COUNT_HW_CACHE_LL
},
795 { "COUNT_HW_CACHE_DTLB", PERF_COUNT_HW_CACHE_DTLB
},
796 { "COUNT_HW_CACHE_ITLB", PERF_COUNT_HW_CACHE_ITLB
},
797 { "COUNT_HW_CACHE_BPU", PERF_COUNT_HW_CACHE_BPU
},
798 { "COUNT_HW_CACHE_OP_READ", PERF_COUNT_HW_CACHE_OP_READ
},
799 { "COUNT_HW_CACHE_OP_WRITE", PERF_COUNT_HW_CACHE_OP_WRITE
},
800 { "COUNT_HW_CACHE_OP_PREFETCH", PERF_COUNT_HW_CACHE_OP_PREFETCH
},
801 { "COUNT_HW_CACHE_RESULT_ACCESS", PERF_COUNT_HW_CACHE_RESULT_ACCESS
},
802 { "COUNT_HW_CACHE_RESULT_MISS", PERF_COUNT_HW_CACHE_RESULT_MISS
},
804 { "COUNT_SW_CPU_CLOCK", PERF_COUNT_SW_CPU_CLOCK
},
805 { "COUNT_SW_TASK_CLOCK", PERF_COUNT_SW_TASK_CLOCK
},
806 { "COUNT_SW_PAGE_FAULTS", PERF_COUNT_SW_PAGE_FAULTS
},
807 { "COUNT_SW_CONTEXT_SWITCHES", PERF_COUNT_SW_CONTEXT_SWITCHES
},
808 { "COUNT_SW_CPU_MIGRATIONS", PERF_COUNT_SW_CPU_MIGRATIONS
},
809 { "COUNT_SW_PAGE_FAULTS_MIN", PERF_COUNT_SW_PAGE_FAULTS_MIN
},
810 { "COUNT_SW_PAGE_FAULTS_MAJ", PERF_COUNT_SW_PAGE_FAULTS_MAJ
},
811 { "COUNT_SW_ALIGNMENT_FAULTS", PERF_COUNT_SW_ALIGNMENT_FAULTS
},
812 { "COUNT_SW_EMULATION_FAULTS", PERF_COUNT_SW_EMULATION_FAULTS
},
814 { "SAMPLE_IP", PERF_SAMPLE_IP
},
815 { "SAMPLE_TID", PERF_SAMPLE_TID
},
816 { "SAMPLE_TIME", PERF_SAMPLE_TIME
},
817 { "SAMPLE_ADDR", PERF_SAMPLE_ADDR
},
818 { "SAMPLE_READ", PERF_SAMPLE_READ
},
819 { "SAMPLE_CALLCHAIN", PERF_SAMPLE_CALLCHAIN
},
820 { "SAMPLE_ID", PERF_SAMPLE_ID
},
821 { "SAMPLE_CPU", PERF_SAMPLE_CPU
},
822 { "SAMPLE_PERIOD", PERF_SAMPLE_PERIOD
},
823 { "SAMPLE_STREAM_ID", PERF_SAMPLE_STREAM_ID
},
824 { "SAMPLE_RAW", PERF_SAMPLE_RAW
},
826 { "FORMAT_TOTAL_TIME_ENABLED", PERF_FORMAT_TOTAL_TIME_ENABLED
},
827 { "FORMAT_TOTAL_TIME_RUNNING", PERF_FORMAT_TOTAL_TIME_RUNNING
},
828 { "FORMAT_ID", PERF_FORMAT_ID
},
829 { "FORMAT_GROUP", PERF_FORMAT_GROUP
},
831 { "RECORD_MMAP", PERF_RECORD_MMAP
},
832 { "RECORD_LOST", PERF_RECORD_LOST
},
833 { "RECORD_COMM", PERF_RECORD_COMM
},
834 { "RECORD_EXIT", PERF_RECORD_EXIT
},
835 { "RECORD_THROTTLE", PERF_RECORD_THROTTLE
},
836 { "RECORD_UNTHROTTLE", PERF_RECORD_UNTHROTTLE
},
837 { "RECORD_FORK", PERF_RECORD_FORK
},
838 { "RECORD_READ", PERF_RECORD_READ
},
839 { "RECORD_SAMPLE", PERF_RECORD_SAMPLE
},
843 static PyMethodDef perf__methods
[] = {
847 PyMODINIT_FUNC
initperf(void)
851 PyObject
*dict
, *module
= Py_InitModule("perf", perf__methods
);
853 if (module
== NULL
||
854 pyrf_event__setup_types() < 0 ||
855 pyrf_evlist__setup_types() < 0 ||
856 pyrf_evsel__setup_types() < 0 ||
857 pyrf_thread_map__setup_types() < 0 ||
858 pyrf_cpu_map__setup_types() < 0)
861 Py_INCREF(&pyrf_evlist__type
);
862 PyModule_AddObject(module
, "evlist", (PyObject
*)&pyrf_evlist__type
);
864 Py_INCREF(&pyrf_evsel__type
);
865 PyModule_AddObject(module
, "evsel", (PyObject
*)&pyrf_evsel__type
);
867 Py_INCREF(&pyrf_thread_map__type
);
868 PyModule_AddObject(module
, "thread_map", (PyObject
*)&pyrf_thread_map__type
);
870 Py_INCREF(&pyrf_cpu_map__type
);
871 PyModule_AddObject(module
, "cpu_map", (PyObject
*)&pyrf_cpu_map__type
);
873 dict
= PyModule_GetDict(module
);
877 for (i
= 0; perf__constants
[i
].name
!= NULL
; i
++) {
878 obj
= PyInt_FromLong(perf__constants
[i
].value
);
881 PyDict_SetItemString(dict
, perf__constants
[i
].name
, obj
);
886 if (PyErr_Occurred())
887 PyErr_SetString(PyExc_ImportError
, "perf: Init failed!");