diff options
| author | Ingo Molnar <mingo@kernel.org> | 2015-10-08 11:52:44 +0300 | 
|---|---|---|
| committer | Ingo Molnar <mingo@kernel.org> | 2015-10-08 11:52:44 +0300 | 
| commit | 0e537fef24d64f7bf3ef61a27edf64a8d9a5424c (patch) | |
| tree | 0f095cadf2c3c7748eaec769e19978abe11d1b3f | |
| parent | d3df65c198dc2f1deefb73c8427b04d1bdd1b18d (diff) | |
| parent | ae938802443732e77d01f8d5b52b900b9327ff30 (diff) | |
| download | linux-0e537fef24d64f7bf3ef61a27edf64a8d9a5424c.tar.xz | |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:
User visible changes:
  - Adding a field via 'perf report -F' that already is enabled makes
    the tool get stuck in a loop, fix it. (Jiri Olsa)
Infrastructure changes:
  - Support PERF_RECORD_SWITCH in the python binding. (Arnaldo Carvalho de Melo)
  - Fix handling read() result using a signed variable, found with Coccinelle.
    (Andrzej Hajda)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
| -rwxr-xr-x | tools/perf/python/twatch.py | 23 | ||||
| -rw-r--r-- | tools/perf/ui/hist.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/event.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/python.c | 59 | ||||
| -rw-r--r-- | tools/perf/util/sort.c | 8 | ||||
| -rw-r--r-- | tools/perf/util/sort.h | 2 | 
6 files changed, 93 insertions, 18 deletions
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py index b9d508336ae6..c235c22b107a 100755 --- a/tools/perf/python/twatch.py +++ b/tools/perf/python/twatch.py @@ -15,14 +15,14 @@  import perf -def main(): +def main(context_switch = 0, thread = -1):  	cpus = perf.cpu_map() -	threads = perf.thread_map() +	threads = perf.thread_map(thread)  	evsel = perf.evsel(type	  = perf.TYPE_SOFTWARE,  			   config = perf.COUNT_SW_DUMMY,  			   task = 1, comm = 1, mmap = 0, freq = 0,  			   wakeup_events = 1, watermark = 1, -			   sample_id_all = 1, +			   sample_id_all = 1, context_switch = context_switch,  			   sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU)  	"""What we want are just the PERF_RECORD_ lifetime events for threads, @@ -48,4 +48,21 @@ def main():  			print event  if __name__ == '__main__': +    """ +	To test the PERF_RECORD_SWITCH record, pick a pid and replace +	in the following line. + +	Example output: + +cpu: 3, pid: 31463, tid: 31593 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31593, switch_out: 1 } +cpu: 1, pid: 31463, tid: 31489 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31489, switch_out: 1 } +cpu: 2, pid: 31463, tid: 31496 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31496, switch_out: 1 } +cpu: 3, pid: 31463, tid: 31491 { type: context_switch, next_prev_pid: 31463, next_prev_tid: 31491, switch_out: 0 } + +	It is possible as well to use event.misc & perf.PERF_RECORD_MISC_SWITCH_OUT +	to figure out if this is a context switch in or out of the monitored threads. + +	If bored, please add command line option parsing support for these options :-) +    """ +    # main(context_switch = 1, thread = 31463)      main() diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 25d608394d74..5029ba2b55af 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -463,27 +463,27 @@ void perf_hpp__init(void)  		return;  	if (symbol_conf.cumulate_callchain) { -		perf_hpp__column_enable(PERF_HPP__OVERHEAD_ACC); +		hpp_dimension__add_output(PERF_HPP__OVERHEAD_ACC);  		perf_hpp__format[PERF_HPP__OVERHEAD].name = "Self";  	} -	perf_hpp__column_enable(PERF_HPP__OVERHEAD); +	hpp_dimension__add_output(PERF_HPP__OVERHEAD);  	if (symbol_conf.show_cpu_utilization) { -		perf_hpp__column_enable(PERF_HPP__OVERHEAD_SYS); -		perf_hpp__column_enable(PERF_HPP__OVERHEAD_US); +		hpp_dimension__add_output(PERF_HPP__OVERHEAD_SYS); +		hpp_dimension__add_output(PERF_HPP__OVERHEAD_US);  		if (perf_guest) { -			perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_SYS); -			perf_hpp__column_enable(PERF_HPP__OVERHEAD_GUEST_US); +			hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_SYS); +			hpp_dimension__add_output(PERF_HPP__OVERHEAD_GUEST_US);  		}  	}  	if (symbol_conf.show_nr_samples) -		perf_hpp__column_enable(PERF_HPP__SAMPLES); +		hpp_dimension__add_output(PERF_HPP__SAMPLES);  	if (symbol_conf.show_total_period) -		perf_hpp__column_enable(PERF_HPP__PERIOD); +		hpp_dimension__add_output(PERF_HPP__PERIOD);  	/* prepend overhead field for backward compatiblity.  */  	list = &perf_hpp__format[PERF_HPP__OVERHEAD].sort_list; diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index cb98b5af9e17..8b10621b415c 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -67,7 +67,8 @@ static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,  	char filename[PATH_MAX];  	char bf[4096];  	int fd; -	size_t size = 0, n; +	size_t size = 0; +	ssize_t n;  	char *nl, *name, *tgids, *ppids;  	*tgid = -1; diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index 6324fe6b161e..98f127abfa42 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c @@ -67,6 +67,7 @@ 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"), @@ -297,6 +298,43 @@ static PyTypeObject pyrf_sample_event__type = {  	.tp_repr	= (reprfunc)pyrf_sample_event__repr,  }; +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; @@ -306,6 +344,7 @@ static int pyrf_event__setup_types(void)  	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) @@ -328,6 +367,9 @@ static int pyrf_event__setup_types(void)  	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;  } @@ -342,6 +384,8 @@ static PyTypeObject *pyrf_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) @@ -349,8 +393,10 @@ 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) +	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]; @@ -528,6 +574,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,  		"exclude_hv",  		"exclude_idle",  		"mmap", +		"context_switch",  		"comm",  		"freq",  		"inherit_stat", @@ -553,6 +600,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,  	    exclude_hv = 0,  	    exclude_idle = 0,  	    mmap = 0, +	    context_switch = 0,  	    comm = 0,  	    freq = 1,  	    inherit_stat = 0, @@ -565,13 +613,13 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,  	int idx = 0;  	if (!PyArg_ParseTupleAndKeywords(args, kwargs, -					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiKK", kwlist, +					 "|iKiKKiiiiiiiiiiiiiiiiiiiiiiKK", 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, +					 &mmap, &context_switch, &comm, &freq, &inherit_stat,  					 &enable_on_exec, &task, &watermark,  					 &precise_ip, &mmap_data, &sample_id_all,  					 &attr.wakeup_events, &attr.bp_type, @@ -595,6 +643,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,  	attr.exclude_hv	    = exclude_hv;  	attr.exclude_idle   = exclude_idle;  	attr.mmap	    = mmap; +	attr.context_switch = context_switch;  	attr.comm	    = comm;  	attr.freq	    = freq;  	attr.inherit_stat   = inherit_stat; @@ -1019,6 +1068,8 @@ static struct {  	PERF_CONST(RECORD_LOST_SAMPLES),  	PERF_CONST(RECORD_SWITCH),  	PERF_CONST(RECORD_SWITCH_CPU_WIDE), + +	PERF_CONST(RECORD_MISC_SWITCH_OUT),  	{ .name = NULL, },  }; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index ee94b728fca4..2d8ccd4d9e1b 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1577,6 +1577,12 @@ static int __hpp_dimension__add_output(struct hpp_dimension *hd)  	return 0;  } +int hpp_dimension__add_output(unsigned col) +{ +	BUG_ON(col >= PERF_HPP__MAX_INDEX); +	return __hpp_dimension__add_output(&hpp_sort_dimensions[col]); +} +  int sort_dimension__add(const char *tok)  {  	unsigned int i; @@ -1917,8 +1923,6 @@ static int __setup_output_field(void)  	if (field_order == NULL)  		return 0; -	reset_dimensions(); -  	strp = str = strdup(field_order);  	if (str == NULL) {  		error("Not enough memory to setup output fields"); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 33b3d30e18d3..31228851e397 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -234,4 +234,6 @@ void perf_hpp__set_elide(int idx, bool elide);  int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, int unset);  bool is_strict_order(const char *order); + +int hpp_dimension__add_output(unsigned col);  #endif	/* __PERF_SORT_H */  | 
