xref: /openbmc/linux/tools/perf/util/stat.c (revision aeb00b1a)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2a43783aeSArnaldo Carvalho de Melo #include <errno.h>
3fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
40007eceaSXiao Guangrong #include <math.h>
5bfc49182SArnaldo Carvalho de Melo #include "counts.h"
60007eceaSXiao Guangrong #include "stat.h"
7aeb00b1aSArnaldo Carvalho de Melo #include "target.h"
824e34f68SJiri Olsa #include "evlist.h"
9e2f56da1SJiri Olsa #include "evsel.h"
1024e34f68SJiri Olsa #include "thread_map.h"
117f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
120007eceaSXiao Guangrong 
130007eceaSXiao Guangrong void update_stats(struct stats *stats, u64 val)
140007eceaSXiao Guangrong {
150007eceaSXiao Guangrong 	double delta;
160007eceaSXiao Guangrong 
170007eceaSXiao Guangrong 	stats->n++;
180007eceaSXiao Guangrong 	delta = val - stats->mean;
190007eceaSXiao Guangrong 	stats->mean += delta / stats->n;
200007eceaSXiao Guangrong 	stats->M2 += delta*(val - stats->mean);
21ffe4f3c0SDavid Ahern 
22ffe4f3c0SDavid Ahern 	if (val > stats->max)
23ffe4f3c0SDavid Ahern 		stats->max = val;
24ffe4f3c0SDavid Ahern 
25ffe4f3c0SDavid Ahern 	if (val < stats->min)
26ffe4f3c0SDavid Ahern 		stats->min = val;
270007eceaSXiao Guangrong }
280007eceaSXiao Guangrong 
290007eceaSXiao Guangrong double avg_stats(struct stats *stats)
300007eceaSXiao Guangrong {
310007eceaSXiao Guangrong 	return stats->mean;
320007eceaSXiao Guangrong }
330007eceaSXiao Guangrong 
340007eceaSXiao Guangrong /*
350007eceaSXiao Guangrong  * http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance
360007eceaSXiao Guangrong  *
370007eceaSXiao Guangrong  *       (\Sum n_i^2) - ((\Sum n_i)^2)/n
380007eceaSXiao Guangrong  * s^2 = -------------------------------
390007eceaSXiao Guangrong  *                  n - 1
400007eceaSXiao Guangrong  *
410007eceaSXiao Guangrong  * http://en.wikipedia.org/wiki/Stddev
420007eceaSXiao Guangrong  *
430007eceaSXiao Guangrong  * The std dev of the mean is related to the std dev by:
440007eceaSXiao Guangrong  *
450007eceaSXiao Guangrong  *             s
460007eceaSXiao Guangrong  * s_mean = -------
470007eceaSXiao Guangrong  *          sqrt(n)
480007eceaSXiao Guangrong  *
490007eceaSXiao Guangrong  */
500007eceaSXiao Guangrong double stddev_stats(struct stats *stats)
510007eceaSXiao Guangrong {
520007eceaSXiao Guangrong 	double variance, variance_mean;
530007eceaSXiao Guangrong 
5445528f7cSDavid Ahern 	if (stats->n < 2)
550007eceaSXiao Guangrong 		return 0.0;
560007eceaSXiao Guangrong 
570007eceaSXiao Guangrong 	variance = stats->M2 / (stats->n - 1);
580007eceaSXiao Guangrong 	variance_mean = variance / stats->n;
590007eceaSXiao Guangrong 
600007eceaSXiao Guangrong 	return sqrt(variance_mean);
610007eceaSXiao Guangrong }
620007eceaSXiao Guangrong 
630007eceaSXiao Guangrong double rel_stddev_stats(double stddev, double avg)
640007eceaSXiao Guangrong {
650007eceaSXiao Guangrong 	double pct = 0.0;
660007eceaSXiao Guangrong 
670007eceaSXiao Guangrong 	if (avg)
680007eceaSXiao Guangrong 		pct = 100.0 * stddev/avg;
690007eceaSXiao Guangrong 
700007eceaSXiao Guangrong 	return pct;
710007eceaSXiao Guangrong }
72e2f56da1SJiri Olsa 
7332dcd021SJiri Olsa bool __perf_evsel_stat__is(struct evsel *evsel,
74e2f56da1SJiri Olsa 			   enum perf_stat_evsel_id id)
75e2f56da1SJiri Olsa {
76e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
77e2f56da1SJiri Olsa 
78e2f56da1SJiri Olsa 	return ps->id == id;
79e2f56da1SJiri Olsa }
80e2f56da1SJiri Olsa 
81e2f56da1SJiri Olsa #define ID(id, name) [PERF_STAT_EVSEL_ID__##id] = #name
82e2f56da1SJiri Olsa static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
83e2f56da1SJiri Olsa 	ID(NONE,		x),
844c358d5cSJiri Olsa 	ID(CYCLES_IN_TX,	cpu/cycles-t/),
854c358d5cSJiri Olsa 	ID(TRANSACTION_START,	cpu/tx-start/),
864c358d5cSJiri Olsa 	ID(ELISION_START,	cpu/el-start/),
874c358d5cSJiri Olsa 	ID(CYCLES_IN_TX_CP,	cpu/cycles-ct/),
88239bd47fSAndi Kleen 	ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
89239bd47fSAndi Kleen 	ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
90239bd47fSAndi Kleen 	ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
91239bd47fSAndi Kleen 	ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
92239bd47fSAndi Kleen 	ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
93daefd0bcSKan Liang 	ID(SMI_NUM, msr/smi/),
94daefd0bcSKan Liang 	ID(APERF, msr/aperf/),
95e2f56da1SJiri Olsa };
96e2f56da1SJiri Olsa #undef ID
97e2f56da1SJiri Olsa 
9832dcd021SJiri Olsa static void perf_stat_evsel_id_init(struct evsel *evsel)
99e2f56da1SJiri Olsa {
100e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
101e2f56da1SJiri Olsa 	int i;
102e2f56da1SJiri Olsa 
103e2f56da1SJiri Olsa 	/* ps->id is 0 hence PERF_STAT_EVSEL_ID__NONE by default */
104e2f56da1SJiri Olsa 
105e2f56da1SJiri Olsa 	for (i = 0; i < PERF_STAT_EVSEL_ID__MAX; i++) {
106e2f56da1SJiri Olsa 		if (!strcmp(perf_evsel__name(evsel), id_str[i])) {
107e2f56da1SJiri Olsa 			ps->id = i;
108e2f56da1SJiri Olsa 			break;
109e2f56da1SJiri Olsa 		}
110e2f56da1SJiri Olsa 	}
111e2f56da1SJiri Olsa }
112a9a3a4d9SJiri Olsa 
11332dcd021SJiri Olsa static void perf_evsel__reset_stat_priv(struct evsel *evsel)
1149689edfaSJiri Olsa {
1159689edfaSJiri Olsa 	int i;
116e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
1179689edfaSJiri Olsa 
1189689edfaSJiri Olsa 	for (i = 0; i < 3; i++)
1199689edfaSJiri Olsa 		init_stats(&ps->res_stats[i]);
1209689edfaSJiri Olsa 
1219689edfaSJiri Olsa 	perf_stat_evsel_id_init(evsel);
1229689edfaSJiri Olsa }
1239689edfaSJiri Olsa 
12432dcd021SJiri Olsa static int perf_evsel__alloc_stat_priv(struct evsel *evsel)
1259689edfaSJiri Olsa {
126e669e833SArnaldo Carvalho de Melo 	evsel->stats = zalloc(sizeof(struct perf_stat_evsel));
127e669e833SArnaldo Carvalho de Melo 	if (evsel->stats == NULL)
1289689edfaSJiri Olsa 		return -ENOMEM;
1299689edfaSJiri Olsa 	perf_evsel__reset_stat_priv(evsel);
1309689edfaSJiri Olsa 	return 0;
1319689edfaSJiri Olsa }
1329689edfaSJiri Olsa 
13332dcd021SJiri Olsa static void perf_evsel__free_stat_priv(struct evsel *evsel)
1349689edfaSJiri Olsa {
135e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = evsel->stats;
136f7794d52SJiri Olsa 
137f7794d52SJiri Olsa 	if (ps)
138d8f9da24SArnaldo Carvalho de Melo 		zfree(&ps->group_data);
139e669e833SArnaldo Carvalho de Melo 	zfree(&evsel->stats);
1409689edfaSJiri Olsa }
141a939512dSJiri Olsa 
14232dcd021SJiri Olsa static int perf_evsel__alloc_prev_raw_counts(struct evsel *evsel,
143a939512dSJiri Olsa 					     int ncpus, int nthreads)
144a939512dSJiri Olsa {
145a939512dSJiri Olsa 	struct perf_counts *counts;
146a939512dSJiri Olsa 
147a939512dSJiri Olsa 	counts = perf_counts__new(ncpus, nthreads);
148a939512dSJiri Olsa 	if (counts)
149a939512dSJiri Olsa 		evsel->prev_raw_counts = counts;
150a939512dSJiri Olsa 
151a939512dSJiri Olsa 	return counts ? 0 : -ENOMEM;
152a939512dSJiri Olsa }
153a939512dSJiri Olsa 
15432dcd021SJiri Olsa static void perf_evsel__free_prev_raw_counts(struct evsel *evsel)
155a939512dSJiri Olsa {
156a939512dSJiri Olsa 	perf_counts__delete(evsel->prev_raw_counts);
157a939512dSJiri Olsa 	evsel->prev_raw_counts = NULL;
158a939512dSJiri Olsa }
15924e34f68SJiri Olsa 
16032dcd021SJiri Olsa static int perf_evsel__alloc_stats(struct evsel *evsel, bool alloc_raw)
16124e34f68SJiri Olsa {
16224e34f68SJiri Olsa 	int ncpus = perf_evsel__nr_cpus(evsel);
163a2f354e3SJiri Olsa 	int nthreads = perf_thread_map__nr(evsel->core.threads);
16424e34f68SJiri Olsa 
16524e34f68SJiri Olsa 	if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
16624e34f68SJiri Olsa 	    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
16724e34f68SJiri Olsa 	    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
168a7d0a102SJiri Olsa 		return -ENOMEM;
169a7d0a102SJiri Olsa 
170a7d0a102SJiri Olsa 	return 0;
171a7d0a102SJiri Olsa }
172a7d0a102SJiri Olsa 
17363503dbaSJiri Olsa int perf_evlist__alloc_stats(struct evlist *evlist, bool alloc_raw)
174a7d0a102SJiri Olsa {
17532dcd021SJiri Olsa 	struct evsel *evsel;
176a7d0a102SJiri Olsa 
177e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
178a7d0a102SJiri Olsa 		if (perf_evsel__alloc_stats(evsel, alloc_raw))
17924e34f68SJiri Olsa 			goto out_free;
18024e34f68SJiri Olsa 	}
18124e34f68SJiri Olsa 
18224e34f68SJiri Olsa 	return 0;
18324e34f68SJiri Olsa 
18424e34f68SJiri Olsa out_free:
18524e34f68SJiri Olsa 	perf_evlist__free_stats(evlist);
18624e34f68SJiri Olsa 	return -1;
18724e34f68SJiri Olsa }
18824e34f68SJiri Olsa 
18963503dbaSJiri Olsa void perf_evlist__free_stats(struct evlist *evlist)
19024e34f68SJiri Olsa {
19132dcd021SJiri Olsa 	struct evsel *evsel;
19224e34f68SJiri Olsa 
193e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
19424e34f68SJiri Olsa 		perf_evsel__free_stat_priv(evsel);
19524e34f68SJiri Olsa 		perf_evsel__free_counts(evsel);
19624e34f68SJiri Olsa 		perf_evsel__free_prev_raw_counts(evsel);
19724e34f68SJiri Olsa 	}
19824e34f68SJiri Olsa }
19924e34f68SJiri Olsa 
20063503dbaSJiri Olsa void perf_evlist__reset_stats(struct evlist *evlist)
20124e34f68SJiri Olsa {
20232dcd021SJiri Olsa 	struct evsel *evsel;
20324e34f68SJiri Olsa 
204e5cadb93SArnaldo Carvalho de Melo 	evlist__for_each_entry(evlist, evsel) {
20524e34f68SJiri Olsa 		perf_evsel__reset_stat_priv(evsel);
20624e34f68SJiri Olsa 		perf_evsel__reset_counts(evsel);
20724e34f68SJiri Olsa 	}
20824e34f68SJiri Olsa }
209f80010ebSJiri Olsa 
21032dcd021SJiri Olsa static void zero_per_pkg(struct evsel *counter)
211f80010ebSJiri Olsa {
212f80010ebSJiri Olsa 	if (counter->per_pkg_mask)
213f80010ebSJiri Olsa 		memset(counter->per_pkg_mask, 0, MAX_NR_CPUS);
214f80010ebSJiri Olsa }
215f80010ebSJiri Olsa 
21632dcd021SJiri Olsa static int check_per_pkg(struct evsel *counter,
21702d8dabcSStephane Eranian 			 struct perf_counts_values *vals, int cpu, bool *skip)
218f80010ebSJiri Olsa {
219f80010ebSJiri Olsa 	unsigned long *mask = counter->per_pkg_mask;
220b49aca3eSJiri Olsa 	struct perf_cpu_map *cpus = evsel__cpus(counter);
221f80010ebSJiri Olsa 	int s;
222f80010ebSJiri Olsa 
223f80010ebSJiri Olsa 	*skip = false;
224f80010ebSJiri Olsa 
225f80010ebSJiri Olsa 	if (!counter->per_pkg)
226f80010ebSJiri Olsa 		return 0;
227f80010ebSJiri Olsa 
228315c0a1fSJiri Olsa 	if (perf_cpu_map__empty(cpus))
229f80010ebSJiri Olsa 		return 0;
230f80010ebSJiri Olsa 
231f80010ebSJiri Olsa 	if (!mask) {
232f80010ebSJiri Olsa 		mask = zalloc(MAX_NR_CPUS);
233f80010ebSJiri Olsa 		if (!mask)
234f80010ebSJiri Olsa 			return -ENOMEM;
235f80010ebSJiri Olsa 
236f80010ebSJiri Olsa 		counter->per_pkg_mask = mask;
237f80010ebSJiri Olsa 	}
238f80010ebSJiri Olsa 
23902d8dabcSStephane Eranian 	/*
24002d8dabcSStephane Eranian 	 * we do not consider an event that has not run as a good
24102d8dabcSStephane Eranian 	 * instance to mark a package as used (skip=1). Otherwise
24202d8dabcSStephane Eranian 	 * we may run into a situation where the first CPU in a package
24302d8dabcSStephane Eranian 	 * is not running anything, yet the second is, and this function
24402d8dabcSStephane Eranian 	 * would mark the package as used after the first CPU and would
24502d8dabcSStephane Eranian 	 * not read the values from the second CPU.
24602d8dabcSStephane Eranian 	 */
24702d8dabcSStephane Eranian 	if (!(vals->run && vals->ena))
24802d8dabcSStephane Eranian 		return 0;
24902d8dabcSStephane Eranian 
2501fe7a300SJiri Olsa 	s = cpu_map__get_socket(cpus, cpu, NULL);
251f80010ebSJiri Olsa 	if (s < 0)
252f80010ebSJiri Olsa 		return -1;
253f80010ebSJiri Olsa 
254f80010ebSJiri Olsa 	*skip = test_and_set_bit(s, mask) == 1;
255f80010ebSJiri Olsa 	return 0;
256f80010ebSJiri Olsa }
257f80010ebSJiri Olsa 
258f80010ebSJiri Olsa static int
25932dcd021SJiri Olsa process_counter_values(struct perf_stat_config *config, struct evsel *evsel,
260f80010ebSJiri Olsa 		       int cpu, int thread,
261f80010ebSJiri Olsa 		       struct perf_counts_values *count)
262f80010ebSJiri Olsa {
263f80010ebSJiri Olsa 	struct perf_counts_values *aggr = &evsel->counts->aggr;
264f80010ebSJiri Olsa 	static struct perf_counts_values zero;
265f80010ebSJiri Olsa 	bool skip = false;
266f80010ebSJiri Olsa 
26702d8dabcSStephane Eranian 	if (check_per_pkg(evsel, count, cpu, &skip)) {
268f80010ebSJiri Olsa 		pr_err("failed to read per-pkg counter\n");
269f80010ebSJiri Olsa 		return -1;
270f80010ebSJiri Olsa 	}
271f80010ebSJiri Olsa 
272f80010ebSJiri Olsa 	if (skip)
273f80010ebSJiri Olsa 		count = &zero;
274f80010ebSJiri Olsa 
275f80010ebSJiri Olsa 	switch (config->aggr_mode) {
276f80010ebSJiri Olsa 	case AGGR_THREAD:
277f80010ebSJiri Olsa 	case AGGR_CORE:
278db5742b6SKan Liang 	case AGGR_DIE:
279f80010ebSJiri Olsa 	case AGGR_SOCKET:
280f80010ebSJiri Olsa 	case AGGR_NONE:
281f80010ebSJiri Olsa 		if (!evsel->snapshot)
282f80010ebSJiri Olsa 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
283f80010ebSJiri Olsa 		perf_counts_values__scale(count, config->scale, NULL);
2844fc4d8dfSJin Yao 		if ((config->aggr_mode == AGGR_NONE) && (!evsel->percore)) {
2854fc4d8dfSJin Yao 			perf_stat__update_shadow_stats(evsel, count->val,
2864fc4d8dfSJin Yao 						       cpu, &rt_stat);
2874fc4d8dfSJin Yao 		}
2884fc4d8dfSJin Yao 
28914e72a21SJin Yao 		if (config->aggr_mode == AGGR_THREAD) {
29014e72a21SJin Yao 			if (config->stats)
29114e72a21SJin Yao 				perf_stat__update_shadow_stats(evsel,
29214e72a21SJin Yao 					count->val, 0, &config->stats[thread]);
29314e72a21SJin Yao 			else
29414e72a21SJin Yao 				perf_stat__update_shadow_stats(evsel,
29514e72a21SJin Yao 					count->val, 0, &rt_stat);
29614e72a21SJin Yao 		}
297f80010ebSJiri Olsa 		break;
298f80010ebSJiri Olsa 	case AGGR_GLOBAL:
299f80010ebSJiri Olsa 		aggr->val += count->val;
300f80010ebSJiri Olsa 		aggr->ena += count->ena;
301f80010ebSJiri Olsa 		aggr->run += count->run;
302208df99eSJiri Olsa 	case AGGR_UNSET:
303f80010ebSJiri Olsa 	default:
304f80010ebSJiri Olsa 		break;
305f80010ebSJiri Olsa 	}
306f80010ebSJiri Olsa 
307f80010ebSJiri Olsa 	return 0;
308f80010ebSJiri Olsa }
309f80010ebSJiri Olsa 
310f80010ebSJiri Olsa static int process_counter_maps(struct perf_stat_config *config,
31132dcd021SJiri Olsa 				struct evsel *counter)
312f80010ebSJiri Olsa {
313a2f354e3SJiri Olsa 	int nthreads = perf_thread_map__nr(counter->core.threads);
314f80010ebSJiri Olsa 	int ncpus = perf_evsel__nr_cpus(counter);
315f80010ebSJiri Olsa 	int cpu, thread;
316f80010ebSJiri Olsa 
317f80010ebSJiri Olsa 	if (counter->system_wide)
318f80010ebSJiri Olsa 		nthreads = 1;
319f80010ebSJiri Olsa 
320f80010ebSJiri Olsa 	for (thread = 0; thread < nthreads; thread++) {
321f80010ebSJiri Olsa 		for (cpu = 0; cpu < ncpus; cpu++) {
322f80010ebSJiri Olsa 			if (process_counter_values(config, counter, cpu, thread,
323f80010ebSJiri Olsa 						   perf_counts(counter->counts, cpu, thread)))
324f80010ebSJiri Olsa 				return -1;
325f80010ebSJiri Olsa 		}
326f80010ebSJiri Olsa 	}
327f80010ebSJiri Olsa 
328f80010ebSJiri Olsa 	return 0;
329f80010ebSJiri Olsa }
330f80010ebSJiri Olsa 
331f80010ebSJiri Olsa int perf_stat_process_counter(struct perf_stat_config *config,
33232dcd021SJiri Olsa 			      struct evsel *counter)
333f80010ebSJiri Olsa {
334f80010ebSJiri Olsa 	struct perf_counts_values *aggr = &counter->counts->aggr;
335e669e833SArnaldo Carvalho de Melo 	struct perf_stat_evsel *ps = counter->stats;
336f80010ebSJiri Olsa 	u64 *count = counter->counts->aggr.values;
337f80010ebSJiri Olsa 	int i, ret;
338f80010ebSJiri Olsa 
339f80010ebSJiri Olsa 	aggr->val = aggr->ena = aggr->run = 0;
340f80010ebSJiri Olsa 
34151fd2df1SJiri Olsa 	/*
34251fd2df1SJiri Olsa 	 * We calculate counter's data every interval,
34351fd2df1SJiri Olsa 	 * and the display code shows ps->res_stats
34451fd2df1SJiri Olsa 	 * avg value. We need to zero the stats for
34551fd2df1SJiri Olsa 	 * interval mode, otherwise overall avg running
34651fd2df1SJiri Olsa 	 * averages will be shown for each interval.
34751fd2df1SJiri Olsa 	 */
34851fd2df1SJiri Olsa 	if (config->interval)
34951fd2df1SJiri Olsa 		init_stats(ps->res_stats);
35051fd2df1SJiri Olsa 
351f80010ebSJiri Olsa 	if (counter->per_pkg)
352f80010ebSJiri Olsa 		zero_per_pkg(counter);
353f80010ebSJiri Olsa 
354f80010ebSJiri Olsa 	ret = process_counter_maps(config, counter);
355f80010ebSJiri Olsa 	if (ret)
356f80010ebSJiri Olsa 		return ret;
357f80010ebSJiri Olsa 
358f80010ebSJiri Olsa 	if (config->aggr_mode != AGGR_GLOBAL)
359f80010ebSJiri Olsa 		return 0;
360f80010ebSJiri Olsa 
361f80010ebSJiri Olsa 	if (!counter->snapshot)
362f80010ebSJiri Olsa 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
363f80010ebSJiri Olsa 	perf_counts_values__scale(aggr, config->scale, &counter->counts->scaled);
364f80010ebSJiri Olsa 
365f80010ebSJiri Olsa 	for (i = 0; i < 3; i++)
366f80010ebSJiri Olsa 		update_stats(&ps->res_stats[i], count[i]);
367f80010ebSJiri Olsa 
368bb963e16SNamhyung Kim 	if (verbose > 0) {
369f80010ebSJiri Olsa 		fprintf(config->output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
370f80010ebSJiri Olsa 			perf_evsel__name(counter), count[0], count[1], count[2]);
371f80010ebSJiri Olsa 	}
372f80010ebSJiri Olsa 
373f80010ebSJiri Olsa 	/*
374f80010ebSJiri Olsa 	 * Save the full runtime - to allow normalization during printout:
375f80010ebSJiri Olsa 	 */
3761fcd0394SJin Yao 	perf_stat__update_shadow_stats(counter, *count, 0, &rt_stat);
377f80010ebSJiri Olsa 
378f80010ebSJiri Olsa 	return 0;
379f80010ebSJiri Olsa }
3800ea0e355SJiri Olsa 
38189f1688aSJiri Olsa int perf_event__process_stat_event(struct perf_session *session,
38289f1688aSJiri Olsa 				   union perf_event *event)
3830ea0e355SJiri Olsa {
3840ea0e355SJiri Olsa 	struct perf_counts_values count;
3850ea0e355SJiri Olsa 	struct stat_event *st = &event->stat;
38632dcd021SJiri Olsa 	struct evsel *counter;
3870ea0e355SJiri Olsa 
3880ea0e355SJiri Olsa 	count.val = st->val;
3890ea0e355SJiri Olsa 	count.ena = st->ena;
3900ea0e355SJiri Olsa 	count.run = st->run;
3910ea0e355SJiri Olsa 
3920ea0e355SJiri Olsa 	counter = perf_evlist__id2evsel(session->evlist, st->id);
3930ea0e355SJiri Olsa 	if (!counter) {
3940ea0e355SJiri Olsa 		pr_err("Failed to resolve counter for stat event.\n");
3950ea0e355SJiri Olsa 		return -EINVAL;
3960ea0e355SJiri Olsa 	}
3970ea0e355SJiri Olsa 
3980ea0e355SJiri Olsa 	*perf_counts(counter->counts, st->cpu, st->thread) = count;
3990ea0e355SJiri Olsa 	counter->supported = true;
4000ea0e355SJiri Olsa 	return 0;
4010ea0e355SJiri Olsa }
402e08a4564SJiri Olsa 
403e08a4564SJiri Olsa size_t perf_event__fprintf_stat(union perf_event *event, FILE *fp)
404e08a4564SJiri Olsa {
405e08a4564SJiri Olsa 	struct stat_event *st = (struct stat_event *) event;
406e08a4564SJiri Olsa 	size_t ret;
407e08a4564SJiri Olsa 
408e08a4564SJiri Olsa 	ret  = fprintf(fp, "\n... id %" PRIu64 ", cpu %d, thread %d\n",
409e08a4564SJiri Olsa 		       st->id, st->cpu, st->thread);
410e08a4564SJiri Olsa 	ret += fprintf(fp, "... value %" PRIu64 ", enabled %" PRIu64 ", running %" PRIu64 "\n",
411e08a4564SJiri Olsa 		       st->val, st->ena, st->run);
412e08a4564SJiri Olsa 
413e08a4564SJiri Olsa 	return ret;
414e08a4564SJiri Olsa }
415e08a4564SJiri Olsa 
416e08a4564SJiri Olsa size_t perf_event__fprintf_stat_round(union perf_event *event, FILE *fp)
417e08a4564SJiri Olsa {
418e08a4564SJiri Olsa 	struct stat_round_event *rd = (struct stat_round_event *)event;
419e08a4564SJiri Olsa 	size_t ret;
420e08a4564SJiri Olsa 
421e08a4564SJiri Olsa 	ret = fprintf(fp, "\n... time %" PRIu64 ", type %s\n", rd->time,
422e08a4564SJiri Olsa 		      rd->type == PERF_STAT_ROUND_TYPE__FINAL ? "FINAL" : "INTERVAL");
423e08a4564SJiri Olsa 
424e08a4564SJiri Olsa 	return ret;
425e08a4564SJiri Olsa }
426e08a4564SJiri Olsa 
427e08a4564SJiri Olsa size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
428e08a4564SJiri Olsa {
429e08a4564SJiri Olsa 	struct perf_stat_config sc;
430e08a4564SJiri Olsa 	size_t ret;
431e08a4564SJiri Olsa 
432e08a4564SJiri Olsa 	perf_event__read_stat_config(&sc, &event->stat_config);
433e08a4564SJiri Olsa 
434e08a4564SJiri Olsa 	ret  = fprintf(fp, "\n");
435e08a4564SJiri Olsa 	ret += fprintf(fp, "... aggr_mode %d\n", sc.aggr_mode);
436e08a4564SJiri Olsa 	ret += fprintf(fp, "... scale     %d\n", sc.scale);
437e08a4564SJiri Olsa 	ret += fprintf(fp, "... interval  %u\n", sc.interval);
438e08a4564SJiri Olsa 
439e08a4564SJiri Olsa 	return ret;
440e08a4564SJiri Olsa }
441d09cefd2SJiri Olsa 
44232dcd021SJiri Olsa int create_perf_stat_counter(struct evsel *evsel,
443d09cefd2SJiri Olsa 			     struct perf_stat_config *config,
444d09cefd2SJiri Olsa 			     struct target *target)
445d09cefd2SJiri Olsa {
4461fc632ceSJiri Olsa 	struct perf_event_attr *attr = &evsel->core.attr;
44732dcd021SJiri Olsa 	struct evsel *leader = evsel->leader;
448d09cefd2SJiri Olsa 
449d09cefd2SJiri Olsa 	attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
450d09cefd2SJiri Olsa 			    PERF_FORMAT_TOTAL_TIME_RUNNING;
451d09cefd2SJiri Olsa 
452d09cefd2SJiri Olsa 	/*
453d09cefd2SJiri Olsa 	 * The event is part of non trivial group, let's enable
454d09cefd2SJiri Olsa 	 * the group read (for leader) and ID retrieval for all
455d09cefd2SJiri Olsa 	 * members.
456d09cefd2SJiri Olsa 	 */
4575643b1a5SJiri Olsa 	if (leader->core.nr_members > 1)
458d09cefd2SJiri Olsa 		attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
459d09cefd2SJiri Olsa 
460d09cefd2SJiri Olsa 	attr->inherit = !config->no_inherit;
461d09cefd2SJiri Olsa 
462d09cefd2SJiri Olsa 	/*
463d09cefd2SJiri Olsa 	 * Some events get initialized with sample_(period/type) set,
464d09cefd2SJiri Olsa 	 * like tracepoints. Clear it up for counting.
465d09cefd2SJiri Olsa 	 */
466d09cefd2SJiri Olsa 	attr->sample_period = 0;
467d09cefd2SJiri Olsa 
468d09cefd2SJiri Olsa 	if (config->identifier)
469d09cefd2SJiri Olsa 		attr->sample_type = PERF_SAMPLE_IDENTIFIER;
470d09cefd2SJiri Olsa 
471d09cefd2SJiri Olsa 	/*
472d09cefd2SJiri Olsa 	 * Disabling all counters initially, they will be enabled
473d09cefd2SJiri Olsa 	 * either manually by us or by kernel via enable_on_exec
474d09cefd2SJiri Olsa 	 * set later.
475d09cefd2SJiri Olsa 	 */
476d09cefd2SJiri Olsa 	if (perf_evsel__is_group_leader(evsel)) {
477d09cefd2SJiri Olsa 		attr->disabled = 1;
478d09cefd2SJiri Olsa 
479d09cefd2SJiri Olsa 		/*
480d09cefd2SJiri Olsa 		 * In case of initial_delay we enable tracee
481d09cefd2SJiri Olsa 		 * events manually.
482d09cefd2SJiri Olsa 		 */
483d09cefd2SJiri Olsa 		if (target__none(target) && !config->initial_delay)
484d09cefd2SJiri Olsa 			attr->enable_on_exec = 1;
485d09cefd2SJiri Olsa 	}
486d09cefd2SJiri Olsa 
487d09cefd2SJiri Olsa 	if (target__has_cpu(target) && !target__has_per_thread(target))
488b49aca3eSJiri Olsa 		return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel));
489d09cefd2SJiri Olsa 
490af663bd0SJiri Olsa 	return perf_evsel__open_per_thread(evsel, evsel->core.threads);
491d09cefd2SJiri Olsa }
4920a4e64d3SJiri Olsa 
4930a4e64d3SJiri Olsa int perf_stat_synthesize_config(struct perf_stat_config *config,
4940a4e64d3SJiri Olsa 				struct perf_tool *tool,
49563503dbaSJiri Olsa 				struct evlist *evlist,
4960a4e64d3SJiri Olsa 				perf_event__handler_t process,
4970a4e64d3SJiri Olsa 				bool attrs)
4980a4e64d3SJiri Olsa {
4990a4e64d3SJiri Olsa 	int err;
5000a4e64d3SJiri Olsa 
5010a4e64d3SJiri Olsa 	if (attrs) {
5020a4e64d3SJiri Olsa 		err = perf_event__synthesize_attrs(tool, evlist, process);
5030a4e64d3SJiri Olsa 		if (err < 0) {
5040a4e64d3SJiri Olsa 			pr_err("Couldn't synthesize attrs.\n");
5050a4e64d3SJiri Olsa 			return err;
5060a4e64d3SJiri Olsa 		}
5070a4e64d3SJiri Olsa 	}
5080a4e64d3SJiri Olsa 
5090a4e64d3SJiri Olsa 	err = perf_event__synthesize_extra_attr(tool, evlist, process,
5100a4e64d3SJiri Olsa 						attrs);
5110a4e64d3SJiri Olsa 
51203617c22SJiri Olsa 	err = perf_event__synthesize_thread_map2(tool, evlist->core.threads,
5130a4e64d3SJiri Olsa 						 process, NULL);
5140a4e64d3SJiri Olsa 	if (err < 0) {
5150a4e64d3SJiri Olsa 		pr_err("Couldn't synthesize thread map.\n");
5160a4e64d3SJiri Olsa 		return err;
5170a4e64d3SJiri Olsa 	}
5180a4e64d3SJiri Olsa 
519f72f901dSJiri Olsa 	err = perf_event__synthesize_cpu_map(tool, evlist->core.cpus,
5200a4e64d3SJiri Olsa 					     process, NULL);
5210a4e64d3SJiri Olsa 	if (err < 0) {
5220a4e64d3SJiri Olsa 		pr_err("Couldn't synthesize thread map.\n");
5230a4e64d3SJiri Olsa 		return err;
5240a4e64d3SJiri Olsa 	}
5250a4e64d3SJiri Olsa 
5260a4e64d3SJiri Olsa 	err = perf_event__synthesize_stat_config(tool, config, process, NULL);
5270a4e64d3SJiri Olsa 	if (err < 0) {
5280a4e64d3SJiri Olsa 		pr_err("Couldn't synthesize config.\n");
5290a4e64d3SJiri Olsa 		return err;
5300a4e64d3SJiri Olsa 	}
5310a4e64d3SJiri Olsa 
5320a4e64d3SJiri Olsa 	return 0;
5330a4e64d3SJiri Olsa }
534