diff options
Diffstat (limited to 'tools/perf/util/expr.c')
| -rw-r--r-- | tools/perf/util/expr.c | 158 |
1 files changed, 86 insertions, 72 deletions
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 00dcde35e0d3..465fe2e9bbbe 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -5,25 +5,23 @@ #include <stdlib.h> #include <string.h> #include "metricgroup.h" -#include "cpumap.h" -#include "cputopo.h" #include "debug.h" +#include "evlist.h" #include "expr.h" -#include "expr-bison.h" -#include "expr-flex.h" -#include "util/hashmap.h" #include "smt.h" -#include "tsc.h" +#include "tool_pmu.h" +#include <util/expr-bison.h> +#include <util/expr-flex.h> +#include "util/hashmap.h" +#include "util/header.h" +#include "util/pmu.h" +#include <perf/cpumap.h> #include <linux/err.h> #include <linux/kernel.h> #include <linux/zalloc.h> #include <ctype.h> #include <math.h> -#ifdef PARSER_DEBUG -extern int expr_debug; -#endif - struct expr_id_data { union { struct { @@ -84,8 +82,8 @@ void ids__free(struct hashmap *ids) return; hashmap__for_each_entry(ids, cur, bkt) { - free((void *)cur->pkey); - free((void *)cur->pvalue); + zfree(&cur->pkey); + zfree(&cur->pvalue); } hashmap__free(ids); @@ -168,8 +166,12 @@ int expr__add_id_val_source_count(struct expr_parse_ctx *ctx, const char *id, data_ptr->kind = EXPR_ID_DATA__VALUE; ret = hashmap__set(ctx->ids, id, data_ptr, &old_key, &old_data); - if (ret) + if (ret) { free(data_ptr); + } else if (old_data) { + data_ptr->val.val += old_data->val.val; + data_ptr->val.source_count += old_data->val.source_count; + } free(old_key); free(old_data); return ret; @@ -217,6 +219,8 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) int expr__get_id(struct expr_parse_ctx *ctx, const char *id, struct expr_id_data **data) { + if (!ctx || !id) + return -1; return hashmap__find(ctx->ids, id, data) ? 0 : -1; } @@ -287,7 +291,7 @@ struct expr_parse_ctx *expr__ctx_new(void) { struct expr_parse_ctx *ctx; - ctx = malloc(sizeof(struct expr_parse_ctx)); + ctx = calloc(1, sizeof(struct expr_parse_ctx)); if (!ctx) return NULL; @@ -296,9 +300,6 @@ struct expr_parse_ctx *expr__ctx_new(void) free(ctx); return NULL; } - ctx->sctx.user_requested_cpu_list = NULL; - ctx->sctx.runtime = 0; - ctx->sctx.system_wide = false; return ctx; } @@ -309,8 +310,8 @@ void expr__ctx_clear(struct expr_parse_ctx *ctx) size_t bkt; hashmap__for_each_entry(ctx->ids, cur, bkt) { - free((void *)cur->pkey); - free(cur->pvalue); + zfree(&cur->pkey); + zfree(&cur->pvalue); } hashmap__clear(ctx->ids); } @@ -323,10 +324,10 @@ void expr__ctx_free(struct expr_parse_ctx *ctx) if (!ctx) return; - free(ctx->sctx.user_requested_cpu_list); + zfree(&ctx->sctx.user_requested_cpu_list); hashmap__for_each_entry(ctx->ids, cur, bkt) { - free((void *)cur->pkey); - free(cur->pvalue); + zfree(&cur->pkey); + zfree(&cur->pvalue); } hashmap__free(ctx->ids); free(ctx); @@ -392,65 +393,78 @@ double expr_id_data__source_count(const struct expr_id_data *data) return data->val.source_count; } -#if !defined(__i386__) && !defined(__x86_64__) -double arch_get_tsc_freq(void) +double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx) { - return 0.0; + double result = NAN; + enum tool_pmu_event ev = tool_pmu__str_to_event(literal + 1); + + if (ev != TOOL_PMU__EVENT_NONE) { + u64 count; + + if (tool_pmu__read_event(ev, /*evsel=*/NULL, + ctx->system_wide, ctx->user_requested_cpu_list, + &count)) + result = count; + else + pr_err("Failure to read '%s'", literal); + } else { + pr_err("Unrecognized literal '%s'", literal); + } + + pr_debug2("literal: %s = %f\n", literal, result); + return result; } -#endif -double expr__get_literal(const char *literal, const struct expr_scanner_ctx *ctx) +/* Does the event 'id' parse? Determine via ctx->ids if possible. */ +double expr__has_event(const struct expr_parse_ctx *ctx, bool compute_ids, const char *id) { - static struct cpu_topology *topology; - double result = NAN; + struct evlist *tmp; + double ret; - if (!strcmp("#num_cpus", literal)) { - result = cpu__max_present_cpu().cpu; - goto out; - } + if (hashmap__find(ctx->ids, id, /*value=*/NULL)) + return 1.0; - if (!strcasecmp("#system_tsc_freq", literal)) { - result = arch_get_tsc_freq(); - goto out; - } + if (!compute_ids) + return 0.0; - /* - * 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"); + tmp = evlist__new(); + if (!tmp) + return NAN; + + if (strchr(id, '@')) { + char *tmp_id, *p; + + tmp_id = strdup(id); + if (!tmp_id) { + ret = NAN; goto out; } + p = strchr(tmp_id, '@'); + *p = '/'; + p = strrchr(tmp_id, '@'); + *p = '/'; + ret = parse_event(tmp, tmp_id) ? 0 : 1; + free(tmp_id); + } else { + ret = parse_event(tmp, id) ? 0 : 1; } - if (!strcasecmp("#smt_on", literal)) { - result = smt_on(topology) ? 1.0 : 0.0; - goto out; - } - if (!strcmp("#core_wide", literal)) { - result = core_wide(ctx->system_wide, ctx->user_requested_cpu_list, topology) - ? 1.0 : 0.0; - goto out; - } - if (!strcmp("#num_packages", literal)) { - result = topology->package_cpus_lists; - goto out; - } - if (!strcmp("#num_dies", literal)) { - result = topology->die_cpus_lists; - goto out; - } - if (!strcmp("#num_cores", literal)) { - result = topology->core_cpus_lists; - goto out; - } - - pr_err("Unrecognized literal '%s'", literal); out: - pr_debug2("literal: %s = %f\n", literal, result); - return result; + evlist__delete(tmp); + return ret; +} + +double expr__strcmp_cpuid_str(const struct expr_parse_ctx *ctx __maybe_unused, + bool compute_ids __maybe_unused, const char *test_id) +{ + double ret; + struct perf_cpu cpu = {-1}; + char *cpuid = get_cpuid_allow_env_override(cpu); + + if (!cpuid) + return NAN; + + ret = !strcmp_cpuid_str(test_id, cpuid); + + free(cpuid); + return ret; } |
