From patchwork Thu Jun 23 05:27:41 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wang Nan X-Patchwork-Id: 70731 Delivered-To: patch@linaro.org Received: by 10.140.28.4 with SMTP id 4csp250334qgy; Wed, 22 Jun 2016 22:29:31 -0700 (PDT) X-Received: by 10.66.132.72 with SMTP id os8mr40047975pab.63.1466659767573; Wed, 22 Jun 2016 22:29:27 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id i82si4592799pfd.11.2016.06.22.22.29.26; Wed, 22 Jun 2016 22:29:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752202AbcFWF27 (ORCPT + 30 others); Thu, 23 Jun 2016 01:28:59 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:58339 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752101AbcFWF2y (ORCPT ); Thu, 23 Jun 2016 01:28:54 -0400 Received: from 172.24.1.137 (EHLO szxeml431-hub.china.huawei.com) ([172.24.1.137]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DJF20261; Thu, 23 Jun 2016 13:28:38 +0800 (CST) Received: from linux-4hy3.site (10.107.193.248) by szxeml431-hub.china.huawei.com (10.82.67.208) with Microsoft SMTP Server id 14.3.235.1; Thu, 23 Jun 2016 13:28:30 +0800 From: Wang Nan To: CC: , , Wang Nan , He Kuang , Jiri Olsa , Masami Hiramatsu , Namhyung Kim , Zefan Li Subject: [PATCH v10 04/10] perf evlist: Introduce aux evlist Date: Thu, 23 Jun 2016 05:27:41 +0000 Message-ID: <1466659667-99144-5-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1466659667-99144-1-git-send-email-wangnan0@huawei.com> References: <1466659667-99144-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090206.576B7387.0065, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 176517bd502220b1c165ae955aebd1c3 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org An auxiliary evlist is created by perf_evlist__new_aux() using an existing evlist as its parent. An auxiliary evlist can have its own 'struct perf_mmap', but can't have any other data. User should use its parent instead when accessing other data. Auxiliary evlists are containers of 'struct perf_mmap'. It is introduced to allow its parent evlist to map different events into separated mmaps. Following commits create an auxiliary evlist for overwritable events, because overwritable events need a read only and backwards ring buffer, which is different from normal events. To achieve this goal, this patch carefully changes 'evlist' to 'evlist->parent' in all functions in the path of 'perf_evlist__mmap_ex', except 'evlist->mmap' related operations, to make sure all evlist modifications (like pollfd and event id hash tables) goes to original evlist. A 'evlist->parent' pointer is added to 'struct perf_evlist' and points to the evlist itself for normal evlists. Children of one evlist are linked into it so one can find all children from its parent. To avoid potential complexity, forbid creating aux evlist from another aux evlist. Improve perf_evlist__munmap_filtered(), so when recording, if an event is terminated, unmap mmaps, from parent and children. Signed-off-by: Wang Nan Cc: He Kuang Cc: Jiri Olsa Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com --- tools/perf/util/evlist.c | 49 +++++++++++++++++++++++++++++++++++++----------- tools/perf/util/evlist.h | 12 ++++++++++++ 2 files changed, 50 insertions(+), 11 deletions(-) -- 1.8.3.4 diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index fcb8f1f..ef2e920 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -41,10 +41,12 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, for (i = 0; i < PERF_EVLIST__HLIST_SIZE; ++i) INIT_HLIST_HEAD(&evlist->heads[i]); INIT_LIST_HEAD(&evlist->entries); + INIT_LIST_HEAD(&evlist->children); perf_evlist__set_maps(evlist, cpus, threads); fdarray__init(&evlist->pollfd, 64); evlist->workload.pid = -1; evlist->backward = false; + evlist->parent = evlist; } struct perf_evlist *perf_evlist__new(void) @@ -490,13 +492,17 @@ static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd, void *arg __maybe_unused) { struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); + struct perf_evlist *child; perf_evlist__mmap_put(evlist, fda->priv[fd].idx); + list_for_each_entry(child, &evlist->children, list) + perf_evlist__mmap_put(child, fda->priv[fd].idx); + } int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) { - return fdarray__filter(&evlist->pollfd, revents_and_mask, + return fdarray__filter(&evlist->parent->pollfd, revents_and_mask, perf_evlist__munmap_filtered, NULL); } @@ -1015,7 +1021,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, struct perf_evsel *evsel; int revent; - evlist__for_each(evlist, evsel) { + evlist__for_each(evlist->parent, evsel) { int fd; if (evsel->overwrite != (evlist->overwrite && evlist->backward)) @@ -1047,16 +1053,16 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, * Therefore don't add it for polling. */ if (!evsel->system_wide && - __perf_evlist__add_pollfd(evlist, fd, idx, revent) < 0) { + __perf_evlist__add_pollfd(evlist->parent, fd, idx, revent) < 0) { perf_evlist__mmap_put(evlist, idx); return -1; } if (evsel->attr.read_format & PERF_FORMAT_ID) { - if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, + if (perf_evlist__id_add_fd(evlist->parent, evsel, cpu, thread, fd) < 0) return -1; - perf_evlist__set_sid_idx(evlist, evsel, idx, cpu, + perf_evlist__set_sid_idx(evlist->parent, evsel, idx, cpu, thread); } } @@ -1097,13 +1103,13 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, struct mmap_params *mp) { int thread; - int nr_threads = thread_map__nr(evlist->threads); + int nr_threads = thread_map__nr(evlist->parent->threads); pr_debug2("perf event ring buffer mmapped per thread\n"); for (thread = 0; thread < nr_threads; thread++) { int output = -1; - auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, + auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist->parent, thread, false); if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, @@ -1242,8 +1248,8 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, bool auxtrace_overwrite) { struct perf_evsel *evsel; - const struct cpu_map *cpus = evlist->cpus; - const struct thread_map *threads = evlist->threads; + const struct cpu_map *cpus = evlist->parent->cpus; + const struct thread_map *threads = evlist->parent->threads; struct mmap_params mp = { .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), }; @@ -1251,7 +1257,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) return -ENOMEM; - if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) + if (evlist->parent->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist->parent) < 0) return -ENOMEM; evlist->overwrite = overwrite; @@ -1262,7 +1268,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, auxtrace_pages, auxtrace_overwrite); - evlist__for_each(evlist, evsel) { + evlist__for_each(evlist->parent, evsel) { if ((evsel->attr.read_format & PERF_FORMAT_ID) && evsel->sample_id == NULL && perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) @@ -1919,3 +1925,24 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, return NULL; } + +struct perf_evlist *perf_evlist__new_aux(struct perf_evlist *parent) +{ + struct perf_evlist *evlist; + + if (perf_evlist__is_aux(parent)) { + pr_err("Internal error: create aux evlist from another aux evlist\n"); + return NULL; + } + + evlist = zalloc(sizeof(*evlist)); + if (!evlist) + return NULL; + + perf_evlist__init(evlist, parent->cpus, parent->threads); + evlist->parent = parent; + INIT_LIST_HEAD(&evlist->list); + list_add(&evlist->list, &parent->children); + + return evlist; +} diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 68cb136..5b50692 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -37,6 +37,10 @@ struct perf_mmap { struct perf_evlist { struct list_head entries; + union { + struct list_head children; + struct list_head list; + }; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; int nr_groups; @@ -60,8 +64,14 @@ struct perf_evlist { struct perf_evsel *selected; struct events_stats stats; struct perf_env *env; + struct perf_evlist *parent; }; +static inline bool perf_evlist__is_aux(struct perf_evlist *evlist) +{ + return evlist->parent != evlist; +} + struct perf_evsel_str_handler { const char *name; void *handler; @@ -70,6 +80,8 @@ struct perf_evsel_str_handler { struct perf_evlist *perf_evlist__new(void); struct perf_evlist *perf_evlist__new_default(void); struct perf_evlist *perf_evlist__new_dummy(void); +struct perf_evlist *perf_evlist__new_aux(struct perf_evlist *); + void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads); void perf_evlist__exit(struct perf_evlist *evlist);