diff options
Diffstat (limited to 'tools/perf/util/stat-shadow.c')
| -rw-r--r-- | tools/perf/util/stat-shadow.c | 76 | 
1 files changed, 40 insertions, 36 deletions
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index 34a7f5c1fff7..e4fb02b05130 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c @@ -1,8 +1,10 @@  // SPDX-License-Identifier: GPL-2.0 +#include <math.h>  #include <stdio.h>  #include "evsel.h"  #include "stat.h"  #include "color.h" +#include "debug.h"  #include "pmu.h"  #include "rblist.h"  #include "evlist.h" @@ -370,12 +372,16 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)  {  	struct evsel *counter, *leader, **metric_events, *oc;  	bool found; -	struct expr_parse_ctx ctx; +	struct expr_parse_ctx *ctx;  	struct hashmap_entry *cur;  	size_t bkt;  	int i; -	expr__ctx_init(&ctx); +	ctx = expr__ctx_new(); +	if (!ctx) { +		pr_debug("expr__ctx_new failed"); +		return; +	}  	evlist__for_each_entry(evsel_list, counter) {  		bool invalid = false; @@ -383,25 +389,25 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)  		if (!counter->metric_expr)  			continue; -		expr__ctx_clear(&ctx); +		expr__ctx_clear(ctx);  		metric_events = counter->metric_events;  		if (!metric_events) { -			if (expr__find_other(counter->metric_expr, -					     counter->name, -					     &ctx, 1) < 0) +			if (expr__find_ids(counter->metric_expr, +					   counter->name, +					   ctx) < 0)  				continue;  			metric_events = calloc(sizeof(struct evsel *), -					       hashmap__size(&ctx.ids) + 1); +					       hashmap__size(ctx->ids) + 1);  			if (!metric_events) { -				expr__ctx_clear(&ctx); +				expr__ctx_free(ctx);  				return;  			}  			counter->metric_events = metric_events;  		}  		i = 0; -		hashmap__for_each_entry((&ctx.ids), cur, bkt) { +		hashmap__for_each_entry(ctx->ids, cur, bkt) {  			const char *metric_name = (const char *)cur->key;  			found = false; @@ -438,6 +444,7 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)  						"Add %s event to groups to get metric expression for %s\n",  						metric_name,  						counter->name); +					free(printed);  					printed = strdup(metric_name);  				}  				invalid = true; @@ -453,7 +460,7 @@ void perf_stat__collect_metric_expr(struct evlist *evsel_list)  			counter->metric_expr = NULL;  		}  	} -	expr__ctx_clear(&ctx); +	expr__ctx_free(ctx);  }  static double runtime_stat_avg(struct runtime_stat *st, @@ -815,10 +822,9 @@ static int prepare_metric(struct evsel **metric_events,  			  struct runtime_stat *st)  {  	double scale; -	char *n, *pn; +	char *n;  	int i, j, ret; -	expr__ctx_init(pctx);  	for (i = 0; metric_events[i]; i++) {  		struct saved_value *v;  		struct stats *stats; @@ -839,23 +845,11 @@ static int prepare_metric(struct evsel **metric_events,  			if (v->metric_other)  				metric_total = v->metric_total;  		} - -		n = strdup(metric_events[i]->name); +		n = strdup(evsel__metric_id(metric_events[i]));  		if (!n)  			return -ENOMEM; -		/* -		 * This display code with --no-merge adds [cpu] postfixes. -		 * These are not supported by the parser. Remove everything -		 * after the space. -		 */ -		pn = strchr(n, ' '); -		if (pn) -			*pn = 0; - -		if (metric_total) -			expr__add_id_val(pctx, n, metric_total); -		else -			expr__add_id_val(pctx, n, avg_stats(stats)*scale); + +		expr__add_id_val(pctx, n, metric_total ? : avg_stats(stats) * scale);  	}  	for (j = 0; metric_refs && metric_refs[j].metric_name; j++) { @@ -880,17 +874,23 @@ static void generic_metric(struct perf_stat_config *config,  			   struct runtime_stat *st)  {  	print_metric_t print_metric = out->print_metric; -	struct expr_parse_ctx pctx; +	struct expr_parse_ctx *pctx;  	double ratio, scale;  	int i;  	void *ctxp = out->ctx; -	i = prepare_metric(metric_events, metric_refs, &pctx, cpu, st); -	if (i < 0) +	pctx = expr__ctx_new(); +	if (!pctx)  		return; +	pctx->runtime = runtime; +	i = prepare_metric(metric_events, metric_refs, pctx, cpu, st); +	if (i < 0) { +		expr__ctx_free(pctx); +		return; +	}  	if (!metric_events[i]) { -		if (expr__parse(&ratio, &pctx, metric_expr, runtime) == 0) { +		if (expr__parse(&ratio, pctx, metric_expr) == 0) {  			char *unit;  			char metric_bf[64]; @@ -926,22 +926,26 @@ static void generic_metric(struct perf_stat_config *config,  			     (metric_name ? metric_name : name) : "", 0);  	} -	expr__ctx_clear(&pctx); +	expr__ctx_free(pctx);  }  double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st)  { -	struct expr_parse_ctx pctx; +	struct expr_parse_ctx *pctx;  	double ratio = 0.0; -	if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0) +	pctx = expr__ctx_new(); +	if (!pctx) +		return NAN; + +	if (prepare_metric(mexp->metric_events, mexp->metric_refs, pctx, cpu, st) < 0)  		goto out; -	if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) +	if (expr__parse(&ratio, pctx, mexp->metric_expr))  		ratio = 0.0;  out: -	expr__ctx_clear(&pctx); +	expr__ctx_free(pctx);  	return ratio;  }  |