Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932107AbbDOPIx (ORCPT ); Wed, 15 Apr 2015 11:08:53 -0400 Received: from mga14.intel.com ([192.55.52.115]:23699 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755122AbbDOPIr (ORCPT ); Wed, 15 Apr 2015 11:08:47 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.11,582,1422950400"; d="scan'208";a="714104619" From: Kan Liang To: acme@kernel.org, a.p.zijlstra@chello.nl Cc: eranian@google.com, andi@firstfloor.org, linux-kernel@vger.kernel.org, Kan Liang Subject: [PATCH V2 5/6] perf,tools: open/mmap event uses event's cpu map Date: Wed, 15 Apr 2015 03:56:15 -0400 Message-Id: <1429084576-1078-5-git-send-email-kan.liang@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1429084576-1078-1-git-send-email-kan.liang@intel.com> References: <1429084576-1078-1-git-send-email-kan.liang@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7718 Lines: 256 From: Kan Liang In perf_evlist__mmap, leader's fd has to be mmaped before member's fd. So evlist__for_each must be the outermost of the loop. Since different event's cpu list could vary, we cannot rely on the index to get group leader's fd. In get_group_fd, the cpu id is used to get correct fd. Signed-off-by: Kan Liang --- tools/perf/util/evlist.c | 104 +++++++++++++++++++++++++++-------------------- tools/perf/util/evsel.c | 28 +++++++++---- 2 files changed, 80 insertions(+), 52 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 16319b4..637fcf4 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -834,51 +834,48 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, return 0; } -static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, - struct mmap_params *mp, int cpu, - int thread, int *output) +static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, + struct perf_evsel *evsel, + int idx, struct mmap_params *mp, + int cpu, int thread, int *output) { - struct perf_evsel *evsel; + int fd; - evlist__for_each(evlist, evsel) { - int fd; + if (evsel->system_wide && thread) + return 0; - if (evsel->system_wide && thread) - continue; + fd = FD(evsel, cpu, thread); - fd = FD(evsel, cpu, thread); + if (*output == -1) { + *output = fd; + if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) + return -1; + } else { + if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) + return -1; - if (*output == -1) { - *output = fd; - if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) - return -1; - } else { - if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) - return -1; + perf_evlist__mmap_get(evlist, idx); + } - perf_evlist__mmap_get(evlist, idx); - } + /* + * The system_wide flag causes a selected event to be opened + * always without a pid. Consequently it will never get a + * POLLHUP, but it is used for tracking in combination with + * other events, so it should not need to be polled anyway. + * Therefore don't add it for polling. + */ + if (!evsel->system_wide && + __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { + perf_evlist__mmap_put(evlist, idx); + return -1; + } - /* - * The system_wide flag causes a selected event to be opened - * always without a pid. Consequently it will never get a - * POLLHUP, but it is used for tracking in combination with - * other events, so it should not need to be polled anyway. - * Therefore don't add it for polling. - */ - if (!evsel->system_wide && - __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { - perf_evlist__mmap_put(evlist, idx); + if (evsel->attr.read_format & PERF_FORMAT_ID) { + if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, + fd) < 0) return -1; - } - - if (evsel->attr.read_format & PERF_FORMAT_ID) { - if (perf_evlist__id_add_fd(evlist, evsel, cpu, thread, - fd) < 0) - return -1; - perf_evlist__set_sid_idx(evlist, evsel, idx, cpu, - thread); - } + perf_evlist__set_sid_idx(evlist, evsel, idx, cpu, + thread); } return 0; @@ -890,23 +887,37 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int cpu, thread; int nr_cpus = cpu_map__nr(evlist->cpus); int nr_threads = thread_map__nr(evlist->threads); + int *output = malloc(nr_cpus * sizeof(int)); + int evlist_cpu; + struct perf_evsel *evsel; pr_debug2("perf event ring buffer mmapped per cpu\n"); - for (cpu = 0; cpu < nr_cpus; cpu++) { - int output = -1; - for (thread = 0; thread < nr_threads; thread++) { - if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, - thread, &output)) + for (cpu = 0; cpu < nr_cpus; cpu++) + output[cpu] = -1; + + evlist__for_each(evlist, evsel) { + for (cpu = 0; cpu < cpu_map__nr(evsel->cpus); cpu++) { + evlist_cpu = perf_evsel__get_cpumap_index(evsel->cpus->map[cpu], evlist->cpus); + if (evlist_cpu < 0) goto out_unmap; + + for (thread = 0; thread < nr_threads; thread++) { + if (perf_evlist__mmap_per_evsel(evlist, evsel, evlist_cpu, + mp, cpu, thread, + &output[evlist_cpu])) + goto out_unmap; + } } } + free(output); return 0; out_unmap: for (cpu = 0; cpu < nr_cpus; cpu++) __perf_evlist__munmap(evlist, cpu); + free(output); return -1; } @@ -915,14 +926,17 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, { int thread; int nr_threads = thread_map__nr(evlist->threads); + struct perf_evsel *evsel; pr_debug2("perf event ring buffer mmapped per thread\n"); for (thread = 0; thread < nr_threads; thread++) { int output = -1; - if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, - &output)) - goto out_unmap; + evlist__for_each(evlist, evsel) { + if (perf_evlist__mmap_per_evsel(evlist, evsel, thread, + mp, 0, thread, &output)) + goto out_unmap; + } } return 0; diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index e177f43..44a663c 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1008,7 +1008,7 @@ int perf_evsel__get_cpumap_index(int cpu, struct cpu_map *evsel_cpus) static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) { struct perf_evsel *leader = evsel->leader; - int fd; + int fd, leader_cpu; if (perf_evsel__is_group_leader(evsel)) return -1; @@ -1019,7 +1019,15 @@ static int get_group_fd(struct perf_evsel *evsel, int cpu, int thread) */ BUG_ON(!leader->fd); - fd = FD(leader, cpu, thread); + if (cpu < 0) + fd = FD(leader, 0, thread); + else { + leader_cpu = perf_evsel__get_cpumap_index(cpu, leader->cpus); + if (leader_cpu >= 0) + fd = FD(leader, leader_cpu, thread); + else + return -1; + } BUG_ON(fd == -1); return fd; @@ -1151,15 +1159,21 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, int cpu, thread, nthreads; unsigned long flags = PERF_FLAG_FD_CLOEXEC; int pid = -1, err; + struct cpu_map *cpumap; enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; + if (evsel->cpus) + cpumap = evsel->cpus; + else + cpumap = cpus; + if (evsel->system_wide) nthreads = 1; else nthreads = threads->nr; if (evsel->fd == NULL && - perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0) + perf_evsel__alloc_fd(evsel, cpumap->nr, nthreads) < 0) return -ENOMEM; if (evsel->cgrp) { @@ -1191,7 +1205,7 @@ retry_sample_id: fprintf(stderr, "%.60s\n", graph_dotted_line); } - for (cpu = 0; cpu < cpus->nr; cpu++) { + for (cpu = 0; cpu < cpumap->nr; cpu++) { for (thread = 0; thread < nthreads; thread++) { int group_fd; @@ -1199,14 +1213,14 @@ retry_sample_id: if (!evsel->cgrp && !evsel->system_wide) pid = threads->map[thread]; - group_fd = get_group_fd(evsel, cpu, thread); + group_fd = get_group_fd(evsel, cpumap->map[cpu], thread); retry_open: pr_debug2("sys_perf_event_open: pid %d cpu %d group_fd %d flags %#lx\n", - pid, cpus->map[cpu], group_fd, flags); + pid, cpumap->map[cpu], group_fd, flags); FD(evsel, cpu, thread) = sys_perf_event_open(&evsel->attr, pid, - cpus->map[cpu], + cpumap->map[cpu], group_fd, flags); if (FD(evsel, cpu, thread) < 0) { err = -errno; -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/