diff options
| author | Jiri Kosina <jkosina@suse.cz> | 2020-10-15 20:37:01 +0200 | 
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2020-10-15 20:37:01 +0200 | 
| commit | 62b31a045757eac81fed94b19df47418a0818528 (patch) | |
| tree | 285fda56df8304dff6ba929bad65ddfb4e4fd726 /tools/perf/util/expr.c | |
| parent | cc51d171776f3a6acb6828bad0b780a4cacf5423 (diff) | |
| parent | c27e08820bc6cb7d483a8d87589bdbbbf10f2306 (diff) | |
Merge branch 'for-5.10/core' into for-linus
- nonblocking read semantics fix for hid-debug
Diffstat (limited to 'tools/perf/util/expr.c')
| -rw-r--r-- | tools/perf/util/expr.c | 156 | 
1 files changed, 134 insertions, 22 deletions
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index f64ab91c432b..53482ef53c41 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -1,10 +1,17 @@  // SPDX-License-Identifier: GPL-2.0  #include <stdbool.h>  #include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include "metricgroup.h" +#include "debug.h"  #include "expr.h"  #include "expr-bison.h"  #include "expr-flex.h"  #include <linux/kernel.h> +#include <linux/zalloc.h> +#include <ctype.h>  #ifdef PARSER_DEBUG  extern int expr_debug; @@ -30,35 +37,144 @@ static bool key_equal(const void *key1, const void *key2,  }  /* Caller must make sure id is allocated */ -int expr__add_id(struct expr_parse_ctx *ctx, const char *name, double val) +int expr__add_id(struct expr_parse_ctx *ctx, const char *id)  { -	double *val_ptr = NULL, *old_val = NULL; +	struct expr_id_data *data_ptr = NULL, *old_data = NULL;  	char *old_key = NULL;  	int ret; -	if (val != 0.0) { -		val_ptr = malloc(sizeof(double)); -		if (!val_ptr) -			return -ENOMEM; -		*val_ptr = val; +	data_ptr = malloc(sizeof(*data_ptr)); +	if (!data_ptr) +		return -ENOMEM; + +	data_ptr->parent = ctx->parent; + +	ret = hashmap__set(&ctx->ids, id, data_ptr, +			   (const void **)&old_key, (void **)&old_data); +	if (ret) +		free(data_ptr); +	free(old_key); +	free(old_data); +	return ret; +} + +/* Caller must make sure id is allocated */ +int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val) +{ +	struct expr_id_data *data_ptr = NULL, *old_data = NULL; +	char *old_key = NULL; +	int ret; + +	data_ptr = malloc(sizeof(*data_ptr)); +	if (!data_ptr) +		return -ENOMEM; +	data_ptr->val = val; +	data_ptr->is_ref = false; + +	ret = hashmap__set(&ctx->ids, id, data_ptr, +			   (const void **)&old_key, (void **)&old_data); +	if (ret) +		free(data_ptr); +	free(old_key); +	free(old_data); +	return ret; +} + +int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref) +{ +	struct expr_id_data *data_ptr = NULL, *old_data = NULL; +	char *old_key = NULL; +	char *name, *p; +	int ret; + +	data_ptr = zalloc(sizeof(*data_ptr)); +	if (!data_ptr) +		return -ENOMEM; + +	name = strdup(ref->metric_name); +	if (!name) { +		free(data_ptr); +		return -ENOMEM;  	} -	ret = hashmap__set(&ctx->ids, name, val_ptr, -			   (const void **)&old_key, (void **)&old_val); + +	/* +	 * The jevents tool converts all metric expressions +	 * to lowercase, including metric references, hence +	 * we need to add lowercase name for metric, so it's +	 * properly found. +	 */ +	for (p = name; *p; p++) +		*p = tolower(*p); + +	/* +	 * Intentionally passing just const char pointers, +	 * originally from 'struct pmu_event' object. +	 * We don't need to change them, so there's no +	 * need to create our own copy. +	 */ +	data_ptr->ref.metric_name = ref->metric_name; +	data_ptr->ref.metric_expr = ref->metric_expr; +	data_ptr->ref.counted = false; +	data_ptr->is_ref = true; + +	ret = hashmap__set(&ctx->ids, name, data_ptr, +			   (const void **)&old_key, (void **)&old_data); +	if (ret) +		free(data_ptr); + +	pr_debug2("adding ref metric %s: %s\n", +		  ref->metric_name, ref->metric_expr); +  	free(old_key); -	free(old_val); +	free(old_data);  	return ret;  } -int expr__get_id(struct expr_parse_ctx *ctx, const char *id, double *val_ptr) +int expr__get_id(struct expr_parse_ctx *ctx, const char *id, +		 struct expr_id_data **data) +{ +	return hashmap__find(&ctx->ids, id, (void **)data) ? 0 : -1; +} + +int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id, +		     struct expr_id_data **datap)  { -	double *data; +	struct expr_id_data *data; -	if (!hashmap__find(&ctx->ids, id, (void **)&data)) +	if (expr__get_id(ctx, id, datap) || !*datap) { +		pr_debug("%s not found\n", id);  		return -1; -	*val_ptr = (data == NULL) ?  0.0 : *data; +	} + +	data = *datap; + +	pr_debug2("lookup: is_ref %d, counted %d, val %f: %s\n", +		  data->is_ref, data->ref.counted, data->val, id); + +	if (data->is_ref && !data->ref.counted) { +		data->ref.counted = true; +		pr_debug("processing metric: %s ENTRY\n", id); +		if (expr__parse(&data->val, ctx, data->ref.metric_expr, 1)) { +			pr_debug("%s failed to count\n", id); +			return -1; +		} +		pr_debug("processing metric: %s EXIT: %f\n", id, data->val); +	} +  	return 0;  } +void expr__del_id(struct expr_parse_ctx *ctx, const char *id) +{ +	struct expr_id_data *old_val = NULL; +	char *old_key = NULL; + +	hashmap__delete(&ctx->ids, id, +			(const void **)&old_key, (void **)&old_val); +	free(old_key); +	free(old_val); +} +  void expr__ctx_init(struct expr_parse_ctx *ctx)  {  	hashmap__init(&ctx->ids, key_hash, key_equal, NULL); @@ -88,6 +204,8 @@ __expr__parse(double *val, struct expr_parse_ctx *ctx, const char *expr,  	void *scanner;  	int ret; +	pr_debug2("parsing metric: %s\n", expr); +  	ret = expr_lex_init_extra(&scanner_ctx, &scanner);  	if (ret)  		return ret; @@ -116,16 +234,10 @@ int expr__parse(double *final_val, struct expr_parse_ctx *ctx,  int expr__find_other(const char *expr, const char *one,  		     struct expr_parse_ctx *ctx, int runtime)  { -	double *old_val = NULL; -	char *old_key = NULL;  	int ret = __expr__parse(NULL, ctx, expr, EXPR_OTHER, runtime); -	if (one) { -		hashmap__delete(&ctx->ids, one, -				(const void **)&old_key, (void **)&old_val); -		free(old_key); -		free(old_val); -	} +	if (one) +		expr__del_id(ctx, one);  	return ret;  }  | 
