diff options
Diffstat (limited to 'tools/perf/util/expr.c')
| -rw-r--r-- | tools/perf/util/expr.c | 68 | 
1 files changed, 59 insertions, 9 deletions
diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c index 53482ef53c41..a850fd0be3ee 100644 --- a/tools/perf/util/expr.c +++ b/tools/perf/util/expr.c @@ -17,6 +17,29 @@  extern int expr_debug;  #endif +struct expr_id_data { +	union { +		double val; +		struct { +			double val; +			const char *metric_name; +			const char *metric_expr; +		} ref; +		struct expr_id	*parent; +	}; + +	enum { +		/* Holding a double value. */ +		EXPR_ID_DATA__VALUE, +		/* Reference to another metric. */ +		EXPR_ID_DATA__REF, +		/* A reference but the value has been computed. */ +		EXPR_ID_DATA__REF_VALUE, +		/* A parent is remembered for the recursion check. */ +		EXPR_ID_DATA__PARENT, +	} kind; +}; +  static size_t key_hash(const void *key, void *ctx __maybe_unused)  {  	const char *str = (const char *)key; @@ -48,6 +71,7 @@ int expr__add_id(struct expr_parse_ctx *ctx, const char *id)  		return -ENOMEM;  	data_ptr->parent = ctx->parent; +	data_ptr->kind = EXPR_ID_DATA__PARENT;  	ret = hashmap__set(&ctx->ids, id, data_ptr,  			   (const void **)&old_key, (void **)&old_data); @@ -69,7 +93,7 @@ int expr__add_id_val(struct expr_parse_ctx *ctx, const char *id, double val)  	if (!data_ptr)  		return -ENOMEM;  	data_ptr->val = val; -	data_ptr->is_ref = false; +	data_ptr->kind = EXPR_ID_DATA__VALUE;  	ret = hashmap__set(&ctx->ids, id, data_ptr,  			   (const void **)&old_key, (void **)&old_data); @@ -114,8 +138,7 @@ int expr__add_ref(struct expr_parse_ctx *ctx, struct metric_ref *ref)  	 */  	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; +	data_ptr->kind = EXPR_ID_DATA__REF;  	ret = hashmap__set(&ctx->ids, name, data_ptr,  			   (const void **)&old_key, (void **)&old_data); @@ -148,17 +171,30 @@ int expr__resolve_id(struct expr_parse_ctx *ctx, const char *id,  	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; +	switch (data->kind) { +	case EXPR_ID_DATA__VALUE: +		pr_debug2("lookup(%s): val %f\n", id, data->val); +		break; +	case EXPR_ID_DATA__PARENT: +		pr_debug2("lookup(%s): parent %s\n", id, data->parent->id); +		break; +	case EXPR_ID_DATA__REF: +		pr_debug2("lookup(%s): ref metric name %s\n", id, +			data->ref.metric_name);  		pr_debug("processing metric: %s ENTRY\n", id); -		if (expr__parse(&data->val, ctx, data->ref.metric_expr, 1)) { +		data->kind = EXPR_ID_DATA__REF_VALUE; +		if (expr__parse(&data->ref.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); +		break; +	case EXPR_ID_DATA__REF_VALUE: +		pr_debug2("lookup(%s): ref val %f metric name %s\n", id, +			data->ref.val, data->ref.metric_name); +		break; +	default: +		assert(0);  /* Unreachable. */  	}  	return 0; @@ -241,3 +277,17 @@ int expr__find_other(const char *expr, const char *one,  	return ret;  } + +double expr_id_data__value(const struct expr_id_data *data) +{ +	if (data->kind == EXPR_ID_DATA__VALUE) +		return data->val; +	assert(data->kind == EXPR_ID_DATA__REF_VALUE); +	return data->ref.val; +} + +struct expr_id *expr_id_data__parent(struct expr_id_data *data) +{ +	assert(data->kind == EXPR_ID_DATA__PARENT); +	return data->parent; +}  | 
