diff options
| author | 2019-11-15 14:42:17 +0200 | |
|---|---|---|
| committer | 2019-11-22 10:48:13 -0300 | |
| commit | eb7a52d46c6ac95df563f867d526b3d46616b10b (patch) | |
| tree | a5125438d96512fdd938e1618327b929dd566cef /tools/perf/util | |
| parent | perf record: Add support for AUX area sampling (diff) | |
| download | wireguard-linux-eb7a52d46c6ac95df563f867d526b3d46616b10b.tar.xz wireguard-linux-eb7a52d46c6ac95df563f867d526b3d46616b10b.zip  | |
perf record: Add aux-sample-size config term
To allow individual events to be selected for AUX area sampling, add
aux-sample-size config term. attr.aux_sample_size is updated by
auxtrace_parse_sample_options() so that the existing validation will see
the value. Any event that has a non-zero aux_sample_size will cause AUX
area sampling to be configured, irrespective of the --aux-sample option.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lore.kernel.org/lkml/20191115124225.5247-8-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/auxtrace.c | 76 | ||||
| -rw-r--r-- | tools/perf/util/evsel.c | 16 | ||||
| -rw-r--r-- | tools/perf/util/evsel_config.h | 11 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.c | 14 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.l | 1 | 
6 files changed, 118 insertions, 1 deletions
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 51fbe01f8a11..026585b67a3c 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -31,6 +31,7 @@  #include "map.h"  #include "pmu.h"  #include "evsel.h" +#include "evsel_config.h"  #include "symbol.h"  #include "util/synthetic-events.h"  #include "thread_map.h" @@ -76,6 +77,53 @@ static bool perf_evsel__is_aux_event(struct evsel *evsel)  	return pmu && pmu->auxtrace;  } +/* + * Make a group from 'leader' to 'last', requiring that the events were not + * already grouped to a different leader. + */ +static int perf_evlist__regroup(struct evlist *evlist, +				struct evsel *leader, +				struct evsel *last) +{ +	struct evsel *evsel; +	bool grp; + +	if (!perf_evsel__is_group_leader(leader)) +		return -EINVAL; + +	grp = false; +	evlist__for_each_entry(evlist, evsel) { +		if (grp) { +			if (!(evsel->leader == leader || +			     (evsel->leader == evsel && +			      evsel->core.nr_members <= 1))) +				return -EINVAL; +		} else if (evsel == leader) { +			grp = true; +		} +		if (evsel == last) +			break; +	} + +	grp = false; +	evlist__for_each_entry(evlist, evsel) { +		if (grp) { +			if (evsel->leader != leader) { +				evsel->leader = leader; +				if (leader->core.nr_members < 1) +					leader->core.nr_members = 1; +				leader->core.nr_members += 1; +			} +		} else if (evsel == leader) { +			grp = true; +		} +		if (evsel == last) +			break; +	} + +	return 0; +} +  static bool auxtrace__dont_decode(struct perf_session *session)  {  	return !session->itrace_synth_opts || @@ -679,13 +727,16 @@ int auxtrace_parse_sample_options(struct auxtrace_record *itr,  				  struct evlist *evlist,  				  struct record_opts *opts, const char *str)  { +	struct perf_evsel_config_term *term; +	struct evsel *aux_evsel; +	bool has_aux_sample_size = false;  	bool has_aux_leader = false;  	struct evsel *evsel;  	char *endptr;  	unsigned long sz;  	if (!str) -		return 0; +		goto no_opt;  	if (!itr) {  		pr_err("No AUX area event to sample\n"); @@ -712,6 +763,29 @@ int auxtrace_parse_sample_options(struct auxtrace_record *itr,  			evsel->core.attr.aux_sample_size = sz;  		}  	} +no_opt: +	aux_evsel = NULL; +	/* Override with aux_sample_size from config term */ +	evlist__for_each_entry(evlist, evsel) { +		if (perf_evsel__is_aux_event(evsel)) +			aux_evsel = evsel; +		term = perf_evsel__get_config_term(evsel, AUX_SAMPLE_SIZE); +		if (term) { +			has_aux_sample_size = true; +			evsel->core.attr.aux_sample_size = term->val.aux_sample_size; +			/* If possible, group with the AUX event */ +			if (aux_evsel && evsel->core.attr.aux_sample_size) +				perf_evlist__regroup(evlist, aux_evsel, evsel); +		} +	} + +	if (!str && !has_aux_sample_size) +		return 0; + +	if (!itr) { +		pr_err("No AUX area event to sample\n"); +		return -EINVAL; +	}  	return auxtrace_validate_aux_sample_size(evlist, opts);  } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 772f4879c492..ad7665a546cf 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -846,6 +846,9 @@ static void apply_config_terms(struct evsel *evsel,  		case PERF_EVSEL__CONFIG_TERM_AUX_OUTPUT:  			attr->aux_output = term->val.aux_output ? 1 : 0;  			break; +		case PERF_EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE: +			/* Already applied by auxtrace */ +			break;  		default:  			break;  		} @@ -905,6 +908,19 @@ static bool is_dummy_event(struct evsel *evsel)  	       (evsel->core.attr.config == PERF_COUNT_SW_DUMMY);  } +struct perf_evsel_config_term *__perf_evsel__get_config_term(struct evsel *evsel, +							     enum evsel_term_type type) +{ +	struct perf_evsel_config_term *term, *found_term = NULL; + +	list_for_each_entry(term, &evsel->config_terms, list) { +		if (term->type == type) +			found_term = term; +	} + +	return found_term; +} +  /*   * The enable_on_exec/disabled value strategy:   * diff --git a/tools/perf/util/evsel_config.h b/tools/perf/util/evsel_config.h index 8a7648037c18..6e654ede8fbe 100644 --- a/tools/perf/util/evsel_config.h +++ b/tools/perf/util/evsel_config.h @@ -25,6 +25,7 @@ enum evsel_term_type {  	PERF_EVSEL__CONFIG_TERM_BRANCH,  	PERF_EVSEL__CONFIG_TERM_PERCORE,  	PERF_EVSEL__CONFIG_TERM_AUX_OUTPUT, +	PERF_EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE,  };  struct perf_evsel_config_term { @@ -44,7 +45,17 @@ struct perf_evsel_config_term {  		unsigned long max_events;  		bool	      percore;  		bool	      aux_output; +		u32	      aux_sample_size;  	} val;  	bool weak;  }; + +struct evsel; + +struct perf_evsel_config_term *__perf_evsel__get_config_term(struct evsel *evsel, +							     enum evsel_term_type type); + +#define perf_evsel__get_config_term(evsel, type) \ +	__perf_evsel__get_config_term(evsel, PERF_EVSEL__CONFIG_TERM_ ## type) +  #endif // __PERF_EVSEL_CONFIG_H diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 6bae9d6edc12..fc5e27bc8315 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -996,6 +996,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {  	[PARSE_EVENTS__TERM_TYPE_DRV_CFG]		= "driver-config",  	[PARSE_EVENTS__TERM_TYPE_PERCORE]		= "percore",  	[PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT]		= "aux-output", +	[PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE]	= "aux-sample-size",  };  static bool config_term_shrinked; @@ -1126,6 +1127,15 @@ do {									   \  	case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:  		CHECK_TYPE_VAL(NUM);  		break; +	case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: +		CHECK_TYPE_VAL(NUM); +		if (term->val.num > UINT_MAX) { +			parse_events__handle_error(err, term->err_val, +						strdup("too big"), +						NULL); +			return -EINVAL; +		} +		break;  	default:  		parse_events__handle_error(err, term->err_term,  				strdup("unknown term"), @@ -1177,6 +1187,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,  	case PARSE_EVENTS__TERM_TYPE_OVERWRITE:  	case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:  	case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT: +	case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE:  		return config_term_common(attr, term, err);  	default:  		if (err) { @@ -1272,6 +1283,9 @@ do {								\  		case PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT:  			ADD_CONFIG_TERM(AUX_OUTPUT, aux_output, term->val.num ? 1 : 0);  			break; +		case PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE: +			ADD_CONFIG_TERM(AUX_SAMPLE_SIZE, aux_sample_size, term->val.num); +			break;  		default:  			break;  		} diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index ff367f248fe8..27596cbd0ba0 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -77,6 +77,7 @@ enum {  	PARSE_EVENTS__TERM_TYPE_DRV_CFG,  	PARSE_EVENTS__TERM_TYPE_PERCORE,  	PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT, +	PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE,  	__PARSE_EVENTS__TERM_TYPE_NR,  }; diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l index 7469497cd28e..7b1c8ee537cf 100644 --- a/tools/perf/util/parse-events.l +++ b/tools/perf/util/parse-events.l @@ -285,6 +285,7 @@ overwrite		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }  no-overwrite		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }  percore			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_PERCORE); }  aux-output		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_OUTPUT); } +aux-sample-size		{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_AUX_SAMPLE_SIZE); }  ,			{ return ','; }  "/"			{ BEGIN(INITIAL); return '/'; }  {name_minus}		{ return str(yyscanner, PE_NAME); }  | 
