perf tools: Parse aux-action

Add parsing for aux-action to accept "pause", "resume" or "start-paused"
values.

"start-paused" is valid only for AUX area events.

"pause" and "resume" are valid only for events grouped with an AUX area
event as the group leader.  However, like with aux-output, the events
will be automatically grouped if they are not currently in a group, and
the AUX area event precedes the other events.

Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20241216070244.14450-4-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Adrian Hunter 2024-12-16 09:02:39 +02:00 committed by Arnaldo Carvalho de Melo
parent 314bf84e03
commit 8a0f49a7f1
5 changed files with 74 additions and 8 deletions

View File

@ -68,6 +68,10 @@ OPTIONS
like this: name=\'CPU_CLK_UNHALTED.THREAD:cmask=0x1\'.
- 'aux-output': Generate AUX records instead of events. This requires
that an AUX area event is also provided.
- 'aux-action': "pause" or "resume" to pause or resume an AUX
area event (the group leader) when this event occurs.
"start-paused" on an AUX area event itself, will
start in a paused state.
- 'aux-sample-size': Set sample size for AUX area sampling. If the
'--aux-sample' option has been used, set aux-sample-size=0 to disable
AUX area sampling for the event.

View File

@ -860,7 +860,9 @@ static int record__auxtrace_init(struct record *rec)
if (err)
return err;
auxtrace_regroup_aux_output(rec->evlist);
err = auxtrace_parse_aux_action(rec->evlist);
if (err)
return err;
return auxtrace_parse_filters(rec->evlist);
}

View File

@ -810,19 +810,76 @@ no_opt:
return auxtrace_validate_aux_sample_size(evlist, opts);
}
void auxtrace_regroup_aux_output(struct evlist *evlist)
static struct aux_action_opt {
const char *str;
u32 aux_action;
bool aux_event_opt;
} aux_action_opts[] = {
{"start-paused", BIT(0), true},
{"pause", BIT(1), false},
{"resume", BIT(2), false},
{.str = NULL},
};
static const struct aux_action_opt *auxtrace_parse_aux_action_str(const char *str)
{
const struct aux_action_opt *opt;
if (!str)
return NULL;
for (opt = aux_action_opts; opt->str; opt++)
if (!strcmp(str, opt->str))
return opt;
return NULL;
}
int auxtrace_parse_aux_action(struct evlist *evlist)
{
struct evsel *evsel, *aux_evsel = NULL;
struct evsel_config_term *term;
struct evsel *aux_evsel = NULL;
struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (evsel__is_aux_event(evsel))
bool is_aux_event = evsel__is_aux_event(evsel);
const struct aux_action_opt *opt;
if (is_aux_event)
aux_evsel = evsel;
term = evsel__get_config_term(evsel, AUX_OUTPUT);
term = evsel__get_config_term(evsel, AUX_ACTION);
if (!term) {
if (evsel__get_config_term(evsel, AUX_OUTPUT))
goto regroup;
continue;
}
opt = auxtrace_parse_aux_action_str(term->val.str);
if (!opt) {
pr_err("Bad aux-action '%s'\n", term->val.str);
return -EINVAL;
}
if (opt->aux_event_opt && !is_aux_event) {
pr_err("aux-action '%s' can only be used with AUX area event\n",
term->val.str);
return -EINVAL;
}
if (!opt->aux_event_opt && is_aux_event) {
pr_err("aux-action '%s' cannot be used for AUX area event itself\n",
term->val.str);
return -EINVAL;
}
evsel->core.attr.aux_action = opt->aux_action;
regroup:
/* If possible, group with the AUX event */
if (term && aux_evsel)
if (aux_evsel)
evlist__regroup(evlist, aux_evsel, evsel);
if (!evsel__is_aux_event(evsel__leader(evsel))) {
pr_err("Events with aux-action must have AUX area event group leader\n");
return -EINVAL;
}
}
return 0;
}
struct auxtrace_record *__weak

View File

@ -578,7 +578,7 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
int auxtrace_parse_sample_options(struct auxtrace_record *itr,
struct evlist *evlist,
struct record_opts *opts, const char *str);
void auxtrace_regroup_aux_output(struct evlist *evlist);
int auxtrace_parse_aux_action(struct evlist *evlist);
int auxtrace_record__options(struct auxtrace_record *itr,
struct evlist *evlist,
struct record_opts *opts);
@ -799,8 +799,10 @@ int auxtrace_parse_sample_options(struct auxtrace_record *itr __maybe_unused,
}
static inline
void auxtrace_regroup_aux_output(struct evlist *evlist __maybe_unused)
int auxtrace_parse_aux_action(struct evlist *evlist __maybe_unused)
{
pr_err("AUX area tracing not supported\n");
return -EINVAL;
}
static inline

View File

@ -1152,6 +1152,7 @@ static void evsel__apply_config_terms(struct evsel *evsel,
attr->aux_output = term->val.aux_output ? 1 : 0;
break;
case EVSEL__CONFIG_TERM_AUX_ACTION:
/* Already applied by auxtrace */
break;
case EVSEL__CONFIG_TERM_AUX_SAMPLE_SIZE:
/* Already applied by auxtrace */