905 lines · 25.4 KB · C
RawDownload
#include <Python.h>#include <structmember.h>#include <inttypes.h>#include <poll.h>#include "evlist.h"#include "evsel.h"#include "event.h"#include "cpumap.h"#include "thread_map.h" /* Define PyVarObject_HEAD_INIT for python 2.5 */#ifndef PyVarObject_HEAD_INIT# define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,#endif struct throttle_event {	struct perf_event_header header;	u64			 time;	u64			 id;	u64			 stream_id;}; 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_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(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 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_throttle_event__type.tp_new = PyType_GenericNew;	err = PyType_Ready(&pyrf_mmap_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;out:	return err;} static PyTypeObject *pyrf_event__type[] = {	[PERF_RECORD_MMAP]	 = &pyrf_mmap_event__type,	[PERF_RECORD_LOST]	 = &pyrf_mmap_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_mmap_event__type,	[PERF_RECORD_SAMPLE]	 = &pyrf_mmap_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)		return NULL; 	ptype = pyrf_event__type[event->header.type];	pevent = PyObject_New(struct pyrf_event, ptype);	if (pevent != NULL)		memcpy(&pevent->event, event, event->header.size);	return (PyObject *)pevent;} struct pyrf_cpu_map {	PyObject_HEAD 	struct cpu_map *cpus;}; static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,			      PyObject *args, PyObject *kwargs){	static char *kwlist[] = { "cpustr", NULL, NULL, };	char *cpustr = NULL; 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",					 kwlist, &cpustr))		return -1; 	pcpus->cpus = cpu_map__new(cpustr);	if (pcpus->cpus == NULL)		return -1;	return 0;} static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus){	cpu_map__delete(pcpus->cpus);	pcpus->ob_type->tp_free((PyObject*)pcpus);} static Py_ssize_t pyrf_cpu_map__length(PyObject *obj){	struct pyrf_cpu_map *pcpus = (void *)obj; 	return pcpus->cpus->nr;} static PyObject *pyrf_cpu_map__item(PyObject *obj, Py_ssize_t i){	struct pyrf_cpu_map *pcpus = (void *)obj; 	if (i >= pcpus->cpus->nr)		return NULL; 	return Py_BuildValue("i", pcpus->cpus->map[i]);} static PySequenceMethods pyrf_cpu_map__sequence_methods = {	.sq_length = pyrf_cpu_map__length,	.sq_item   = pyrf_cpu_map__item,}; static char pyrf_cpu_map__doc[] = PyDoc_STR("cpu map object."); static PyTypeObject pyrf_cpu_map__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.cpu_map",	.tp_basicsize	= sizeof(struct pyrf_cpu_map),	.tp_dealloc	= (destructor)pyrf_cpu_map__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_cpu_map__doc,	.tp_as_sequence	= &pyrf_cpu_map__sequence_methods,	.tp_init	= (initproc)pyrf_cpu_map__init,}; static int pyrf_cpu_map__setup_types(void){	pyrf_cpu_map__type.tp_new = PyType_GenericNew;	return PyType_Ready(&pyrf_cpu_map__type);} struct pyrf_thread_map {	PyObject_HEAD 	struct thread_map *threads;}; static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,				 PyObject *args, PyObject *kwargs){	static char *kwlist[] = { "pid", "tid", NULL, NULL, };	int pid = -1, tid = -1; 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",					 kwlist, &pid, &tid))		return -1; 	pthreads->threads = thread_map__new(pid, tid);	if (pthreads->threads == NULL)		return -1;	return 0;} static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads){	thread_map__delete(pthreads->threads);	pthreads->ob_type->tp_free((PyObject*)pthreads);} static Py_ssize_t pyrf_thread_map__length(PyObject *obj){	struct pyrf_thread_map *pthreads = (void *)obj; 	return pthreads->threads->nr;} static PyObject *pyrf_thread_map__item(PyObject *obj, Py_ssize_t i){	struct pyrf_thread_map *pthreads = (void *)obj; 	if (i >= pthreads->threads->nr)		return NULL; 	return Py_BuildValue("i", pthreads->threads->map[i]);} static PySequenceMethods pyrf_thread_map__sequence_methods = {	.sq_length = pyrf_thread_map__length,	.sq_item   = pyrf_thread_map__item,}; static char pyrf_thread_map__doc[] = PyDoc_STR("thread map object."); static PyTypeObject pyrf_thread_map__type = {	PyVarObject_HEAD_INIT(NULL, 0)	.tp_name	= "perf.thread_map",	.tp_basicsize	= sizeof(struct pyrf_thread_map),	.tp_dealloc	= (destructor)pyrf_thread_map__delete,	.tp_flags	= Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,	.tp_doc		= pyrf_thread_map__doc,	.tp_as_sequence	= &pyrf_thread_map__sequence_methods,	.tp_init	= (initproc)pyrf_thread_map__init,}; static int pyrf_thread_map__setup_types(void){	pyrf_thread_map__type.tp_new = PyType_GenericNew;	return PyType_Ready(&pyrf_thread_map__type);} struct pyrf_evsel {	PyObject_HEAD 	struct perf_evsel evsel;}; static int pyrf_evsel__init(struct pyrf_evsel *pevsel,			    PyObject *args, PyObject *kwargs){	struct perf_event_attr attr = {		.type = PERF_TYPE_HARDWARE,		.config = PERF_COUNT_HW_CPU_CYCLES,		.sample_type = PERF_SAMPLE_PERIOD | PERF_SAMPLE_TID,	};	static char *kwlist[] = {		"type",		"config",		"sample_freq",		"sample_period",		"sample_type",		"read_format",		"disabled",		"inherit",		"pinned",		"exclusive",		"exclude_user",		"exclude_kernel",		"exclude_hv",		"exclude_idle",		"mmap",		"comm",		"freq",		"inherit_stat",		"enable_on_exec",		"task",		"watermark",		"precise_ip",		"mmap_data",		"sample_id_all",		"wakeup_events",		"bp_type",		"bp_addr",		"bp_len", NULL, NULL, };	u64 sample_period = 0;	u32 disabled = 0,	    inherit = 0,	    pinned = 0,	    exclusive = 0,	    exclude_user = 0,	    exclude_kernel = 0,	    exclude_hv = 0,	    exclude_idle = 0,	    mmap = 0,	    comm = 0,	    freq = 1,	    inherit_stat = 0,	    enable_on_exec = 0,	    task = 0,	    watermark = 0,	    precise_ip = 0,	    mmap_data = 0,	    sample_id_all = 1;	int idx = 0; 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist,					 &attr.type, &attr.config, &attr.sample_freq,					 &sample_period, &attr.sample_type,					 &attr.read_format, &disabled, &inherit,					 &pinned, &exclusive, &exclude_user,					 &exclude_kernel, &exclude_hv, &exclude_idle,					 &mmap, &comm, &freq, &inherit_stat,					 &enable_on_exec, &task, &watermark,					 &precise_ip, &mmap_data, &sample_id_all,					 &attr.wakeup_events, &attr.bp_type,					 &attr.bp_addr, &attr.bp_len, &idx))		return -1; 	/* union... */	if (sample_period != 0) {		if (attr.sample_freq != 0)			return -1; /* FIXME: throw right exception */		attr.sample_period = sample_period;	} 	/* Bitfields */	attr.disabled	    = disabled;	attr.inherit	    = inherit;	attr.pinned	    = pinned;	attr.exclusive	    = exclusive;	attr.exclude_user   = exclude_user;	attr.exclude_kernel = exclude_kernel;	attr.exclude_hv	    = exclude_hv;	attr.exclude_idle   = exclude_idle;	attr.mmap	    = mmap;	attr.comm	    = comm;	attr.freq	    = freq;	attr.inherit_stat   = inherit_stat;	attr.enable_on_exec = enable_on_exec;	attr.task	    = task;	attr.watermark	    = watermark;	attr.precise_ip	    = precise_ip;	attr.mmap_data	    = mmap_data;	attr.sample_id_all  = sample_id_all; 	perf_evsel__init(&pevsel->evsel, &attr, idx);	return 0;} static void pyrf_evsel__delete(struct pyrf_evsel *pevsel){	perf_evsel__exit(&pevsel->evsel);	pevsel->ob_type->tp_free((PyObject*)pevsel);} static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,				  PyObject *args, PyObject *kwargs){	struct perf_evsel *evsel = &pevsel->evsel;	struct cpu_map *cpus = NULL;	struct thread_map *threads = NULL;	PyObject *pcpus = NULL, *pthreads = NULL;

Lines 1–500 of 905.