lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 15 Apr 2015 03:56:15 -0400
From:	Kan Liang <kan.liang@...el.com>
To:	acme@...nel.org, a.p.zijlstra@...llo.nl
Cc:	eranian@...gle.com, andi@...stfloor.org,
	linux-kernel@...r.kernel.org, Kan Liang <kan.liang@...el.com>
Subject: [PATCH V2 5/6] perf,tools: open/mmap event uses event's cpu map

From: Kan Liang <kan.liang@...el.com>

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 <kan.liang@...el.com>
---
 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@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ