diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index a5969fa64503529fc0636d99090f1f39f636733e..e7417fe97a9775eae8712d5bb58be2db0d1d7363 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -326,7 +326,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) "Show event group information together"), OPT_END() }; - int ret; + int ret = hists__init(); + + if (ret < 0) + return ret; argc = parse_options(argc, argv, options, annotate_usage, 0); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 8043b5a7240a19ef8973e5764b2e46a73d4c5934..2cfc4b93991f71008ec336825f207831f6351720 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -568,7 +568,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) struct stat st; bool has_br_stack = false; int branch_mode = -1; - int ret = -1; char callchain_default_opt[] = "fractal,0.5,callee"; const char * const report_usage[] = { "perf report []", @@ -695,6 +694,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) struct perf_data_file file = { .mode = PERF_DATA_MODE_READ, }; + int ret = hists__init(); + + if (ret < 0) + return ret; perf_config(report__config, &report); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 8ab9716db5931b3140f71a8714d1b1a24b963f06..0aa7747ff1390e0995a875a6c185697901cb9632 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1047,7 +1047,6 @@ parse_percent_limit(const struct option *opt, const char *arg, int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) { - int status = -1; char errbuf[BUFSIZ]; struct perf_top top = { .count_filter = 5, @@ -1165,6 +1164,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) "perf top []", NULL }; + int status = hists__init(); + + if (status < 0) + return status; top.evlist = perf_evlist__new(); if (top.evlist == NULL) diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index ac655b0700e7648335cc15c45a560c80f35ae27c..162c978f1491a9e49dd6f37e1dd34ccb40d2a540 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c @@ -6,6 +6,7 @@ #include #include #include "builtin.h" +#include "hist.h" #include "intlist.h" #include "tests.h" #include "debug.h" @@ -302,6 +303,10 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) OPT_END() }; struct intlist *skiplist = NULL; + int ret = hists__init(); + + if (ret < 0) + return ret; argc = parse_options(argc, argv, test_options, test_usage, 0); if (argc >= 1 && !strcmp(argv[0], "list")) diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index a0837642744862b792a51165cee7f2fc6320cb1a..7a3c4c47ceda3f0ba3d4414c8d5f7f8d689b9fc2 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -159,16 +159,6 @@ void perf_evsel__calc_id_pos(struct perf_evsel *evsel) evsel->is_pos = __perf_evsel__calc_is_pos(evsel->attr.sample_type); } -void hists__init(struct hists *hists) -{ - memset(hists, 0, sizeof(*hists)); - hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; - hists->entries_in = &hists->entries_in_array[0]; - hists->entries_collapsed = RB_ROOT; - hists->entries = RB_ROOT; - pthread_mutex_init(&hists->lock, NULL); -} - void __perf_evsel__set_sample_bit(struct perf_evsel *evsel, enum perf_event_sample_format bit) { @@ -211,7 +201,6 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->unit = ""; evsel->scale = 1.0; INIT_LIST_HEAD(&evsel->node); - hists__init(&evsel->hists); perf_evsel__object.init(evsel); evsel->sample_size = __perf_evsel__sample_size(attr->sample_type); perf_evsel__calc_id_pos(evsel); diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index d6325106c8fd4d8b45dea14d954a506e7a8f19d6..fee927404720a16797b4b1981575ee95f6c17cb5 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -8,7 +8,6 @@ #include #include "xyarray.h" #include "cgroup.h" -#include "hist.h" #include "symbol.h" struct perf_counts_values { @@ -66,7 +65,6 @@ struct perf_evsel { struct perf_counts *prev_raw_counts; int idx; u32 ids; - struct hists hists; char *name; double scale; const char *unit; @@ -100,13 +98,6 @@ union u64_swap { u32 val32[2]; }; -#define hists_to_evsel(h) container_of(h, struct perf_evsel, hists) - -static inline struct hists *evsel__hists(struct perf_evsel *evsel) -{ - return &evsel->hists; -} - struct cpu_map; struct thread_map; struct perf_evlist; @@ -290,8 +281,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel, return __perf_evsel__read(evsel, ncpus, nthreads, true); } -void hists__init(struct hists *hists); - int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, struct perf_sample *sample); diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index b143e404e5b135e90b841a1a2414bb383476ebe8..6e88b9e395df67abb0458eea80878112acab0b0a 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1447,3 +1447,31 @@ int perf_hist_config(const char *var, const char *value) return 0; } + +static int hists_evsel__init(struct perf_evsel *evsel) +{ + struct hists *hists = evsel__hists(evsel); + + memset(hists, 0, sizeof(*hists)); + hists->entries_in_array[0] = hists->entries_in_array[1] = RB_ROOT; + hists->entries_in = &hists->entries_in_array[0]; + hists->entries_collapsed = RB_ROOT; + hists->entries = RB_ROOT; + pthread_mutex_init(&hists->lock, NULL); + return 0; +} + +/* + * XXX We probably need a hists_evsel__exit() to free the hist_entries + * stored in the rbtree... + */ + +int hists__init(void) +{ + int err = perf_evsel__object_config(sizeof(struct hists_evsel), + hists_evsel__init, NULL); + if (err) + fputs("FATAL ERROR: Couldn't setup hists class\n", stderr); + + return err; +} diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index ebfc25886cac56546e49461438f1a31c8e74dbb8..d0ef9a19a7445caaf7bdc1d21b42ea2d1087a2a9 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -4,6 +4,7 @@ #include #include #include "callchain.h" +#include "evsel.h" #include "header.h" #include "color.h" #include "ui/progress.h" @@ -158,6 +159,25 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he); void hists__match(struct hists *leader, struct hists *other); int hists__link(struct hists *leader, struct hists *other); +struct hists_evsel { + struct perf_evsel evsel; + struct hists hists; +}; + +static inline struct perf_evsel *hists_to_evsel(struct hists *hists) +{ + struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists); + return &hevsel->evsel; +} + +static inline struct hists *evsel__hists(struct perf_evsel *evsel) +{ + struct hists_evsel *hevsel = (struct hists_evsel *)evsel; + return &hevsel->hists; +} + +int hists__init(void); + struct perf_hpp { char *buf; size_t size;