diff options
Diffstat (limited to 'tools/perf/util/expr.c')
-rw-r--r-- | tools/perf/util/expr.c | 65 |
1 files changed, 60 insertions, 5 deletions
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 77c6ad81a923..1d532b9fed29 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -5,13 +5,17 @@ #include <stdlib.h> #include <string.h> #include "metricgroup.h" +#include "cpumap.h" +#include "cputopo.h" #include "debug.h" #include "expr.h" #include "expr-bison.h" #include "expr-flex.h" +#include "smt.h" #include <linux/kernel.h> #include <linux/zalloc.h> #include <ctype.h> +#include <math.h> #ifdef PARSER_DEBUG extern int expr_debug; @@ -19,7 +23,10 @@ extern int expr_debug; struct expr_id_data { union { - double val; + struct { + double val; + int source_count; + } val; struct { double val; const char *metric_name; @@ -137,6 +144,13 @@ int expr__add_id(struct expr_parse_ctx *ctx, const char *id) /* Caller must make sure id is allocated */ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) { + return expr__add_id_val_source_count(ctx, id, val, /*source_count=*/1); +} + +/* Caller must make sure id is allocated */ +int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, + double val, int source_count) +{ struct expr_id_data *data_ptr = NULL, *old_data = NULL; char *old_key = NULL; int ret; @@ -144,7 +158,8 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) data_ptr = malloc(sizeof(*data_ptr)); if (!data_ptr) return -ENOMEM; - data_ptr->val = val; + data_ptr->val.val = val; + data_ptr->val.source_count = source_count; data_ptr->kind = EXPR_ID_DATA__VALUE; ret = hashmap__set(ctx->ids, id, data_ptr, @@ -240,7 +255,7 @@ int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, switch (data->kind) { case EXPR_ID_DATA__VALUE: - pr_debug2("lookup(%s): val %f\n", id, data->val); + pr_debug2("lookup(%s): val %f\n", id, data->val.val); break; case EXPR_ID_DATA__REF: pr_debug2("lookup(%s): ref metric name %s\n", id, @@ -251,7 +266,7 @@ int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, pr_debug("%s failed to count\n", id); return -1; } - pr_debug("processing metric: %s EXIT: %f\n", id, data->val); + pr_debug("processing metric: %s EXIT: %f\n", id, data->ref.val); break; case EXPR_ID_DATA__REF_VALUE: pr_debug2("lookup(%s): ref val %f metric name %s\n", id, @@ -366,7 +381,47 @@ int expr__find_ids(const char *expr, const char *one, double expr_id_data__value(const struct expr_id_data *data) { if (data->kind == EXPR_ID_DATA__VALUE) - return data->val; + return data->val.val; assert(data->kind == EXPR_ID_DATA__REF_VALUE); return data->ref.val; } + +double expr_id_data__source_count(const struct expr_id_data *data) +{ + assert(data->kind == EXPR_ID_DATA__VALUE); + return data->val.source_count; +} + +double expr__get_literal(const char *literal) +{ + static struct cpu_topology *topology; + + if (!strcmp("#smt_on", literal)) + return smt_on() > 0 ? 1.0 : 0.0; + + if (!strcmp("#num_cpus", literal)) + return cpu__max_present_cpu(); + + /* + * Assume that topology strings are consistent, such as CPUs "0-1" + * wouldn't be listed as "0,1", and so after deduplication the number of + * these strings gives an indication of the number of packages, dies, + * etc. + */ + if (!topology) { + topology = cpu_topology__new(); + if (!topology) { + pr_err("Error creating CPU topology"); + return NAN; + } + } + if (!strcmp("#num_packages", literal)) + return topology->package_cpus_lists; + if (!strcmp("#num_dies", literal)) + return topology->die_cpus_lists; + if (!strcmp("#num_cores", literal)) + return topology->core_cpus_lists; + + pr_err("Unrecognized literal '%s'", literal); + return NAN; +} |