1073 lines · 29.6 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" /* * Support debug printing even though util/debug.c is not linked.  That means * implementing 'verbose' and 'eprintf'. */int verbose; int eprintf(int level, const char *fmt, ...){	va_list args;	int ret = 0; 	if (verbose >= 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_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 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 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,}; 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_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;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,}; 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 };	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", "uid", NULL };	int pid = -1, tid = -1, uid = UINT_MAX; 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",					 kwlist, &pid, &tid, &uid))		return -1; 	pthreads->threads = thread_map__new(pid, tid, uid);	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);} 

Lines 1–500 of 1073.