diff options
| author | Ingo Molnar <[email protected]> | 2018-03-09 08:27:55 +0100 | 
|---|---|---|
| committer | Ingo Molnar <[email protected]> | 2018-03-09 08:27:55 +0100 | 
| commit | fbf8a1e12c3ba3afdf0804bc80f5f13dfec1cffe (patch) | |
| tree | 6b0dd23c7646cd4ec13b0636cdda11188d6845a3 /tools/perf/builtin-sched.c | |
| parent | 1af22eba248efe2de25658041a80a3d40fb3e92e (diff) | |
| parent | 2427b432e63b4b911100f717c48289195b7a7d62 (diff) | |
Merge tag 'perf-core-for-mingo-4.17-20180308' 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:
- Support to display the IPC/Cycle in 'annotate' TUI, for systems
  where this info can be obtained, like Intel's >= Skylake (Jin Yao)
- Support wildcards on PMU name in dynamic PMU events (Agustin Vega-Frias)
- Display pmu name when printing unmerged events in stat (Agustin Vega-Frias)
- Auto-merge PMU events created by prefix or glob match (Agustin Vega-Frias)
- Fix s390 'call' operations target function annotation (Thomas Richter)
- Handle s390 PC relative load and store instruction in the augmented
  'annotate', code, used so far in the TUI modes of 'perf report' and
  'perf annotate' (Thomas Richter)
- Provide libtraceevent with a kernel symbol resolver, so that
  symbols in tracepoint fields can be resolved when showing them in
  tools such as 'perf report' (Wang YanQing)
- Refactor the cgroups code to look more like other code in tools/perf,
  using cgroup__{put,get} for refcount operations instead of its
  open-coded equivalent, breaking larger functions, etc (Arnaldo Carvalho de Melo)
- Implement support for the -G/--cgroup target in 'perf trace', allowing
  strace like tracing (plus other events, backtraces, etc) for cgroups
  (Arnaldo Carvalho de Melo)
- Update thread shortname in 'perf sched map' when the thread's COMM
  changes (Changbin Du)
- refcount 'struct mem_info', for better sharing it over several
  users, avoid duplicating structs and fixing crashes related to
  use after free (Jiri Olsa)
- Display perf.data version, offsets in 'perf report --header' (Jiri Olsa)
- Record the machine's memory topology information in a perf.data
  feature section, to be used by tools such as 'perf c2c' (Jiri Olsa)
- Fix output of forced groups in the header for 'perf report' --stdio
  and --tui (Jiri Olsa)
- Better support llvm, clang, cxx make tests in the build process (Jiri Olsa)
- Streamline the 'struct perf_mmap' methods, storing some info in the
  struct instead of passing it via various methods, shortening its
  signatures (Kan Liang)
- Update the quipper perf.data parser library site information (Stephane Eranian)
- Correct perf's man pages title markers for asciidoctor (Takashi Iwai)
- Intel PT fixes and refactorings paving the way for implementing
  support for AUX area sampling (Adrian Hunter)
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
Diffstat (limited to 'tools/perf/builtin-sched.c')
| -rw-r--r-- | tools/perf/builtin-sched.c | 133 | 
1 files changed, 91 insertions, 42 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 83283fedb00f..4dfdee668b0c 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c @@ -254,6 +254,10 @@ struct thread_runtime {  	u64 total_delay_time;  	int last_state; + +	char shortname[3]; +	bool comm_changed; +  	u64 migrations;  }; @@ -897,6 +901,37 @@ struct sort_dimension {  	struct list_head	list;  }; +/* + * handle runtime stats saved per thread + */ +static struct thread_runtime *thread__init_runtime(struct thread *thread) +{ +	struct thread_runtime *r; + +	r = zalloc(sizeof(struct thread_runtime)); +	if (!r) +		return NULL; + +	init_stats(&r->run_stats); +	thread__set_priv(thread, r); + +	return r; +} + +static struct thread_runtime *thread__get_runtime(struct thread *thread) +{ +	struct thread_runtime *tr; + +	tr = thread__priv(thread); +	if (tr == NULL) { +		tr = thread__init_runtime(thread); +		if (tr == NULL) +			pr_debug("Failed to malloc memory for runtime data.\n"); +	} + +	return tr; +} +  static int  thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)  { @@ -1480,6 +1515,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,  {  	const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");  	struct thread *sched_in; +	struct thread_runtime *tr;  	int new_shortname;  	u64 timestamp0, timestamp = sample->time;  	s64 delta; @@ -1519,22 +1555,28 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,  	if (sched_in == NULL)  		return -1; +	tr = thread__get_runtime(sched_in); +	if (tr == NULL) { +		thread__put(sched_in); +		return -1; +	} +  	sched->curr_thread[this_cpu] = thread__get(sched_in);  	printf("  ");  	new_shortname = 0; -	if (!sched_in->shortname[0]) { +	if (!tr->shortname[0]) {  		if (!strcmp(thread__comm_str(sched_in), "swapper")) {  			/*  			 * Don't allocate a letter-number for swapper:0  			 * as a shortname. Instead, we use '.' for it.  			 */ -			sched_in->shortname[0] = '.'; -			sched_in->shortname[1] = ' '; +			tr->shortname[0] = '.'; +			tr->shortname[1] = ' ';  		} else { -			sched_in->shortname[0] = sched->next_shortname1; -			sched_in->shortname[1] = sched->next_shortname2; +			tr->shortname[0] = sched->next_shortname1; +			tr->shortname[1] = sched->next_shortname2;  			if (sched->next_shortname1 < 'Z') {  				sched->next_shortname1++; @@ -1552,6 +1594,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,  	for (i = 0; i < cpus_nr; i++) {  		int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;  		struct thread *curr_thread = sched->curr_thread[cpu]; +		struct thread_runtime *curr_tr;  		const char *pid_color = color;  		const char *cpu_color = color; @@ -1569,9 +1612,14 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,  		else  			color_fprintf(stdout, cpu_color, "*"); -		if (sched->curr_thread[cpu]) -			color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname); -		else +		if (sched->curr_thread[cpu]) { +			curr_tr = thread__get_runtime(sched->curr_thread[cpu]); +			if (curr_tr == NULL) { +				thread__put(sched_in); +				return -1; +			} +			color_fprintf(stdout, pid_color, "%2s ", curr_tr->shortname); +		} else  			color_fprintf(stdout, color, "   ");  	} @@ -1580,14 +1628,15 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,  	timestamp__scnprintf_usec(timestamp, stimestamp, sizeof(stimestamp));  	color_fprintf(stdout, color, "  %12s secs ", stimestamp); -	if (new_shortname || (verbose > 0 && sched_in->tid)) { +	if (new_shortname || tr->comm_changed || (verbose > 0 && sched_in->tid)) {  		const char *pid_color = color;  		if (thread__has_color(sched_in))  			pid_color = COLOR_PIDS;  		color_fprintf(stdout, pid_color, "%s => %s:%d", -		       sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); +		       tr->shortname, thread__comm_str(sched_in), sched_in->tid); +		tr->comm_changed = false;  	}  	if (sched->map.comp && new_cpu) @@ -1691,6 +1740,37 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_  	return err;  } +static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused, +				    union perf_event *event, +				    struct perf_sample *sample, +				    struct machine *machine) +{ +	struct thread *thread; +	struct thread_runtime *tr; +	int err; + +	err = perf_event__process_comm(tool, event, sample, machine); +	if (err) +		return err; + +	thread = machine__find_thread(machine, sample->pid, sample->tid); +	if (!thread) { +		pr_err("Internal error: can't find thread\n"); +		return -1; +	} + +	tr = thread__get_runtime(thread); +	if (tr == NULL) { +		thread__put(thread); +		return -1; +	} + +	tr->comm_changed = true; +	thread__put(thread); + +	return 0; +} +  static int perf_sched__read_events(struct perf_sched *sched)  {  	const struct perf_evsel_str_handler handlers[] = { @@ -2200,37 +2280,6 @@ static void save_idle_callchain(struct idle_thread_runtime *itr,  	callchain_cursor__copy(&itr->cursor, &callchain_cursor);  } -/* - * handle runtime stats saved per thread - */ -static struct thread_runtime *thread__init_runtime(struct thread *thread) -{ -	struct thread_runtime *r; - -	r = zalloc(sizeof(struct thread_runtime)); -	if (!r) -		return NULL; - -	init_stats(&r->run_stats); -	thread__set_priv(thread, r); - -	return r; -} - -static struct thread_runtime *thread__get_runtime(struct thread *thread) -{ -	struct thread_runtime *tr; - -	tr = thread__priv(thread); -	if (tr == NULL) { -		tr = thread__init_runtime(thread); -		if (tr == NULL) -			pr_debug("Failed to malloc memory for runtime data.\n"); -	} - -	return tr; -} -  static struct thread *timehist_get_thread(struct perf_sched *sched,  					  struct perf_sample *sample,  					  struct machine *machine, @@ -3291,7 +3340,7 @@ int cmd_sched(int argc, const char **argv)  	struct perf_sched sched = {  		.tool = {  			.sample		 = perf_sched__process_tracepoint_sample, -			.comm		 = perf_event__process_comm, +			.comm		 = perf_sched__process_comm,  			.namespaces	 = perf_event__process_namespaces,  			.lost		 = perf_event__process_lost,  			.fork		 = perf_sched__process_fork_event,  |