From 564132f3116cf376fdc04b2380e621f35efbb6c7 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 18 Jan 2016 10:24:09 +0100 Subject: [PATCH] perf hists: Properly release format fields With multiple list holding format entries, we need the support properly releasing format output/sort fields. Signed-off-by: Jiri Olsa Cc: David Ahern Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1453109064-1026-12-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/hist.c | 8 ++++++++ tools/perf/util/hist.h | 1 + tools/perf/util/sort.c | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 80d63a997287..2cd1a03bf375 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -583,6 +583,12 @@ next: } } +static void fmt_free(struct perf_hpp_fmt *fmt) +{ + if (fmt->free) + fmt->free(fmt); +} + void perf_hpp__reset_output_field(void) { struct perf_hpp_fmt *fmt, *tmp; @@ -591,12 +597,14 @@ void perf_hpp__reset_output_field(void) perf_hpp__for_each_format_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } /* reset sort keys */ perf_hpp__for_each_sort_list_safe(fmt, tmp) { list_del_init(&fmt->list); list_del_init(&fmt->sort_list); + fmt_free(fmt); } } diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 1f9e21dd53f3..f3bcf2d38733 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -216,6 +216,7 @@ struct perf_hpp_fmt { int64_t (*sort)(struct perf_hpp_fmt *fmt, struct hist_entry *a, struct hist_entry *b); bool (*equal)(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b); + void (*free)(struct perf_hpp_fmt *fmt); struct list_head list; struct list_head sort_list; diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 52e4a3674985..b5389a54356d 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1545,6 +1545,14 @@ static bool __sort__hpp_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) return hse_a->se == hse_b->se; } +static void hse_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_sort_entry *hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + free(hse); +} + static struct hpp_sort_entry * __sort_dimension__alloc_hpp(struct sort_dimension *sd) { @@ -1567,6 +1575,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.collapse = __sort__hpp_collapse; hse->hpp.sort = __sort__hpp_sort; hse->hpp.equal = __sort__hpp_equal; + hse->hpp.free = hse_free; INIT_LIST_HEAD(&hse->hpp.list); INIT_LIST_HEAD(&hse->hpp.sort_list); @@ -1577,6 +1586,11 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) return hse; } +static void hpp_free(struct perf_hpp_fmt *fmt) +{ + free(fmt); +} + static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) { struct perf_hpp_fmt *fmt; @@ -1585,6 +1599,7 @@ static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) if (fmt) { INIT_LIST_HEAD(&fmt->list); INIT_LIST_HEAD(&fmt->sort_list); + fmt->free = hpp_free; } return fmt; @@ -1818,6 +1833,14 @@ bool perf_hpp__is_dynamic_entry(struct perf_hpp_fmt *fmt) return fmt->cmp == __sort__hde_cmp; } +static void hde_free(struct perf_hpp_fmt *fmt) +{ + struct hpp_dynamic_entry *hde; + + hde = container_of(fmt, struct hpp_dynamic_entry, hpp); + free(hde); +} + static struct hpp_dynamic_entry * __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) { @@ -1842,6 +1865,7 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) hde->hpp.cmp = __sort__hde_cmp; hde->hpp.collapse = __sort__hde_cmp; hde->hpp.sort = __sort__hde_cmp; + hde->hpp.free = hde_free; INIT_LIST_HEAD(&hde->hpp.list); INIT_LIST_HEAD(&hde->hpp.sort_list);