diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
| -rw-r--r-- | tools/perf/builtin-stat.c | 76 | 
1 files changed, 55 insertions, 21 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index a96f106dc93a..4ce87a8eb7d7 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -216,6 +216,7 @@ static struct perf_stat_config stat_config = {  	.run_count		= 1,  	.metric_only_len	= METRIC_ONLY_LEN,  	.walltime_nsecs_stats	= &walltime_nsecs_stats, +	.ru_stats		= &ru_stats,  	.big_num		= true,  	.ctl_fd			= -1,  	.ctl_fd_ack		= -1, @@ -271,11 +272,8 @@ static void evlist__check_cpu_maps(struct evlist *evlist)  			pr_warning("     %s: %s\n", evsel->name, buf);  		} -		for_each_group_evsel(pos, leader) { -			evsel__set_leader(pos, pos); -			pos->core.nr_members = 0; -		} -		evsel->core.leader->nr_members = 0; +		for_each_group_evsel(pos, leader) +			evsel__remove_from_group(pos, leader);  	}  } @@ -341,15 +339,35 @@ static int evsel__write_stat_event(struct evsel *counter, int cpu_map_idx, u32 t  static int read_single_counter(struct evsel *counter, int cpu_map_idx,  			       int thread, struct timespec *rs)  { -	if (counter->tool_event == PERF_TOOL_DURATION_TIME) { -		u64 val = rs->tv_nsec + rs->tv_sec*1000000000ULL; -		struct perf_counts_values *count = -			perf_counts(counter->counts, cpu_map_idx, thread); -		count->ena = count->run = val; -		count->val = val; -		return 0; +	switch(counter->tool_event) { +		case PERF_TOOL_DURATION_TIME: { +			u64 val = rs->tv_nsec + rs->tv_sec*1000000000ULL; +			struct perf_counts_values *count = +				perf_counts(counter->counts, cpu_map_idx, thread); +			count->ena = count->run = val; +			count->val = val; +			return 0; +		} +		case PERF_TOOL_USER_TIME: +		case PERF_TOOL_SYSTEM_TIME: { +			u64 val; +			struct perf_counts_values *count = +				perf_counts(counter->counts, cpu_map_idx, thread); +			if (counter->tool_event == PERF_TOOL_USER_TIME) +				val = ru_stats.ru_utime_usec_stat.mean; +			else +				val = ru_stats.ru_stime_usec_stat.mean; +			count->ena = count->run = val; +			count->val = val; +			return 0; +		} +		default: +		case PERF_TOOL_NONE: +			return evsel__read_counter(counter, cpu_map_idx, thread); +		case PERF_TOOL_MAX: +			/* This should never be reached */ +			return 0;  	} -	return evsel__read_counter(counter, cpu_map_idx, thread);  }  /* @@ -364,9 +382,6 @@ static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu_  	if (!counter->supported)  		return -ENOENT; -	if (counter->core.system_wide) -		nthreads = 1; -  	for (thread = 0; thread < nthreads; thread++) {  		struct perf_counts_values *count; @@ -1010,8 +1025,10 @@ try_again_reset:  		evlist__reset_prev_raw_counts(evsel_list);  		runtime_stat_reset(&stat_config);  		perf_stat__reset_shadow_per_stat(&rt_stat); -	} else +	} else {  		update_stats(&walltime_nsecs_stats, t1 - t0); +		update_rusage_stats(&ru_stats, &stat_config.ru_data); +	}  	/*  	 * Closing a group leader splits the group, and as we only disable @@ -1235,6 +1252,8 @@ static struct option stat_options[] = {  	OPT_SET_UINT('A', "no-aggr", &stat_config.aggr_mode,  		    "disable CPU count aggregation", AGGR_NONE),  	OPT_BOOLEAN(0, "no-merge", &stat_config.no_merge, "Do not merge identical named events"), +	OPT_BOOLEAN(0, "hybrid-merge", &stat_config.hybrid_merge, +		    "Merge identical named hybrid events"),  	OPT_STRING('x', "field-separator", &stat_config.csv_sep, "separator",  		   "print counts with custom separator"),  	OPT_CALLBACK('G', "cgroup", &evsel_list, "name", @@ -1842,11 +1861,23 @@ static int add_default_attributes(void)  		unsigned int max_level = 1;  		char *str = NULL;  		bool warn = false; +		const char *pmu_name = "cpu";  		if (!force_metric_only)  			stat_config.metric_only = true; -		if (pmu_have_event("cpu", topdown_metric_L2_attrs[5])) { +		if (perf_pmu__has_hybrid()) { +			if (!evsel_list->hybrid_pmu_name) { +				pr_warning("WARNING: default to use cpu_core topdown events\n"); +				evsel_list->hybrid_pmu_name = perf_pmu__hybrid_type_to_pmu("core"); +			} + +			pmu_name = evsel_list->hybrid_pmu_name; +			if (!pmu_name) +				return -1; +		} + +		if (pmu_have_event(pmu_name, topdown_metric_L2_attrs[5])) {  			metric_attrs = topdown_metric_L2_attrs;  			max_level = 2;  		} @@ -1857,10 +1888,11 @@ static int add_default_attributes(void)  		} else if (!stat_config.topdown_level)  			stat_config.topdown_level = max_level; -		if (topdown_filter_events(metric_attrs, &str, 1) < 0) { +		if (topdown_filter_events(metric_attrs, &str, 1, pmu_name) < 0) {  			pr_err("Out of memory\n");  			return -1;  		} +  		if (metric_attrs[0] && str) {  			if (!stat_config.interval && !stat_config.metric_only) {  				fprintf(stat_config.output, @@ -1884,10 +1916,12 @@ static int add_default_attributes(void)  		}  		if (topdown_filter_events(topdown_attrs, &str, -				arch_topdown_check_group(&warn)) < 0) { +				arch_topdown_check_group(&warn), +				pmu_name) < 0) {  			pr_err("Out of memory\n");  			return -1;  		} +  		if (topdown_attrs[0] && str) {  			struct parse_events_error errinfo;  			if (warn) @@ -2224,7 +2258,7 @@ static void setup_system_wide(int forks)  		struct evsel *counter;  		evlist__for_each_entry(evsel_list, counter) { -			if (!counter->core.system_wide && +			if (!counter->core.requires_cpu &&  			    strcmp(counter->name, "duration_time")) {  				return;  			}  | 
