diff options
Diffstat (limited to 'tools/perf/builtin-stat.c')
| -rw-r--r-- | tools/perf/builtin-stat.c | 173 | 
1 files changed, 93 insertions, 80 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index b01af171d94f..8cc24967bc27 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -270,7 +270,7 @@ static void perf_stat__reset_stats(void)  {  	int i; -	perf_evlist__reset_stats(evsel_list); +	evlist__reset_stats(evsel_list);  	perf_stat__reset_shadow_stats();  	for (i = 0; i < stat_config.stats_num; i++) @@ -534,7 +534,7 @@ static void disable_counters(void)  static volatile int workload_exec_errno;  /* - * perf_evlist__prepare_workload will send a SIGUSR1 + * evlist__prepare_workload will send a SIGUSR1   * if the fork fails, since we asked by setting its   * want_signal to true.   */ @@ -724,8 +724,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)  	bool second_pass = false;  	if (forks) { -		if (perf_evlist__prepare_workload(evsel_list, &target, argv, is_pipe, -						  workload_exec_failed_signal) < 0) { +		if (evlist__prepare_workload(evsel_list, &target, argv, is_pipe, workload_exec_failed_signal) < 0) {  			perror("failed to prepare workload");  			return -1;  		} @@ -733,7 +732,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)  	}  	if (group) -		perf_evlist__set_leader(evsel_list); +		evlist__set_leader(evsel_list);  	if (affinity__setup(&affinity) < 0)  		return -1; @@ -760,7 +759,7 @@ try_again:  				if ((errno == EINVAL || errno == EBADF) &&  				    counter->leader != counter &&  				    counter->weak_group) { -					perf_evlist__reset_weak_group(evsel_list, counter, false); +					evlist__reset_weak_group(evsel_list, counter, false);  					assert(counter->reset_group);  					second_pass = true;  					continue; @@ -843,7 +842,7 @@ try_again_reset:  			return -1;  	} -	if (perf_evlist__apply_filters(evsel_list, &counter)) { +	if (evlist__apply_filters(evsel_list, &counter)) {  		pr_err("failed to set filter \"%s\" on event %s with %d (%s)\n",  			counter->filter, evsel__name(counter), errno,  			str_error_r(errno, msg, sizeof(msg))); @@ -876,7 +875,7 @@ try_again_reset:  	clock_gettime(CLOCK_MONOTONIC, &ref_time);  	if (forks) { -		perf_evlist__start_workload(evsel_list); +		evlist__start_workload(evsel_list);  		enable_counters();  		if (interval || timeout || evlist__ctlfd_initialized(evsel_list)) @@ -914,10 +913,10 @@ try_again_reset:  		update_stats(&walltime_nsecs_stats, t1 - t0);  		if (stat_config.aggr_mode == AGGR_GLOBAL) -			perf_evlist__save_aggr_prev_raw_counts(evsel_list); +			evlist__save_aggr_prev_raw_counts(evsel_list); -		perf_evlist__copy_prev_raw_counts(evsel_list); -		perf_evlist__reset_prev_raw_counts(evsel_list); +		evlist__copy_prev_raw_counts(evsel_list); +		evlist__reset_prev_raw_counts(evsel_list);  		runtime_stat_reset(&stat_config);  		perf_stat__reset_shadow_per_stat(&rt_stat);  	} else @@ -972,9 +971,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)  	/* Do not print anything if we record to the pipe. */  	if (STAT_RECORD && perf_stat.data.is_pipe)  		return; +	if (stat_config.quiet) +		return; -	perf_evlist__print_counters(evsel_list, &stat_config, &target, -				    ts, argc, argv); +	evlist__print_counters(evsel_list, &stat_config, &target, ts, argc, argv);  }  static volatile int signr = -1; @@ -1171,6 +1171,8 @@ static struct option stat_options[] = {  		    "threads of same physical core"),  	OPT_BOOLEAN(0, "summary", &stat_config.summary,  		       "print summary for interval mode"), +	OPT_BOOLEAN(0, "quiet", &stat_config.quiet, +			"don't print output (useful with record)"),  #ifdef HAVE_LIBPFM  	OPT_CALLBACK(0, "pfm-events", &evsel_list, "event",  		"libpfm4 event selector. use 'perf list' to list available events", @@ -1184,65 +1186,67 @@ static struct option stat_options[] = {  	OPT_END()  }; -static int perf_stat__get_socket(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_socket(struct perf_stat_config *config __maybe_unused,  				 struct perf_cpu_map *map, int cpu)  {  	return cpu_map__get_socket(map, cpu, NULL);  } -static int perf_stat__get_die(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_die(struct perf_stat_config *config __maybe_unused,  			      struct perf_cpu_map *map, int cpu)  {  	return cpu_map__get_die(map, cpu, NULL);  } -static int perf_stat__get_core(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_core(struct perf_stat_config *config __maybe_unused,  			       struct perf_cpu_map *map, int cpu)  {  	return cpu_map__get_core(map, cpu, NULL);  } -static int perf_stat__get_node(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_node(struct perf_stat_config *config __maybe_unused,  			       struct perf_cpu_map *map, int cpu)  {  	return cpu_map__get_node(map, cpu, NULL);  } -static int perf_stat__get_aggr(struct perf_stat_config *config, +static struct aggr_cpu_id perf_stat__get_aggr(struct perf_stat_config *config,  			       aggr_get_id_t get_id, struct perf_cpu_map *map, int idx)  {  	int cpu; +	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id();  	if (idx >= map->nr) -		return -1; +		return id;  	cpu = map->map[idx]; -	if (config->cpus_aggr_map->map[cpu] == -1) +	if (cpu_map__aggr_cpu_id_is_empty(config->cpus_aggr_map->map[cpu]))  		config->cpus_aggr_map->map[cpu] = get_id(config, map, idx); -	return config->cpus_aggr_map->map[cpu]; +	id = config->cpus_aggr_map->map[cpu]; +	return id;  } -static int perf_stat__get_socket_cached(struct perf_stat_config *config, +static struct aggr_cpu_id perf_stat__get_socket_cached(struct perf_stat_config *config,  					struct perf_cpu_map *map, int idx)  {  	return perf_stat__get_aggr(config, perf_stat__get_socket, map, idx);  } -static int perf_stat__get_die_cached(struct perf_stat_config *config, +static struct aggr_cpu_id perf_stat__get_die_cached(struct perf_stat_config *config,  					struct perf_cpu_map *map, int idx)  {  	return perf_stat__get_aggr(config, perf_stat__get_die, map, idx);  } -static int perf_stat__get_core_cached(struct perf_stat_config *config, +static struct aggr_cpu_id perf_stat__get_core_cached(struct perf_stat_config *config,  				      struct perf_cpu_map *map, int idx)  {  	return perf_stat__get_aggr(config, perf_stat__get_core, map, idx);  } -static int perf_stat__get_node_cached(struct perf_stat_config *config, +static struct aggr_cpu_id perf_stat__get_node_cached(struct perf_stat_config *config,  				      struct perf_cpu_map *map, int idx)  {  	return perf_stat__get_aggr(config, perf_stat__get_node, map, idx); @@ -1316,14 +1320,29 @@ static int perf_stat_init_aggr_mode(void)  	 * the aggregation translate cpumap.  	 */  	nr = perf_cpu_map__max(evsel_list->core.cpus); -	stat_config.cpus_aggr_map = perf_cpu_map__empty_new(nr + 1); +	stat_config.cpus_aggr_map = cpu_aggr_map__empty_new(nr + 1);  	return stat_config.cpus_aggr_map ? 0 : -ENOMEM;  } +static void cpu_aggr_map__delete(struct cpu_aggr_map *map) +{ +	if (map) { +		WARN_ONCE(refcount_read(&map->refcnt) != 0, +			  "cpu_aggr_map refcnt unbalanced\n"); +		free(map); +	} +} + +static void cpu_aggr_map__put(struct cpu_aggr_map *map) +{ +	if (map && refcount_dec_and_test(&map->refcnt)) +		cpu_aggr_map__delete(map); +} +  static void perf_stat__exit_aggr_mode(void)  { -	perf_cpu_map__put(stat_config.aggr_map); -	perf_cpu_map__put(stat_config.cpus_aggr_map); +	cpu_aggr_map__put(stat_config.aggr_map); +	cpu_aggr_map__put(stat_config.cpus_aggr_map);  	stat_config.aggr_map = NULL;  	stat_config.cpus_aggr_map = NULL;  } @@ -1343,117 +1362,108 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct perf_cpu_map *m  	return cpu;  } -static int perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data) +static struct aggr_cpu_id perf_env__get_socket(struct perf_cpu_map *map, int idx, void *data)  {  	struct perf_env *env = data;  	int cpu = perf_env__get_cpu(env, map, idx); +	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id(); -	return cpu == -1 ? -1 : env->cpu[cpu].socket_id; +	if (cpu != -1) +		id.socket = env->cpu[cpu].socket_id; + +	return id;  } -static int perf_env__get_die(struct perf_cpu_map *map, int idx, void *data) +static struct aggr_cpu_id perf_env__get_die(struct perf_cpu_map *map, int idx, void *data)  {  	struct perf_env *env = data; -	int die_id = -1, cpu = perf_env__get_cpu(env, map, idx); +	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id(); +	int cpu = perf_env__get_cpu(env, map, idx);  	if (cpu != -1) {  		/* -		 * Encode socket in bit range 15:8 -		 * die_id is relative to socket, -		 * we need a global id. So we combine -		 * socket + die id +		 * die_id is relative to socket, so start +		 * with the socket ID and then add die to +		 * make a unique ID.  		 */ -		if (WARN_ONCE(env->cpu[cpu].socket_id >> 8, "The socket id number is too big.\n")) -			return -1; - -		if (WARN_ONCE(env->cpu[cpu].die_id >> 8, "The die id number is too big.\n")) -			return -1; - -		die_id = (env->cpu[cpu].socket_id << 8) | (env->cpu[cpu].die_id & 0xff); +		id.socket = env->cpu[cpu].socket_id; +		id.die = env->cpu[cpu].die_id;  	} -	return die_id; +	return id;  } -static int perf_env__get_core(struct perf_cpu_map *map, int idx, void *data) +static struct aggr_cpu_id perf_env__get_core(struct perf_cpu_map *map, int idx, void *data)  {  	struct perf_env *env = data; -	int core = -1, cpu = perf_env__get_cpu(env, map, idx); +	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id(); +	int cpu = perf_env__get_cpu(env, map, idx);  	if (cpu != -1) {  		/* -		 * Encode socket in bit range 31:24 -		 * encode die id in bit range 23:16  		 * core_id is relative to socket and die, -		 * we need a global id. So we combine -		 * socket + die id + core id +		 * we need a global id. So we set +		 * socket, die id and core id  		 */ -		if (WARN_ONCE(env->cpu[cpu].socket_id >> 8, "The socket id number is too big.\n")) -			return -1; - -		if (WARN_ONCE(env->cpu[cpu].die_id >> 8, "The die id number is too big.\n")) -			return -1; - -		if (WARN_ONCE(env->cpu[cpu].core_id >> 16, "The core id number is too big.\n")) -			return -1; - -		core = (env->cpu[cpu].socket_id << 24) | -		       (env->cpu[cpu].die_id << 16) | -		       (env->cpu[cpu].core_id & 0xffff); +		id.socket = env->cpu[cpu].socket_id; +		id.die = env->cpu[cpu].die_id; +		id.core = env->cpu[cpu].core_id;  	} -	return core; +	return id;  } -static int perf_env__get_node(struct perf_cpu_map *map, int idx, void *data) +static struct aggr_cpu_id perf_env__get_node(struct perf_cpu_map *map, int idx, void *data)  {  	int cpu = perf_env__get_cpu(data, map, idx); +	struct aggr_cpu_id id = cpu_map__empty_aggr_cpu_id(); -	return perf_env__numa_node(data, cpu); +	id.node = perf_env__numa_node(data, cpu); +	return id;  }  static int perf_env__build_socket_map(struct perf_env *env, struct perf_cpu_map *cpus, -				      struct perf_cpu_map **sockp) +				      struct cpu_aggr_map **sockp)  {  	return cpu_map__build_map(cpus, sockp, perf_env__get_socket, env);  }  static int perf_env__build_die_map(struct perf_env *env, struct perf_cpu_map *cpus, -				   struct perf_cpu_map **diep) +				   struct cpu_aggr_map **diep)  {  	return cpu_map__build_map(cpus, diep, perf_env__get_die, env);  }  static int perf_env__build_core_map(struct perf_env *env, struct perf_cpu_map *cpus, -				    struct perf_cpu_map **corep) +				    struct cpu_aggr_map **corep)  {  	return cpu_map__build_map(cpus, corep, perf_env__get_core, env);  }  static int perf_env__build_node_map(struct perf_env *env, struct perf_cpu_map *cpus, -				    struct perf_cpu_map **nodep) +				    struct cpu_aggr_map **nodep)  {  	return cpu_map__build_map(cpus, nodep, perf_env__get_node, env);  } -static int perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_socket_file(struct perf_stat_config *config __maybe_unused,  				      struct perf_cpu_map *map, int idx)  {  	return perf_env__get_socket(map, idx, &perf_stat.session->header.env);  } -static int perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_die_file(struct perf_stat_config *config __maybe_unused,  				   struct perf_cpu_map *map, int idx)  {  	return perf_env__get_die(map, idx, &perf_stat.session->header.env);  } -static int perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_core_file(struct perf_stat_config *config __maybe_unused,  				    struct perf_cpu_map *map, int idx)  {  	return perf_env__get_core(map, idx, &perf_stat.session->header.env);  } -static int perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused, +static struct aggr_cpu_id perf_stat__get_node_file(struct perf_stat_config *config __maybe_unused,  				    struct perf_cpu_map *map, int idx)  {  	return perf_env__get_node(map, idx, &perf_stat.session->header.env); @@ -1904,7 +1914,7 @@ static int set_maps(struct perf_stat *st)  	perf_evlist__set_maps(&evsel_list->core, st->cpus, st->threads); -	if (perf_evlist__alloc_stats(evsel_list, true)) +	if (evlist__alloc_stats(evsel_list, true))  		return -ENOMEM;  	st->maps_allocated = true; @@ -2132,7 +2142,7 @@ int cmd_stat(int argc, const char **argv)  		goto out;  	} -	if (!output) { +	if (!output && !stat_config.quiet) {  		struct timespec tm;  		mode = append_file ? "a" : "w"; @@ -2235,8 +2245,11 @@ int cmd_stat(int argc, const char **argv)  		}  		if (evlist__expand_cgroup(evsel_list, stat_config.cgroup_list, -					  &stat_config.metric_events, true) < 0) +					  &stat_config.metric_events, true) < 0) { +			parse_options_usage(stat_usage, stat_options, +					    "for-each-cgroup", 0);  			goto out; +		}  	}  	target__validate(&target); @@ -2244,7 +2257,7 @@ int cmd_stat(int argc, const char **argv)  	if ((stat_config.aggr_mode == AGGR_THREAD) && (target.system_wide))  		target.per_thread = true; -	if (perf_evlist__create_maps(evsel_list, &target) < 0) { +	if (evlist__create_maps(evsel_list, &target) < 0) {  		if (target__has_task(&target)) {  			pr_err("Problems finding threads of monitor\n");  			parse_options_usage(stat_usage, stat_options, "p", 1); @@ -2303,7 +2316,7 @@ int cmd_stat(int argc, const char **argv)  		goto out;  	} -	if (perf_evlist__alloc_stats(evsel_list, interval)) +	if (evlist__alloc_stats(evsel_list, interval))  		goto out;  	if (perf_stat_init_aggr_mode()) @@ -2343,7 +2356,7 @@ int cmd_stat(int argc, const char **argv)  				run_idx + 1);  		if (run_idx != 0) -			perf_evlist__reset_prev_raw_counts(evsel_list); +			evlist__reset_prev_raw_counts(evsel_list);  		status = run_perf_stat(argc, argv, run_idx);  		if (forever && status != -1 && !interval) { @@ -2394,7 +2407,7 @@ int cmd_stat(int argc, const char **argv)  	}  	perf_stat__exit_aggr_mode(); -	perf_evlist__free_stats(evsel_list); +	evlist__free_stats(evsel_list);  out:  	zfree(&stat_config.walltime_run);  | 
