]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
perf record: Add aux-sample-size config term
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 15 Nov 2019 12:42:17 +0000 (14:42 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 22 Nov 2019 13:48:13 +0000 (10:48 -0300)
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>
tools/perf/Documentation/perf-record.txt
tools/perf/util/auxtrace.c
tools/perf/util/evsel.c
tools/perf/util/evsel_config.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l

index e216d7b529c92483a544cbd8a08264743c291dff..b23a4012a6064eed3e8353068f79c0fdd67972d2 100644 (file)
@@ -62,6 +62,9 @@ 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-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.
 
           See the linkperf:perf-list[1] man page for more parameters.
 
index 51fbe01f8a1196fdbf299d6c403e75e72702efd4..026585b67a3c55768b9ffef826378e5843f5da9c 100644 (file)
@@ -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);
 }
index 772f4879c4923060e6923801f2eb4858f341f8ad..ad7665a546cf15bec2c1f5fb879209e0bd2c3cf8 100644 (file)
@@ -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:
  *
index 8a7648037c18efc499a3640b84d455fe258151f7..6e654ede8fbe26053d135cf9f0b67b8afbe00622 100644 (file)
@@ -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
index 6bae9d6edc121bd21e4652ba509ef6b6b09890bd..fc5e27bc8315b9b5da829687bbb7dc7301b93114 100644 (file)
@@ -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;
                }
index ff367f248fe829595408ec5fa6e7c6a9822f00d2..27596cbd0ba06a73af36557d818dbeb71ef91ed0 100644 (file)
@@ -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,
 };
 
index 7469497cd28e4c25b873c3b02ec9c09b8846a368..7b1c8ee537cf6576941cae1b03681f57db0c8a03 100644 (file)
@@ -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); }