linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/6] perf tools: Share map groups within process
@ 2014-03-18 14:46 Jiri Olsa
  2014-03-18 14:46 ` [PATCH 1/6] perf tests: Add thread maps lookup automated tests Jiri Olsa
                   ` (8 more replies)
  0 siblings, 9 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

hi,
this patchset moves thread's map_groups to be dynamically
allocated and shared within process threads.

The main benefit would be to be able to look up memory
map from any thread that belongs to the process.

This implements one of the solution ideas for issue
described by Don in following thread:
http://marc.info/?l=linux-kernel&m=139403876017159&w=2

RFC changes:
  - added automated test for thread map groups get/put methods
  - fix reference count for case described by Namhyung
  - rename the mmap-events.c test to mmap-thread-lookup.c
  - added PROT_EXEC to mmap call in tests/mmap-thread-lookup.c
    as it's not implied by default on all archs (Namhyung)
  - lazy mg allocation in thread__find_addr_map (Namhyung)
  - fix compilation failures (Arnaldo)

also available in here:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/core_mmaps

thanks,
jirka


Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
Jiri Olsa (6):
      perf tests: Add thread maps lookup automated tests
      perf tools: Remove thread__find_map function
      perf tools: Allocate thread map_groups dynamically
      perf tools: Add machine pointer into thread struct
      perf tools: Share process map groups within process threads
      perf tests: Add map groups sharing with thread object test

 tools/perf/Makefile.perf                 |   2 +
 tools/perf/arch/x86/tests/dwarf-unwind.c |   9 +++-
 tools/perf/perf.h                        |   6 +++
 tools/perf/tests/builtin-test.c          |   8 ++++
 tools/perf/tests/mmap-thread-lookup.c    | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h                 |   2 +
 tools/perf/tests/thread-mg-share.c       | 110 +++++++++++++++++++++++++++++++++++++++++++
 tools/perf/ui/stdio/hist.c               |   9 +++-
 tools/perf/util/event.c                  |  10 +++-
 tools/perf/util/machine.c                |   8 ++--
 tools/perf/util/map.h                    |   3 +-
 tools/perf/util/thread.c                 | 120 +++++++++++++++++++++++++++++++++++++++++-----
 tools/perf/util/thread.h                 |  19 ++++----
 13 files changed, 508 insertions(+), 31 deletions(-)
 create mode 100644 tools/perf/tests/mmap-thread-lookup.c
 create mode 100644 tools/perf/tests/thread-mg-share.c

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/6] perf tests: Add thread maps lookup automated tests
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-18 14:46 ` [PATCH 2/6] perf tools: Remove thread__find_map function Jiri Olsa
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Adding automated test for memory maps lookup within
multiple machines threads.

The test creates 4 threads and separated memory maps.

It checks that we could use thread__find_addr_map
function with thread object based on TID to find
memory maps.

Currently map info is reachable only from thread leader.
Upcoming patches for map groups sharing allow to find
maps from any thread.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/Makefile.perf              |   1 +
 tools/perf/perf.h                     |   6 +
 tools/perf/tests/builtin-test.c       |   4 +
 tools/perf/tests/mmap-thread-lookup.c | 233 ++++++++++++++++++++++++++++++++++
 tools/perf/tests/tests.h              |   1 +
 5 files changed, 245 insertions(+)
 create mode 100644 tools/perf/tests/mmap-thread-lookup.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 50d875d..667e85a 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -414,6 +414,7 @@ ifeq ($(ARCH),x86)
 LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
 endif
 endif
+LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index e18a8b5..1138c41 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -15,6 +15,9 @@
 #ifndef __NR_futex
 # define __NR_futex 240
 #endif
+#ifndef __NR_gettid
+# define __NR_gettid 224
+#endif
 #endif
 
 #if defined(__x86_64__)
@@ -29,6 +32,9 @@
 #ifndef __NR_futex
 # define __NR_futex 202
 #endif
+#ifndef __NR_gettid
+# define __NR_gettid 186
+#endif
 #endif
 
 #ifdef __powerpc__
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index b11bf8a..d947d1a 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -124,6 +124,10 @@ static struct test {
 #endif
 #endif
 	{
+		.desc = "Test mmap thread lookup",
+		.func = test__mmap_thread_lookup,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
new file mode 100644
index 0000000..7f0cd83
--- /dev/null
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -0,0 +1,233 @@
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "debug.h"
+#include "tests.h"
+#include "machine.h"
+#include "thread_map.h"
+#include "symbol.h"
+#include "thread.h"
+
+#define THREADS 4
+
+static int go_away;
+
+struct thread_data {
+	pthread_t	pt;
+	pid_t		tid;
+	void		*map;
+	int		ready[2];
+};
+
+static struct thread_data threads[THREADS];
+
+static int thread_init(struct thread_data *td)
+{
+	void *map;
+
+	map = mmap(NULL, page_size,
+		   PROT_READ|PROT_WRITE|PROT_EXEC,
+		   MAP_SHARED|MAP_ANONYMOUS, -1, 0);
+
+	if (map == MAP_FAILED) {
+		perror("mmap failed");
+		return -1;
+	}
+
+	td->map = map;
+	td->tid = syscall(SYS_gettid);
+
+	pr_debug("tid = %d, map = %p\n", td->tid, map);
+	return 0;
+}
+
+static void *thread_fn(void *arg)
+{
+	struct thread_data *td = arg;
+	ssize_t ret;
+	int go;
+
+	if (thread_init(td))
+		return NULL;
+
+	/* Signal thread_create thread is initialized. */
+	ret = write(td->ready[1], &go, sizeof(int));
+	if (ret != sizeof(int)) {
+		pr_err("failed to notify\n");
+		return NULL;
+	}
+
+	while (!go_away) {
+		/* Waiting for main thread to kill us. */
+		usleep(100);
+	}
+
+	munmap(td->map, page_size);
+	return NULL;
+}
+
+static int thread_create(int i)
+{
+	struct thread_data *td = &threads[i];
+	int err, go;
+
+	if (pipe(td->ready))
+		return -1;
+
+	err = pthread_create(&td->pt, NULL, thread_fn, td);
+	if (!err) {
+		/* Wait for thread initialization. */
+		ssize_t ret = read(td->ready[0], &go, sizeof(int));
+		err = ret != sizeof(int);
+	}
+
+	close(td->ready[0]);
+	close(td->ready[1]);
+	return err;
+}
+
+static int threads_create(void)
+{
+	struct thread_data *td0 = &threads[0];
+	int i, err = 0;
+
+	/* 0 is main thread */
+	if (thread_init(td0))
+		return -1;
+
+	for (i = 1; !err && i < THREADS; i++)
+		err = thread_create(i);
+
+	return err;
+}
+
+static int threads_destroy(void)
+{
+	struct thread_data *td0 = &threads[0];
+	int i, err = 0;
+
+	/* cleanup the main thread */
+	munmap(td0->map, page_size);
+
+	go_away = 1;
+
+	for (i = 1; !err && i < THREADS; i++)
+		err = pthread_join(threads[i].pt, NULL);
+
+	return err;
+}
+
+typedef int (*synth_cb)(struct machine *machine);
+
+static int synth_all(struct machine *machine)
+{
+	return perf_event__synthesize_threads(NULL,
+					      perf_event__process,
+					      machine, 0);
+}
+
+static int synth_process(struct machine *machine)
+{
+	struct thread_map *map;
+	int err;
+
+	map = thread_map__new_by_tid(syscall(SYS_gettid));
+
+	err = perf_event__synthesize_thread_map(NULL, map,
+						perf_event__process,
+						machine, 0);
+
+	thread_map__delete(map);
+	return err;
+}
+
+static int mmap_events(synth_cb synth)
+{
+	struct machines machines;
+	struct machine *machine;
+	int err, i;
+
+	/*
+	 * The threads_create will not return before all threads
+	 * are spawned and all created memory map.
+	 *
+	 * They will loop until threads_destroy is called, so we
+	 * can safely run synthesizing function.
+	 */
+	TEST_ASSERT_VAL("failed to create threads", !threads_create());
+
+	machines__init(&machines);
+	machine = &machines.host;
+
+	dump_trace = verbose > 1 ? 1 : 0;
+
+	err = synth(machine);
+
+	dump_trace = 0;
+
+	TEST_ASSERT_VAL("failed to destroy threads", !threads_destroy());
+	TEST_ASSERT_VAL("failed to synthesize maps", !err);
+
+	/*
+	 * All data is synthesized, try to find map for each
+	 * thread object.
+	 */
+	for (i = 0; i < THREADS; i++) {
+		struct thread_data *td = &threads[i];
+		struct addr_location al;
+		struct thread *thread;
+
+		thread = machine__findnew_thread(machine, getpid(), td->tid);
+
+		pr_debug("looking for map %p\n", td->map);
+
+		thread__find_addr_map(thread, machine,
+				      PERF_RECORD_MISC_USER, MAP__FUNCTION,
+				      (u64) (td->map + 1), &al);
+
+		if (!al.map) {
+			pr_debug("failed, couldn't find map\n");
+			err = -1;
+			break;
+		}
+
+		pr_debug("map %p, addr %lx\n", al.map, al.map->start);
+	}
+
+	machine__delete_threads(machine);
+	machines__exit(&machines);
+	return err;
+}
+
+/*
+ * This test creates 'THREADS' number of threads (including
+ * main thread) and each thread creates memory map.
+ *
+ * When threads are created, we synthesize them with both
+ * (separate tests):
+ *   perf_event__synthesize_thread_map (process based)
+ *   perf_event__synthesize_threads    (global)
+ *
+ * We test we can find all memory maps via:
+ *   thread__find_addr_map
+ *
+ * by using all thread objects. Currently map info is reachable
+ * only from thread leader. Upcoming patches for map groups
+ * sharing allow to find maps from any thread.
+ */
+int test__mmap_thread_lookup(void)
+{
+	/* perf_event__synthesize_threads synthesize */
+	TEST_ASSERT_VAL("failed with sythesizing all",
+			!mmap_events(synth_all));
+
+	/* perf_event__synthesize_thread_map synthesize */
+	TEST_ASSERT_VAL("failed with sythesizing process",
+			!mmap_events(synth_process));
+
+	return 0;
+}
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index a24795c..6db764c 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -41,6 +41,7 @@ int test__sample_parsing(void);
 int test__keep_tracking(void);
 int test__parse_no_sample_id_all(void);
 int test__dwarf_unwind(void);
+int test__mmap_thread_lookup(void);
 
 #if defined(__x86_64__) || defined(__i386__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/6] perf tools: Remove thread__find_map function
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
  2014-03-18 14:46 ` [PATCH 1/6] perf tests: Add thread maps lookup automated tests Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-19 13:08   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2014-03-18 14:46 ` [PATCH 3/6] perf tools: Allocate thread map_groups dynamically Jiri Olsa
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Because it's not used any more.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/util/thread.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 9a07074..9b29f08 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -44,12 +44,6 @@ void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
-static inline struct map *thread__find_map(struct thread *thread,
-					   enum map_type type, u64 addr)
-{
-	return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
-}
-
 void thread__find_addr_map(struct thread *thread, struct machine *machine,
 			   u8 cpumode, enum map_type type, u64 addr,
 			   struct addr_location *al);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/6] perf tools: Allocate thread map_groups dynamically
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
  2014-03-18 14:46 ` [PATCH 1/6] perf tests: Add thread maps lookup automated tests Jiri Olsa
  2014-03-18 14:46 ` [PATCH 2/6] perf tools: Remove thread__find_map function Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-18 14:46 ` [PATCH 4/6] perf tools: Add machine pointer into thread struct Jiri Olsa
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Moving towards sharing map groups within a process threads.

Because of this we need the map groups to be dynamically
allocated. No other functional change is intended in here.

Adding new interface to get/put map groups:
  thread__map_groups_get
    - allocates map groups for thread

  thread__map_groups_put
    - frees map groups for thread

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/arch/x86/tests/dwarf-unwind.c |  9 +++-
 tools/perf/ui/stdio/hist.c               |  9 +++-
 tools/perf/util/event.c                  | 10 +++-
 tools/perf/util/machine.c                |  6 +--
 tools/perf/util/map.h                    |  1 -
 tools/perf/util/thread.c                 | 86 +++++++++++++++++++++++++++-----
 tools/perf/util/thread.h                 |  8 ++-
 7 files changed, 107 insertions(+), 22 deletions(-)

diff --git a/tools/perf/arch/x86/tests/dwarf-unwind.c b/tools/perf/arch/x86/tests/dwarf-unwind.c
index b602ad9..4e2088c 100644
--- a/tools/perf/arch/x86/tests/dwarf-unwind.c
+++ b/tools/perf/arch/x86/tests/dwarf-unwind.c
@@ -23,7 +23,14 @@ static int sample_ustack(struct perf_sample *sample,
 
 	sp = (unsigned long) regs[PERF_REG_X86_SP];
 
-	map = map_groups__find(&thread->mg, MAP__FUNCTION, (u64) sp);
+	/*
+	 * The generic code (test__dwarf_unwind) synthesizes and
+	 * processes mmap events, so if we get NULL in thread->mg,
+	 * it's bug.
+	 */
+	BUG_ON(!thread->mg);
+
+	map = map_groups__find(thread->mg, MAP__FUNCTION, (u64) sp);
 	if (!map) {
 		pr_debug("failed to get stack map\n");
 		return -1;
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index d59893e..fc318c3 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -495,7 +495,14 @@ print_entries:
 			break;
 
 		if (h->ms.map == NULL && verbose > 1) {
-			__map_groups__fprintf_maps(&h->thread->mg,
+			struct map_groups *mg;
+
+			mg = thread__map_groups_get(h->thread);
+			if (!mg) {
+				ret = -ENOMEM;
+				break;
+			}
+			__map_groups__fprintf_maps(mg,
 						   MAP__FUNCTION, verbose, fp);
 			fprintf(fp, "%.10s end\n", graph_dotted_line);
 		}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 9c18b126..bc1da4d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -699,7 +699,7 @@ void thread__find_addr_map(struct thread *thread,
 			   enum map_type type, u64 addr,
 			   struct addr_location *al)
 {
-	struct map_groups *mg = &thread->mg;
+	struct map_groups *mg;
 	bool load_map = false;
 
 	al->machine = machine;
@@ -719,12 +719,14 @@ void thread__find_addr_map(struct thread *thread,
 		load_map = true;
 	} else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
 		al->level = '.';
+		mg = thread__map_groups_get(thread);
 	} else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
 		al->level = 'g';
 		mg = &machine->kmaps;
 		load_map = true;
 	} else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
 		al->level = 'u';
+		mg = thread__map_groups_get(thread);
 	} else {
 		al->level = 'H';
 		al->map = NULL;
@@ -740,6 +742,12 @@ void thread__find_addr_map(struct thread *thread,
 
 		return;
 	}
+
+	if (mg == NULL) {
+		al->map = NULL;
+		return;
+	}
+
 try_again:
 	al->map = map_groups__find(mg, type, al->addr);
 	if (al->map == NULL) {
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index a53cd0b..d1f06d2 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1046,8 +1046,7 @@ int machine__process_mmap2_event(struct machine *machine,
 	if (map == NULL)
 		goto out_problem;
 
-	thread__insert_map(thread, map);
-	return 0;
+	return thread__insert_map(thread, map);
 
 out_problem:
 	dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n");
@@ -1093,8 +1092,7 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
 	if (map == NULL)
 		goto out_problem;
 
-	thread__insert_map(thread, map);
-	return 0;
+	return thread__insert_map(thread, map);
 
 out_problem:
 	dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index f00f058..99a6488 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -202,5 +202,4 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
 				     enum map_type type, const char *name);
 
 void map_groups__flush(struct map_groups *mg);
-
 #endif /* __PERF_MAP_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 3ce0498..bacf60b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -15,7 +15,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)
 	struct thread *thread = zalloc(sizeof(*thread));
 
 	if (thread != NULL) {
-		map_groups__init(&thread->mg);
 		thread->pid_ = pid;
 		thread->tid = tid;
 		thread->ppid = -1;
@@ -45,12 +44,12 @@ void thread__delete(struct thread *thread)
 {
 	struct comm *comm, *tmp;
 
-	map_groups__exit(&thread->mg);
 	list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
 		list_del(&comm->list);
 		comm__free(comm);
 	}
 
+	thread__map_groups_put(thread);
 	free(thread);
 }
 
@@ -111,18 +110,85 @@ int thread__comm_len(struct thread *thread)
 size_t thread__fprintf(struct thread *thread, FILE *fp)
 {
 	return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
-	       map_groups__fprintf(&thread->mg, verbose, fp);
+	       map_groups__fprintf(thread->mg, verbose, fp);
 }
 
-void thread__insert_map(struct thread *thread, struct map *map)
+int thread__insert_map(struct thread *thread, struct map *map)
 {
-	map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr);
-	map_groups__insert(&thread->mg, map);
+	struct map_groups *mg = thread->mg;
+
+	if (!mg) {
+		mg = thread__map_groups_get(thread);
+		if (!mg)
+			return -ENOMEM;
+	}
+
+	map_groups__fixup_overlappings(mg, map, verbose, stderr);
+	map_groups__insert(mg, map);
+	return 0;
+}
+
+static struct map_groups *thread__map_groups_alloc(struct thread *thread)
+{
+	struct map_groups *mg = zalloc(sizeof(*mg));
+
+	if (mg) {
+		map_groups__init(mg);
+		thread->mg = mg;
+	}
+
+	return mg;
+}
+
+struct map_groups *thread__map_groups_get(struct thread *thread)
+{
+	struct map_groups *mg = thread->mg;
+
+	if (!mg)
+		mg = thread__map_groups_alloc(thread);
+
+	return mg;
+}
+
+void thread__map_groups_put(struct thread *thread)
+{
+	if (thread->mg) {
+		map_groups__exit(thread->mg);
+		zfree(&thread->mg);
+	}
+}
+
+static int thread__clone_map_groups(struct thread *thread,
+				    struct thread *parent)
+{
+	struct map_groups *mg;
+	int i;
+
+	/* This is new thread, we share map groups for process. */
+	if (thread->pid_ == parent->pid_)
+		return 0;
+
+	/*
+	 * But this one is new process, copy maps.. if there's
+	 * anything to copy ;-)
+	 */
+	if (!parent->mg)
+		return 0;
+
+	mg = thread__map_groups_alloc(thread);
+	if (!mg)
+		return -ENOMEM;
+
+	for (i = 0; i < MAP__NR_TYPES; ++i)
+		if (map_groups__clone(mg, parent->mg, i) < 0)
+			return -ENOMEM;
+
+	return 0;
 }
 
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 {
-	int i, err;
+	int err;
 
 	if (parent->comm_set) {
 		const char *comm = thread__comm_str(parent);
@@ -134,13 +200,9 @@ int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
 		thread->comm_set = true;
 	}
 
-	for (i = 0; i < MAP__NR_TYPES; ++i)
-		if (map_groups__clone(&thread->mg, &parent->mg, i) < 0)
-			return -ENOMEM;
-
 	thread->ppid = parent->tid;
 
-	return 0;
+	return thread__clone_map_groups(thread, parent);
 }
 
 void thread__find_cpumode_addr_location(struct thread *thread,
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 9b29f08..b3f7d8e 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -13,7 +13,7 @@ struct thread {
 		struct rb_node	 rb_node;
 		struct list_head node;
 	};
-	struct map_groups	mg;
+	struct map_groups	*mg;
 	pid_t			pid_; /* Not all tools update this */
 	pid_t			tid;
 	pid_t			ppid;
@@ -40,7 +40,7 @@ int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
 int thread__comm_len(struct thread *thread);
 struct comm *thread__comm(const struct thread *thread);
 const char *thread__comm_str(const struct thread *thread);
-void thread__insert_map(struct thread *thread, struct map *map);
+int thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
@@ -77,4 +77,8 @@ static inline bool thread__is_filtered(struct thread *thread)
 	return false;
 }
 
+struct map_groups *thread__map_groups_get(struct thread *thread);
+
+void thread__map_groups_put(struct thread *thread);
+
 #endif	/* __PERF_THREAD_H */
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/6] perf tools: Add machine pointer into thread struct
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (2 preceding siblings ...)
  2014-03-18 14:46 ` [PATCH 3/6] perf tools: Allocate thread map_groups dynamically Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-18 14:46 ` [PATCH 5/6] perf tools: Share process map groups within process threads Jiri Olsa
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Need machine pointer in thread object, so we could
lookup the process thread in following patch.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/util/machine.c | 2 +-
 tools/perf/util/thread.c  | 4 +++-
 tools/perf/util/thread.h  | 5 ++++-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index d1f06d2..237d7c2 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -311,7 +311,7 @@ static struct thread *__machine__findnew_thread(struct machine *machine,
 	if (!create)
 		return NULL;
 
-	th = thread__new(pid, tid);
+	th = thread__new(pid, tid, machine);
 	if (th != NULL) {
 		rb_link_node(&th->rb_node, parent, p);
 		rb_insert_color(&th->rb_node, &machine->threads);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index bacf60b..cbe451a 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -8,13 +8,15 @@
 #include "debug.h"
 #include "comm.h"
 
-struct thread *thread__new(pid_t pid, pid_t tid)
+struct thread *thread__new(pid_t pid, pid_t tid,
+			   struct machine *machine)
 {
 	char *comm_str;
 	struct comm *comm;
 	struct thread *thread = zalloc(sizeof(*thread));
 
 	if (thread != NULL) {
+		thread->machine = machine;
 		thread->pid_ = pid;
 		thread->tid = tid;
 		thread->ppid = -1;
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index b3f7d8e..21521e1 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -7,12 +7,14 @@
 #include <sys/types.h>
 #include "symbol.h"
 #include <strlist.h>
+#include "machine.h"
 
 struct thread {
 	union {
 		struct rb_node	 rb_node;
 		struct list_head node;
 	};
+	struct machine		*machine;
 	struct map_groups	*mg;
 	pid_t			pid_; /* Not all tools update this */
 	pid_t			tid;
@@ -29,7 +31,8 @@ struct thread {
 struct machine;
 struct comm;
 
-struct thread *thread__new(pid_t pid, pid_t tid);
+struct thread *thread__new(pid_t pid, pid_t tid,
+			   struct machine *machine);
 void thread__delete(struct thread *thread);
 static inline void thread__exited(struct thread *thread)
 {
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/6] perf tools: Share process map groups within process threads
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (3 preceding siblings ...)
  2014-03-18 14:46 ` [PATCH 4/6] perf tools: Add machine pointer into thread struct Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-18 14:46 ` [PATCH 6/6] perf tests: Add map groups sharing with thread object test Jiri Olsa
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Sharing map groups within all process threads. This way
there's only one copy of mmap info and it's reachable
from any thread within the process.

Adding reference counting for struct map_groups and
changing the thread map groups get/put interface.

Adding reference counter 'refcnt' into struct map_groups.

Function thread__map_groups_get now:
  - lookup (&create) thread leader and returns its mg,
    allocates one if needed
  - increments reference counter for each copy

Function thread__map_groups_put now:
  - decrease map groups reference counter and sets
    its pointer to NULL
  - frees map groups data if it was last copy

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/util/map.h    |  2 ++
 tools/perf/util/thread.c | 40 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 99a6488..472a686 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -59,6 +59,8 @@ struct map_groups {
 	struct rb_root	 maps[MAP__NR_TYPES];
 	struct list_head removed_maps[MAP__NR_TYPES];
 	struct machine	 *machine;
+	/* Used for thread sharing. */
+	int		  refcnt;
 };
 
 static inline struct kmap *map__kmap(struct map *map)
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index cbe451a..f34fda1 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -130,6 +130,13 @@ int thread__insert_map(struct thread *thread, struct map *map)
 	return 0;
 }
 
+static struct thread *thread__get_leader(struct thread *thread)
+{
+	pid_t pid = thread->pid_;
+
+	return machine__findnew_thread(thread->machine, pid, pid);
+}
+
 static struct map_groups *thread__map_groups_alloc(struct thread *thread)
 {
 	struct map_groups *mg = zalloc(sizeof(*mg));
@@ -137,6 +144,7 @@ static struct map_groups *thread__map_groups_alloc(struct thread *thread)
 	if (mg) {
 		map_groups__init(mg);
 		thread->mg = mg;
+		mg->refcnt = 1;
 	}
 
 	return mg;
@@ -146,17 +154,39 @@ struct map_groups *thread__map_groups_get(struct thread *thread)
 {
 	struct map_groups *mg = thread->mg;
 
-	if (!mg)
-		mg = thread__map_groups_alloc(thread);
+	if (!mg) {
+		struct thread *leader = thread__get_leader(thread);
+
+		if (!leader)
+			return NULL;
+
+		if (leader->mg)
+			mg = leader->mg;
+		else
+			mg = thread__map_groups_alloc(leader);
+
+		if (leader != thread) {
+			thread->mg = mg;
+			mg->refcnt++;
+		}
+	}
 
 	return mg;
 }
 
 void thread__map_groups_put(struct thread *thread)
 {
-	if (thread->mg) {
-		map_groups__exit(thread->mg);
-		zfree(&thread->mg);
+	struct map_groups *mg = thread->mg;
+
+	if (mg) {
+		BUG_ON(!mg->refcnt);
+
+		if (!--mg->refcnt) {
+			map_groups__exit(thread->mg);
+			free(thread->mg);
+		}
+
+		thread->mg = NULL;
 	}
 }
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/6] perf tests: Add map groups sharing with thread object test
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (4 preceding siblings ...)
  2014-03-18 14:46 ` [PATCH 5/6] perf tools: Share process map groups within process threads Jiri Olsa
@ 2014-03-18 14:46 ` Jiri Olsa
  2014-03-18 19:14 ` [PATCH 0/6] perf tools: Share map groups within process Don Zickus
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-18 14:46 UTC (permalink / raw)
  To: linux-kernel
  Cc: Jiri Olsa, Don Zickus, Corey Ashford, David Ahern,
	Frederic Weisbecker, Ingo Molnar, Namhyung Kim, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

This test create 2 processes abstractions, with several threads
and checks they properly share and maintain map groups info.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
---
 tools/perf/Makefile.perf           |   1 +
 tools/perf/tests/builtin-test.c    |   4 ++
 tools/perf/tests/tests.h           |   1 +
 tools/perf/tests/thread-mg-share.c | 110 +++++++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+)
 create mode 100644 tools/perf/tests/thread-mg-share.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 667e85a..ffa6cac 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -415,6 +415,7 @@ LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
 endif
 endif
 LIB_OBJS += $(OUTPUT)tests/mmap-thread-lookup.o
+LIB_OBJS += $(OUTPUT)tests/thread-mg-share.o
 
 BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
 BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index d947d1a..a1145d1 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -128,6 +128,10 @@ static struct test {
 		.func = test__mmap_thread_lookup,
 	},
 	{
+		.desc = "Test thread mg sharing",
+		.func = test__thread_mg_share,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 6db764c..5ed3bd5 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -42,6 +42,7 @@ int test__keep_tracking(void);
 int test__parse_no_sample_id_all(void);
 int test__dwarf_unwind(void);
 int test__mmap_thread_lookup(void);
+int test__thread_mg_share(void);
 
 #if defined(__x86_64__) || defined(__i386__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-mg-share.c b/tools/perf/tests/thread-mg-share.c
new file mode 100644
index 0000000..43cbd8b
--- /dev/null
+++ b/tools/perf/tests/thread-mg-share.c
@@ -0,0 +1,110 @@
+#include "tests.h"
+#include "machine.h"
+#include "thread.h"
+#include "map.h"
+
+int test__thread_mg_share(void)
+{
+	struct machines machines;
+	struct machine *machine;
+
+	/* thread group */
+	struct thread *leader;
+	struct thread *t1, *t2, *t3;
+	struct map_groups *mg;
+	struct map_groups *mg1, *mg2, *mg3;
+
+	/* other process */
+	struct thread *other, *other_leader;
+	struct map_groups *mg_other, *mg_other_leader;
+
+	/*
+	 * This test create 2 processes abstractions (struct thread)
+	 * with several threads and checks they properly share and
+	 * maintain map groups info (struct map_groups).
+	 *
+	 * thread group (pid: 0, tids: 0, 1, 2, 3)
+	 * other  group (pid: 4, tids: 4, 5)
+	*/
+
+	machines__init(&machines);
+	machine = &machines.host;
+
+	/* create process with 4 threads */
+	leader = machine__findnew_thread(machine, 0, 0);
+	t1     = machine__findnew_thread(machine, 0, 1);
+	t2     = machine__findnew_thread(machine, 0, 2);
+	t3     = machine__findnew_thread(machine, 0, 3);
+
+	/* and create 1 separated process, without thread leader */
+	other  = machine__findnew_thread(machine, 4, 5);
+
+	TEST_ASSERT_VAL("failed to create threads",
+			leader && t1 && t2 && t3 && other);
+
+	/* requests map groups for each thread in the group */
+	mg  = thread__map_groups_get(leader);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 1);
+
+	mg1 = thread__map_groups_get(t1);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 2);
+
+	mg2 = thread__map_groups_get(t2);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 3);
+
+	mg3 = thread__map_groups_get(t3);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 4);
+
+	/* test the map groups pointer is shared */
+	TEST_ASSERT_VAL("map groups don't match", mg == mg1);
+	TEST_ASSERT_VAL("map groups don't match", mg == mg2);
+	TEST_ASSERT_VAL("map groups don't match", mg == mg3);
+
+	/*
+	 * Now get map groups for other thread (not thread leader)
+	 * Its refcnt should be 2 because of the thread leader being
+	 * included.
+	 */
+	mg_other = thread__map_groups_get(other);
+	TEST_ASSERT_VAL("wrong refcnt", mg_other->refcnt == 2);
+
+	/*
+	 * Verify the other leader was created by previous call.
+	 * It should have shared map groups with no change in
+	 * refcnt.
+	 */
+	other_leader = machine__find_thread(machine, 4, 4);
+	TEST_ASSERT_VAL("failed to find other leader", other_leader);
+
+	mg_other_leader = thread__map_groups_get(other_leader);
+	TEST_ASSERT_VAL("map groups don't match", mg_other_leader == mg_other);
+	TEST_ASSERT_VAL("wrong refcnt", mg_other_leader->refcnt == 2);
+
+	/* release thread group */
+	thread__map_groups_put(leader);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 3);
+	TEST_ASSERT_VAL("wrong mg", leader->mg == NULL);
+
+	thread__map_groups_put(t1);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 2);
+	TEST_ASSERT_VAL("wrong mg", t1->mg == NULL);
+
+	thread__map_groups_put(t2);
+	TEST_ASSERT_VAL("wrong refcnt", mg->refcnt == 1);
+	TEST_ASSERT_VAL("wrong mg", t2->mg == NULL);
+
+	thread__map_groups_put(t3);
+	TEST_ASSERT_VAL("wrong mg", t3->mg == NULL);
+
+	/* release other group  */
+	thread__map_groups_put(other_leader);
+	TEST_ASSERT_VAL("wrong refcnt", mg_other_leader->refcnt == 1);
+	TEST_ASSERT_VAL("wrong mg", other_leader->mg == NULL);
+
+	thread__map_groups_put(other);
+	TEST_ASSERT_VAL("wrong mg", other->mg == NULL);
+
+	machine__delete_threads(machine);
+	machines__exit(&machines);
+	return 0;
+}
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/6] perf tools: Share map groups within process
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (5 preceding siblings ...)
  2014-03-18 14:46 ` [PATCH 6/6] perf tests: Add map groups sharing with thread object test Jiri Olsa
@ 2014-03-18 19:14 ` Don Zickus
  2014-03-19  0:46 ` Namhyung Kim
  2014-03-20  8:33 ` Jiri Olsa
  8 siblings, 0 replies; 11+ messages in thread
From: Don Zickus @ 2014-03-18 19:14 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel, Corey Ashford, David Ahern, Frederic Weisbecker,
	Ingo Molnar, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Arnaldo Carvalho de Melo

On Tue, Mar 18, 2014 at 03:46:50PM +0100, Jiri Olsa wrote:
> hi,
> this patchset moves thread's map_groups to be dynamically
> allocated and shared within process threads.
> 
> The main benefit would be to be able to look up memory
> map from any thread that belongs to the process.
> 
> This implements one of the solution ideas for issue
> described by Don in following thread:
> http://marc.info/?l=linux-kernel&m=139403876017159&w=2
> 
> RFC changes:
>   - added automated test for thread map groups get/put methods
>   - fix reference count for case described by Namhyung
>   - rename the mmap-events.c test to mmap-thread-lookup.c
>   - added PROT_EXEC to mmap call in tests/mmap-thread-lookup.c
>     as it's not implied by default on all archs (Namhyung)
>   - lazy mg allocation in thread__find_addr_map (Namhyung)
>   - fix compilation failures (Arnaldo)
> 
> also available in here:
>   git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
>   perf/core_mmaps

I ran this patchset through my multi-threaded java test (SPECJBB) and saw
no issues.  The threads seemed to have matched with their pids properly.
I even took an old perf.data file (with old synthesized mmap2 events using
pids) and the tids from the samples matched the pids correctly (for what
it is worth).

So I will add my 

Tested-by: Don Zickus <dzickus@redhat.com>


I don't know the code well enough to know if it is right or not, but my
quick review didn't see anything wrong.

Cheers,
Don

> 
> thanks,
> jirka
> 
> 
> Signed-off-by: Jiri Olsa <jolsa@redhat.com>
> Cc: Don Zickus <dzickus@redhat.com>
> Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
> Cc: David Ahern <dsahern@gmail.com>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Ingo Molnar <mingo@kernel.org>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
> ---
> Jiri Olsa (6):
>       perf tests: Add thread maps lookup automated tests
>       perf tools: Remove thread__find_map function
>       perf tools: Allocate thread map_groups dynamically
>       perf tools: Add machine pointer into thread struct
>       perf tools: Share process map groups within process threads
>       perf tests: Add map groups sharing with thread object test
> 
>  tools/perf/Makefile.perf                 |   2 +
>  tools/perf/arch/x86/tests/dwarf-unwind.c |   9 +++-
>  tools/perf/perf.h                        |   6 +++
>  tools/perf/tests/builtin-test.c          |   8 ++++
>  tools/perf/tests/mmap-thread-lookup.c    | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/tests/tests.h                 |   2 +
>  tools/perf/tests/thread-mg-share.c       | 110 +++++++++++++++++++++++++++++++++++++++++++
>  tools/perf/ui/stdio/hist.c               |   9 +++-
>  tools/perf/util/event.c                  |  10 +++-
>  tools/perf/util/machine.c                |   8 ++--
>  tools/perf/util/map.h                    |   3 +-
>  tools/perf/util/thread.c                 | 120 +++++++++++++++++++++++++++++++++++++++++-----
>  tools/perf/util/thread.h                 |  19 ++++----
>  13 files changed, 508 insertions(+), 31 deletions(-)
>  create mode 100644 tools/perf/tests/mmap-thread-lookup.c
>  create mode 100644 tools/perf/tests/thread-mg-share.c

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/6] perf tools: Share map groups within process
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (6 preceding siblings ...)
  2014-03-18 19:14 ` [PATCH 0/6] perf tools: Share map groups within process Don Zickus
@ 2014-03-19  0:46 ` Namhyung Kim
  2014-03-20  8:33 ` Jiri Olsa
  8 siblings, 0 replies; 11+ messages in thread
From: Namhyung Kim @ 2014-03-19  0:46 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: linux-kernel@vger.kernel.org, Don Zickus, Corey Ashford,
	David Ahern, Frederic Weisbecker, Ingo Molnar, Paul Mackerras,
	Peter Zijlstra, Arnaldo Carvalho de Melo

Hi Jiri,

On Tue, Mar 18, 2014 at 2:46 PM, Jiri Olsa <jolsa@redhat.com> wrote:
> hi,
> this patchset moves thread's map_groups to be dynamically
> allocated and shared within process threads.
>
> The main benefit would be to be able to look up memory
> map from any thread that belongs to the process.
>
> This implements one of the solution ideas for issue
> described by Don in following thread:
> http://marc.info/?l=linux-kernel&m=139403876017159&w=2
>
> RFC changes:
>   - added automated test for thread map groups get/put methods
>   - fix reference count for case described by Namhyung
>   - rename the mmap-events.c test to mmap-thread-lookup.c
>   - added PROT_EXEC to mmap call in tests/mmap-thread-lookup.c
>     as it's not implied by default on all archs (Namhyung)
>   - lazy mg allocation in thread__find_addr_map (Namhyung)
>   - fix compilation failures (Arnaldo)

Looks good to me!

Reviewed-by: Namhyung Kim <namhyung@kernel.org>

Thanks,
Namhyung

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [tip:perf/core] perf tools: Remove thread__find_map function
  2014-03-18 14:46 ` [PATCH 2/6] perf tools: Remove thread__find_map function Jiri Olsa
@ 2014-03-19 13:08   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot for Jiri Olsa @ 2014-03-19 13:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, paulus, hpa, mingo, a.p.zijlstra, namhyung,
	jolsa, fweisbec, dsahern, tglx, cjashfor, dzickus

Commit-ID:  8fffdb6821e8ca249f56fba796ef463ac74ab196
Gitweb:     http://git.kernel.org/tip/8fffdb6821e8ca249f56fba796ef463ac74ab196
Author:     Jiri Olsa <jolsa@redhat.com>
AuthorDate: Tue, 18 Mar 2014 15:46:52 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 18 Mar 2014 18:17:04 -0300

perf tools: Remove thread__find_map function

Because it's not used any more.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1395154016-26709-3-git-send-email-jolsa@redhat.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/thread.h | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 9a07074..9b29f08 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -44,12 +44,6 @@ void thread__insert_map(struct thread *thread, struct map *map);
 int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
 size_t thread__fprintf(struct thread *thread, FILE *fp);
 
-static inline struct map *thread__find_map(struct thread *thread,
-					   enum map_type type, u64 addr)
-{
-	return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
-}
-
 void thread__find_addr_map(struct thread *thread, struct machine *machine,
 			   u8 cpumode, enum map_type type, u64 addr,
 			   struct addr_location *al);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 0/6] perf tools: Share map groups within process
  2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
                   ` (7 preceding siblings ...)
  2014-03-19  0:46 ` Namhyung Kim
@ 2014-03-20  8:33 ` Jiri Olsa
  8 siblings, 0 replies; 11+ messages in thread
From: Jiri Olsa @ 2014-03-20  8:33 UTC (permalink / raw)
  To: linux-kernel
  Cc: Don Zickus, Corey Ashford, David Ahern, Frederic Weisbecker,
	Ingo Molnar, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
	Arnaldo Carvalho de Melo

On Tue, Mar 18, 2014 at 03:46:50PM +0100, Jiri Olsa wrote:
> hi,
> this patchset moves thread's map_groups to be dynamically
> allocated and shared within process threads.
> 
> The main benefit would be to be able to look up memory
> map from any thread that belongs to the process.
> 
> This implements one of the solution ideas for issue
> described by Don in following thread:
> http://marc.info/?l=linux-kernel&m=139403876017159&w=2
> 
> RFC changes:
>   - added automated test for thread map groups get/put methods
>   - fix reference count for case described by Namhyung
>   - rename the mmap-events.c test to mmap-thread-lookup.c
>   - added PROT_EXEC to mmap call in tests/mmap-thread-lookup.c
>     as it's not implied by default on all archs (Namhyung)
>   - lazy mg allocation in thread__find_addr_map (Namhyung)
>   - fix compilation failures (Arnaldo)
> 
> also available in here:
>   git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
>   perf/core_mmaps

Arnaldo,
I rebased this to your latest perf/core

thanks,
jirka

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-03-20 10:42 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-18 14:46 [PATCH 0/6] perf tools: Share map groups within process Jiri Olsa
2014-03-18 14:46 ` [PATCH 1/6] perf tests: Add thread maps lookup automated tests Jiri Olsa
2014-03-18 14:46 ` [PATCH 2/6] perf tools: Remove thread__find_map function Jiri Olsa
2014-03-19 13:08   ` [tip:perf/core] " tip-bot for Jiri Olsa
2014-03-18 14:46 ` [PATCH 3/6] perf tools: Allocate thread map_groups dynamically Jiri Olsa
2014-03-18 14:46 ` [PATCH 4/6] perf tools: Add machine pointer into thread struct Jiri Olsa
2014-03-18 14:46 ` [PATCH 5/6] perf tools: Share process map groups within process threads Jiri Olsa
2014-03-18 14:46 ` [PATCH 6/6] perf tests: Add map groups sharing with thread object test Jiri Olsa
2014-03-18 19:14 ` [PATCH 0/6] perf tools: Share map groups within process Don Zickus
2014-03-19  0:46 ` Namhyung Kim
2014-03-20  8:33 ` Jiri Olsa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).