1277 lines · 34.3 KB · C
RawDownload
#include <Python.h>#include <structmember.h>#include <inttypes.h>#include <poll.h>#include <linux/err.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, 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);	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 };

Lines 1–500 of 1277.