linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 00/26] perf stat: Introduce --per-thread option
@ 2015-06-18 21:48 Jiri Olsa
  2015-06-18 21:48 ` [PATCH 01/26] perf tools: Change thread_map::map into struct Jiri Olsa
                   ` (25 more replies)
  0 siblings, 26 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

hi,
adding the possibility to display stat data per thread.

Allowing following commands and output:

  $ perf stat  -e cycles,instructions --per-thread -p 30190,30242
  ^C
   Performance counter stats for process id '30190,30242':

               cat-30190                     0      cycles
               yes-30242         3,842,525,421      cycles
               cat-30190                     0      instructions
               yes-30242        10,370,817,010      instructions

         1.143155657 seconds time elapsed


Also works under interval mode:

  $ perf stat  -e cycles,instructions --per-thread -p 30190,30242 -I 1000
  #           time             comm-pid                  counts unit events
       1.000073435              cat-30190                89,058      cycles
       1.000073435              yes-30242         3,360,786,902      cycles                     (100.00%)
       1.000073435              cat-30190                14,066      instructions
       1.000073435              yes-30242         9,069,937,462      instructions
       2.000204830              cat-30190                     0      cycles
       2.000204830              yes-30242         3,351,667,626      cycles
       2.000204830              cat-30190                     0      instructions
       2.000204830              yes-30242         9,045,796,885      instructions
  ^C     2.771286639              cat-30190                     0      cycles
       2.771286639              yes-30242         2,593,884,166      cycles
       2.771286639              cat-30190                     0      instructions
       2.771286639              yes-30242         7,001,171,191      instructions


Available in here:
  git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git
  perf/per_thread

v3 changes:
  - some patches already pulled in, rebased on latest acme's perf/core
  - fixed cpu_map__get/thread_map__get to accept NULL map
  - renamed propagate_maps to perf_evlist__propagate_maps
  - renamed --per-task option to --per-thread
  - changed 'task-pid' header output to 'comm-pid'

v2 changes:
  - renamed xyarray__zero to xyarray__reset
  - using atomic_t for cpu_map/thread_map refcnt
  - moving all stat functions into stat object
  - using init_stats to initialize 'struct stats*'
  - change TASK-$pid output into $comm-$pid
  - updated doc with --per-task option


thanks,
jirka
---
Jiri Olsa (26):
      perf tools: Change thread_map::map into struct
      perf tools: Add comm string into struct thread_map
      perf tools: Add reference counting for cpu_map object
      perf tools: Add reference counting for thread_map object
      perf tools: Propagate cpu maps through the evlist
      perf tools: Propagate thread maps through the evlist
      perf tools: Make perf_evsel__(nr_)cpus generic
      perf tests: Add thread_map object tests
      perf stat: Introduce perf_counts function
      perf stat: Use xyarray for cpu evsel counts
      perf stat: Make stats work over the thread dimension
      perf stat: Rename struct perf_counts::cpu member to values
      perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object
      perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object
      perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
      perf stat: Introduce perf_evsel__alloc_stats function
      perf stat: Introduce perf_evsel__read function
      perf stat: Introduce read_counters function
      perf stat: Separate counters reading and processing
      perf stat: Move zero_per_pkg into counter process code
      perf stat: Move perf_stat initialization counter process code
      perf stat: Remove perf_evsel__read_cb function
      perf stat: Rename print_interval to process_interval
      perf stat: Using init_stats instead of memset
      perf stat: Introduce print_counters function
      perf stat: Introduce --per-thread option

 tools/perf/Documentation/perf-stat.txt      |   4 +
 tools/perf/builtin-stat.c                   | 394 ++++++++++++++--------------
 tools/perf/builtin-trace.c                  |   4 +-
 tools/perf/tests/Build                      |   1 +
 tools/perf/tests/builtin-test.c             |   4 +
 tools/perf/tests/code-reading.c             |   4 +-
 tools/perf/tests/keep-tracking.c            |   4 +-
 tools/perf/tests/mmap-basic.c               |   4 +-
 tools/perf/tests/mmap-thread-lookup.c       |   2 +-
 tools/perf/tests/openat-syscall-all-cpus.c  |   8 +-
 tools/perf/tests/openat-syscall-tp-fields.c |   2 +-
 tools/perf/tests/openat-syscall.c           |   6 +-
 tools/perf/tests/switch-tracking.c          |   4 +-
 tools/perf/tests/tests.h                    |   1 +
 tools/perf/tests/thread-map.c               |  28 ++
 tools/perf/util/auxtrace.c                  |   4 +-
 tools/perf/util/cpumap.c                    |  26 +-
 tools/perf/util/cpumap.h                    |   6 +-
 tools/perf/util/event.c                     |   6 +-
 tools/perf/util/evlist.c                    |  39 ++-
 tools/perf/util/evlist.h                    |   1 -
 tools/perf/util/evsel.c                     |  28 +-
 tools/perf/util/evsel.h                     |  40 ++-
 tools/perf/util/parse-events.c              |   5 +-
 tools/perf/util/python-ext-sources          |   1 +
 tools/perf/util/python.c                    |   4 +-
 tools/perf/util/record.c                    |   4 +-
 tools/perf/util/session.c                   |   2 +-
 tools/perf/util/stat.c                      | 122 ++++++++-
 tools/perf/util/stat.h                      |  46 +++-
 tools/perf/util/svghelper.c                 |   2 +-
 tools/perf/util/thread_map.c                | 110 ++++++--
 tools/perf/util/thread_map.h                |  17 +-
 33 files changed, 622 insertions(+), 311 deletions(-)
 create mode 100644 tools/perf/tests/thread-map.c

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

* [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-19 21:07   ` Arnaldo Carvalho de Melo
  2015-06-18 21:48 ` [PATCH 02/26] perf tools: Add comm string into struct thread_map Jiri Olsa
                   ` (24 subsequent siblings)
  25 siblings, 1 reply; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

We need to store command names with the pid. Changing
map to be struct holding pid. Process name is coming
in shortly.

Link: http://lkml.kernel.org/n/tip-z4zuyvcxa6glzqm8qubk6vg7@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-trace.c                  |  4 ++--
 tools/perf/tests/openat-syscall-tp-fields.c |  2 +-
 tools/perf/util/auxtrace.c                  |  4 ++--
 tools/perf/util/event.c                     |  6 +++---
 tools/perf/util/evlist.c                    |  4 ++--
 tools/perf/util/evsel.c                     |  2 +-
 tools/perf/util/thread_map.c                | 22 +++++++++++-----------
 tools/perf/util/thread_map.h                |  8 +++++++-
 8 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4bf805b2fbf6..b75a68c385ea 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2324,7 +2324,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	 */
 	if (trace->filter_pids.nr > 0)
 		err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
-	else if (evlist->threads->map[0] == -1)
+	else if (thread_map__pid(evlist->threads, 0) == -1)
 		err = perf_evlist__set_filter_pid(evlist, getpid());
 
 	if (err < 0) {
@@ -2342,7 +2342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
 	if (forks)
 		perf_evlist__start_workload(evlist);
 
-	trace->multiple_threads = evlist->threads->map[0] == -1 ||
+	trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
 				  evlist->threads->nr > 1 ||
 				  perf_evlist__first(evlist)->attr.inherit;
 again:
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 6245221479d7..ebc6e7938c9a 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)
 
 	perf_evsel__config(evsel, &opts);
 
-	evlist->threads->map[0] = getpid();
+	thread_map__pid(evlist->threads, 0) = getpid();
 
 	err = perf_evlist__open(evlist);
 	if (err < 0) {
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index df66966cfde7..3dab006b4a03 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -119,12 +119,12 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
 	if (per_cpu) {
 		mp->cpu = evlist->cpus->map[idx];
 		if (evlist->threads)
-			mp->tid = evlist->threads->map[0];
+			mp->tid = thread_map__pid(evlist->threads, 0);
 		else
 			mp->tid = -1;
 	} else {
 		mp->cpu = -1;
-		mp->tid = evlist->threads->map[idx];
+		mp->tid = thread_map__pid(evlist->threads, idx);
 	}
 }
 
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 793b1503d437..51a1bedf90fb 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -479,7 +479,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 	for (thread = 0; thread < threads->nr; ++thread) {
 		if (__event__synthesize_thread(comm_event, mmap_event,
 					       fork_event,
-					       threads->map[thread], 0,
+					       thread_map__pid(threads, thread), 0,
 					       process, tool, machine,
 					       mmap_data)) {
 			err = -1;
@@ -490,12 +490,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
 		 * comm.pid is set to thread group id by
 		 * perf_event__synthesize_comm
 		 */
-		if ((int) comm_event->comm.pid != threads->map[thread]) {
+		if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) {
 			bool need_leader = true;
 
 			/* is thread group leader in thread_map? */
 			for (j = 0; j < threads->nr; ++j) {
-				if ((int) comm_event->comm.pid == threads->map[j]) {
+				if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) {
 					need_leader = false;
 					break;
 				}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 8366511b45f8..a62b3adcc32b 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -548,7 +548,7 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
 	else
 		sid->cpu = -1;
 	if (!evsel->system_wide && evlist->threads && thread >= 0)
-		sid->tid = evlist->threads->map[thread];
+		sid->tid = thread_map__pid(evlist->threads, thread);
 	else
 		sid->tid = -1;
 }
@@ -1475,7 +1475,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
 				__func__, __LINE__);
 			goto out_close_pipes;
 		}
-		evlist->threads->map[0] = evlist->workload.pid;
+		thread_map__pid(evlist->threads, 0) = evlist->workload.pid;
 	}
 
 	close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 33449decf7bd..1b56047af96b 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1167,7 +1167,7 @@ retry_sample_id:
 			int group_fd;
 
 			if (!evsel->cgrp && !evsel->system_wide)
-				pid = threads->map[thread];
+				pid = thread_map__pid(threads, thread);
 
 			group_fd = get_group_fd(evsel, cpu, thread);
 retry_open:
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f4822bd03709..7f03f9facfdd 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -22,7 +22,7 @@ static int filter(const struct dirent *dir)
 
 static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
 {
-	size_t size = sizeof(*map) + sizeof(pid_t) * nr;
+	size_t size = sizeof(*map) + sizeof(struct thread_map_data) * nr;
 
 	return realloc(map, size);
 }
@@ -45,7 +45,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 	threads = thread_map__alloc(items);
 	if (threads != NULL) {
 		for (i = 0; i < items; i++)
-			threads->map[i] = atoi(namelist[i]->d_name);
+			thread_map__pid(threads, i) = atoi(namelist[i]->d_name);
 		threads->nr = items;
 	}
 
@@ -61,8 +61,8 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
 	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
-		threads->map[0] = tid;
-		threads->nr	= 1;
+		thread_map__pid(threads, 0) = tid;
+		threads->nr		    = 1;
 	}
 
 	return threads;
@@ -124,7 +124,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 		}
 
 		for (i = 0; i < items; i++)
-			threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
+			thread_map__pid(threads, threads->nr + i) = atoi(namelist[i]->d_name);
 
 		for (i = 0; i < items; i++)
 			zfree(&namelist[i]);
@@ -201,7 +201,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 		threads = nt;
 
 		for (i = 0; i < items; i++) {
-			threads->map[j++] = atoi(namelist[i]->d_name);
+			thread_map__pid(threads, j++) = atoi(namelist[i]->d_name);
 			zfree(&namelist[i]);
 		}
 		threads->nr = total_tasks;
@@ -227,8 +227,8 @@ struct thread_map *thread_map__new_dummy(void)
 	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
-		threads->map[0]	= -1;
-		threads->nr	= 1;
+		thread_map__pid(threads, 0) = -1;
+		threads->nr		    = 1;
 	}
 	return threads;
 }
@@ -267,8 +267,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 			goto out_free_threads;
 
 		threads = nt;
-		threads->map[ntasks - 1] = tid;
-		threads->nr		 = ntasks;
+		thread_map__pid(threads, ntasks - 1) = tid;
+		threads->nr			     = ntasks;
 	}
 out:
 	return threads;
@@ -301,7 +301,7 @@ size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
 	size_t printed = fprintf(fp, "%d thread%s: ",
 				 threads->nr, threads->nr > 1 ? "s" : "");
 	for (i = 0; i < threads->nr; ++i)
-		printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]);
+		printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i));
 
 	return printed + fprintf(fp, "\n");
 }
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 95313f43cc0f..9377850c7b71 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -4,11 +4,17 @@
 #include <sys/types.h>
 #include <stdio.h>
 
+struct thread_map_data {
+	pid_t    pid;
+};
+
 struct thread_map {
 	int nr;
-	pid_t map[];
+	struct thread_map_data map[];
 };
 
+#define thread_map__pid(__m, __t)  __m->map[__t].pid
+
 struct thread_map *thread_map__new_dummy(void);
 struct thread_map *thread_map__new_by_pid(pid_t pid);
 struct thread_map *thread_map__new_by_tid(pid_t tid);
-- 
1.9.3


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

* [PATCH 02/26] perf tools: Add comm string into struct thread_map
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
  2015-06-18 21:48 ` [PATCH 01/26] perf tools: Change thread_map::map into struct Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 03/26] perf tools: Add reference counting for cpu_map object Jiri Olsa
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Adding support to hold comm name together with pids in
'struct thread_map'. It will be useful for --per-task
option to display task pid together with task name.

Getting the task name from /proc/$pid/comm.

Link: http://lkml.kernel.org/n/tip-pf6bgmbujukce0sgliuhj2f4@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/python-ext-sources |  1 +
 tools/perf/util/thread_map.c       | 63 +++++++++++++++++++++++++++++++++++---
 tools/perf/util/thread_map.h       |  2 ++
 3 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 5925fec90562..e23ded40c79e 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -20,3 +20,4 @@ util/stat.c
 util/strlist.c
 util/trace-event.c
 ../../lib/rbtree.c
+util/string.c
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 7f03f9facfdd..f7a49a693d27 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -8,8 +8,10 @@
 #include <unistd.h>
 #include "strlist.h"
 #include <string.h>
+#include <api/fs/fs.h>
 #include "thread_map.h"
 #include "util.h"
+#include "debug.h"
 
 /* Skip "." and ".." directories */
 static int filter(const struct dirent *dir)
@@ -29,6 +31,44 @@ static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
 
 #define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
 
+static int get_comm(char **comm, pid_t pid)
+{
+	char *path;
+	size_t size;
+	int err;
+
+	if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1)
+		return -ENOMEM;
+
+	err = filename__read_str(path, comm, &size);
+	if (!err)
+		rtrim(*comm);
+
+	free(path);
+	return err;
+}
+
+static void comm_init(struct thread_map *map, int i)
+{
+	struct thread_map_data *data = &map->map[i];
+
+	/*
+	 * The comm name is like extra bonus ;-),
+	 * so just warn if we fail for any reason.
+	 */
+	data->comm = NULL;
+
+	/* dummy pid comm initialization */
+	if (data->pid == -1) {
+		data->comm = strdup("dummy");
+		return;
+	}
+
+	/* try to get pid's comm string */
+	if (get_comm(&data->comm, data->pid))
+		pr_warning("Couldn't resolve comm name for pid %d\n", data->pid);
+}
+
 struct thread_map *thread_map__new_by_pid(pid_t pid)
 {
 	struct thread_map *threads;
@@ -44,8 +84,10 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 
 	threads = thread_map__alloc(items);
 	if (threads != NULL) {
-		for (i = 0; i < items; i++)
+		for (i = 0; i < items; i++) {
 			thread_map__pid(threads, i) = atoi(namelist[i]->d_name);
+			comm_init(threads, i);
+		}
 		threads->nr = items;
 	}
 
@@ -63,6 +105,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
 	if (threads != NULL) {
 		thread_map__pid(threads, 0) = tid;
 		threads->nr		    = 1;
+		comm_init(threads, 0);
 	}
 
 	return threads;
@@ -123,8 +166,10 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 			threads = tmp;
 		}
 
-		for (i = 0; i < items; i++)
+		for (i = 0; i < items; i++) {
 			thread_map__pid(threads, threads->nr + i) = atoi(namelist[i]->d_name);
+			comm_init(threads, threads->nr + i);
+		}
 
 		for (i = 0; i < items; i++)
 			zfree(&namelist[i]);
@@ -200,8 +245,9 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 
 		threads = nt;
 
-		for (i = 0; i < items; i++) {
-			thread_map__pid(threads, j++) = atoi(namelist[i]->d_name);
+		for (i = 0; i < items; i++, j++) {
+			thread_map__pid(threads, j) = atoi(namelist[i]->d_name);
+			comm_init(threads, j);
 			zfree(&namelist[i]);
 		}
 		threads->nr = total_tasks;
@@ -229,6 +275,7 @@ struct thread_map *thread_map__new_dummy(void)
 	if (threads != NULL) {
 		thread_map__pid(threads, 0) = -1;
 		threads->nr		    = 1;
+		comm_init(threads, 0);
 	}
 	return threads;
 }
@@ -269,6 +316,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 		threads = nt;
 		thread_map__pid(threads, ntasks - 1) = tid;
 		threads->nr			     = ntasks;
+		comm_init(threads, ntasks - 1);
 	}
 out:
 	return threads;
@@ -292,6 +340,13 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
 
 void thread_map__delete(struct thread_map *threads)
 {
+	int i;
+
+	if (threads) {
+		for (i = 0; i < threads->nr; i++)
+			free(thread_map__comm(threads, i));
+	}
+
 	free(threads);
 }
 
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 9377850c7b71..6933f9d316d9 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -6,6 +6,7 @@
 
 struct thread_map_data {
 	pid_t    pid;
+	char	*comm;
 };
 
 struct thread_map {
@@ -14,6 +15,7 @@ struct thread_map {
 };
 
 #define thread_map__pid(__m, __t)  __m->map[__t].pid
+#define thread_map__comm(__m, __t) __m->map[__t].comm
 
 struct thread_map *thread_map__new_dummy(void);
 struct thread_map *thread_map__new_by_pid(pid_t pid);
-- 
1.9.3


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

* [PATCH 03/26] perf tools: Add reference counting for cpu_map object
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
  2015-06-18 21:48 ` [PATCH 01/26] perf tools: Change thread_map::map into struct Jiri Olsa
  2015-06-18 21:48 ` [PATCH 02/26] perf tools: Add comm string into struct thread_map Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 04/26] perf tools: Add reference counting for thread_map object Jiri Olsa
                   ` (22 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Adding refference counting for cpu_map object, so
it could be easily shared among other objects.

Using cpu_map__put instead cpu_map__delete and making
cpu_map__delete static.

Link: http://lkml.kernel.org/n/tip-gwy96ohuwhjz603bnf70af6i@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/code-reading.c    |  2 +-
 tools/perf/tests/keep-tracking.c   |  2 +-
 tools/perf/tests/mmap-basic.c      |  2 +-
 tools/perf/tests/switch-tracking.c |  2 +-
 tools/perf/util/cpumap.c           | 26 ++++++++++++++++++++++++--
 tools/perf/util/cpumap.h           |  6 +++++-
 tools/perf/util/evlist.c           |  4 ++--
 tools/perf/util/evsel.c            |  1 +
 tools/perf/util/parse-events.c     |  5 ++++-
 tools/perf/util/python.c           |  2 +-
 tools/perf/util/record.c           |  4 ++--
 tools/perf/util/session.c          |  2 +-
 tools/perf/util/svghelper.c        |  2 +-
 13 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index e2a432b67d52..86d17d2e9e50 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -545,7 +545,7 @@ out_err:
 	if (evlist) {
 		perf_evlist__delete(evlist);
 	} else {
-		cpu_map__delete(cpus);
+		cpu_map__put(cpus);
 		thread_map__delete(threads);
 	}
 	machines__destroy_kernel_maps(&machines);
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index 5b171d1e338b..a330235cefc0 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -144,7 +144,7 @@ out_err:
 		perf_evlist__disable(evlist);
 		perf_evlist__delete(evlist);
 	} else {
-		cpu_map__delete(cpus);
+		cpu_map__put(cpus);
 		thread_map__delete(threads);
 	}
 
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 5855cf471210..5a9ef5833452 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -140,7 +140,7 @@ out_delete_evlist:
 	cpus	= NULL;
 	threads = NULL;
 out_free_cpus:
-	cpu_map__delete(cpus);
+	cpu_map__put(cpus);
 out_free_threads:
 	thread_map__delete(threads);
 	return err;
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 0d31403ea593..1b06122beb76 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -560,7 +560,7 @@ out:
 		perf_evlist__disable(evlist);
 		perf_evlist__delete(evlist);
 	} else {
-		cpu_map__delete(cpus);
+		cpu_map__put(cpus);
 		thread_map__delete(threads);
 	}
 
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index c4e55b71010c..d2662d0e7d2e 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include "asm/bug.h"
 
 static struct cpu_map *cpu_map__default_new(void)
 {
@@ -22,6 +23,7 @@ static struct cpu_map *cpu_map__default_new(void)
 			cpus->map[i] = i;
 
 		cpus->nr = nr_cpus;
+		atomic_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -35,6 +37,7 @@ static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 	if (cpus != NULL) {
 		cpus->nr = nr_cpus;
 		memcpy(cpus->map, tmp_cpus, payload_size);
+		atomic_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
@@ -194,14 +197,32 @@ struct cpu_map *cpu_map__dummy_new(void)
 	if (cpus != NULL) {
 		cpus->nr = 1;
 		cpus->map[0] = -1;
+		atomic_set(&cpus->refcnt, 1);
 	}
 
 	return cpus;
 }
 
-void cpu_map__delete(struct cpu_map *map)
+static void cpu_map__delete(struct cpu_map *map)
 {
-	free(map);
+	if (map) {
+		WARN_ONCE(atomic_read(&map->refcnt) != 0,
+			  "cpu map refcnt disbalanced\n");
+		free(map);
+	}
+}
+
+struct cpu_map *cpu_map__get(struct cpu_map *map)
+{
+	if (map)
+		atomic_inc(&map->refcnt);
+	return map;
+}
+
+void cpu_map__put(struct cpu_map *map)
+{
+	if (map && atomic_dec_and_test(&map->refcnt))
+		cpu_map__delete(map);
 }
 
 int cpu_map__get_socket(struct cpu_map *map, int idx)
@@ -263,6 +284,7 @@ static int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
 	/* ensure we process id in increasing order */
 	qsort(c->map, c->nr, sizeof(int), cmp_ids);
 
+	atomic_set(&cpus->refcnt, 1);
 	*res = c;
 	return 0;
 }
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 61a654849002..0af9cecb4c51 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -3,18 +3,19 @@
 
 #include <stdio.h>
 #include <stdbool.h>
+#include <linux/atomic.h>
 
 #include "perf.h"
 #include "util/debug.h"
 
 struct cpu_map {
+	atomic_t refcnt;
 	int nr;
 	int map[];
 };
 
 struct cpu_map *cpu_map__new(const char *cpu_list);
 struct cpu_map *cpu_map__dummy_new(void);
-void cpu_map__delete(struct cpu_map *map);
 struct cpu_map *cpu_map__read(FILE *file);
 size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
 int cpu_map__get_socket(struct cpu_map *map, int idx);
@@ -22,6 +23,9 @@ int cpu_map__get_core(struct cpu_map *map, int idx);
 int cpu_map__build_socket_map(struct cpu_map *cpus, struct cpu_map **sockp);
 int cpu_map__build_core_map(struct cpu_map *cpus, struct cpu_map **corep);
 
+struct cpu_map *cpu_map__get(struct cpu_map *map);
+void cpu_map__put(struct cpu_map *map);
+
 static inline int cpu_map__socket(struct cpu_map *sock, int s)
 {
 	if (!sock || s > sock->nr || s < 0)
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index a62b3adcc32b..12c69cb1dd89 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -114,7 +114,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)
 {
 	perf_evlist__munmap(evlist);
 	perf_evlist__close(evlist);
-	cpu_map__delete(evlist->cpus);
+	cpu_map__put(evlist->cpus);
 	thread_map__delete(evlist->threads);
 	evlist->cpus = NULL;
 	evlist->threads = NULL;
@@ -1353,7 +1353,7 @@ static int perf_evlist__create_syswide_maps(struct perf_evlist *evlist)
 out:
 	return err;
 out_free_cpus:
-	cpu_map__delete(evlist->cpus);
+	cpu_map__put(evlist->cpus);
 	evlist->cpus = NULL;
 	goto out;
 }
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1b56047af96b..31b0afb68825 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -885,6 +885,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
 	perf_evsel__free_fd(evsel);
 	perf_evsel__free_id(evsel);
 	close_cgroup(evsel->cgrp);
+	cpu_map__put(evsel->cpus);
 	zfree(&evsel->group_name);
 	zfree(&evsel->name);
 	perf_evsel__object.fini(evsel);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 2a4d1ec02846..09f8d2357108 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -17,6 +17,7 @@
 #include "parse-events-flex.h"
 #include "pmu.h"
 #include "thread_map.h"
+#include "cpumap.h"
 #include "asm/bug.h"
 
 #define MAX_NAME_LEN 100
@@ -285,7 +286,9 @@ __add_event(struct list_head *list, int *idx,
 	if (!evsel)
 		return NULL;
 
-	evsel->cpus = cpus;
+	if (cpus)
+		evsel->cpus = cpu_map__get(cpus);
+
 	if (name)
 		evsel->name = strdup(name);
 	list_add_tail(&evsel->node, list);
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index d906d0ad5d40..b106d56df240 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -384,7 +384,7 @@ static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
 
 static void pyrf_cpu_map__delete(struct pyrf_cpu_map *pcpus)
 {
-	cpu_map__delete(pcpus->cpus);
+	cpu_map__put(pcpus->cpus);
 	pcpus->ob_type->tp_free((PyObject*)pcpus);
 }
 
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index d457c523a33d..1f7becbe5e18 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -64,7 +64,7 @@ static bool perf_probe_api(setup_probe_fn_t fn)
 	if (!cpus)
 		return false;
 	cpu = cpus->map[0];
-	cpu_map__delete(cpus);
+	cpu_map__put(cpus);
 
 	do {
 		ret = perf_do_probe_api(fn, cpu, try[i++]);
@@ -226,7 +226,7 @@ bool perf_evlist__can_select_event(struct perf_evlist *evlist, const char *str)
 		struct cpu_map *cpus = cpu_map__new(NULL);
 
 		cpu =  cpus ? cpus->map[0] : 0;
-		cpu_map__delete(cpus);
+		cpu_map__put(cpus);
 	} else {
 		cpu = evlist->cpus->map[0];
 	}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index e1cd17c2afab..d63a97c74eaa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1860,7 +1860,7 @@ int perf_session__cpu_bitmap(struct perf_session *session,
 	err = 0;
 
 out_delete_map:
-	cpu_map__delete(map);
+	cpu_map__put(map);
 	return err;
 }
 
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index 283d3e73e2f2..eec6c1149f44 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -748,7 +748,7 @@ static int str_to_bitmap(char *s, cpumask_t *b)
 		set_bit(c, cpumask_bits(b));
 	}
 
-	cpu_map__delete(m);
+	cpu_map__put(m);
 
 	return ret;
 }
-- 
1.9.3


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

* [PATCH 04/26] perf tools: Add reference counting for thread_map object
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (2 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 03/26] perf tools: Add reference counting for cpu_map object Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 05/26] perf tools: Propagate cpu maps through the evlist Jiri Olsa
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Adding refference counting for thread_map object, so
it could be easily shared among other objects.

Using thread_map__put instead thread_map__delete and making
thread_map__delete static.

Link: http://lkml.kernel.org/n/tip-myadl53clbkjvzeqolwp95w0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/code-reading.c            |  2 +-
 tools/perf/tests/keep-tracking.c           |  2 +-
 tools/perf/tests/mmap-basic.c              |  2 +-
 tools/perf/tests/mmap-thread-lookup.c      |  2 +-
 tools/perf/tests/openat-syscall-all-cpus.c |  2 +-
 tools/perf/tests/openat-syscall.c          |  2 +-
 tools/perf/tests/switch-tracking.c         |  2 +-
 tools/perf/util/evlist.c                   |  4 ++--
 tools/perf/util/python.c                   |  2 +-
 tools/perf/util/thread_map.c               | 31 ++++++++++++++++++++++++++----
 tools/perf/util/thread_map.h               |  7 +++++--
 11 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index 86d17d2e9e50..7dcd2c3d865f 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -546,7 +546,7 @@ out_err:
 		perf_evlist__delete(evlist);
 	} else {
 		cpu_map__put(cpus);
-		thread_map__delete(threads);
+		thread_map__put(threads);
 	}
 	machines__destroy_kernel_maps(&machines);
 	machine__delete_threads(machine);
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index a330235cefc0..4d4b9837b630 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -145,7 +145,7 @@ out_err:
 		perf_evlist__delete(evlist);
 	} else {
 		cpu_map__put(cpus);
-		thread_map__delete(threads);
+		thread_map__put(threads);
 	}
 
 	return err;
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 5a9ef5833452..666b67a4df9d 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -142,6 +142,6 @@ out_delete_evlist:
 out_free_cpus:
 	cpu_map__put(cpus);
 out_free_threads:
-	thread_map__delete(threads);
+	thread_map__put(threads);
 	return err;
 }
diff --git a/tools/perf/tests/mmap-thread-lookup.c b/tools/perf/tests/mmap-thread-lookup.c
index 264e215c0d36..412a41eb3f81 100644
--- a/tools/perf/tests/mmap-thread-lookup.c
+++ b/tools/perf/tests/mmap-thread-lookup.c
@@ -143,7 +143,7 @@ static int synth_process(struct machine *machine)
 						perf_event__process,
 						machine, 0);
 
-	thread_map__delete(map);
+	thread_map__put(map);
 	return err;
 }
 
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 9a7a116e09b8..b8d552b13950 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -111,6 +111,6 @@ out_close_fd:
 out_evsel_delete:
 	perf_evsel__delete(evsel);
 out_thread_map_delete:
-	thread_map__delete(threads);
+	thread_map__put(threads);
 	return err;
 }
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 9f9491bb8e48..bdfa1f446681 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -56,6 +56,6 @@ out_close_fd:
 out_evsel_delete:
 	perf_evsel__delete(evsel);
 out_thread_map_delete:
-	thread_map__delete(threads);
+	thread_map__put(threads);
 	return err;
 }
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index 1b06122beb76..e698742d4fec 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -561,7 +561,7 @@ out:
 		perf_evlist__delete(evlist);
 	} else {
 		cpu_map__put(cpus);
-		thread_map__delete(threads);
+		thread_map__put(threads);
 	}
 
 	return err;
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 12c69cb1dd89..b8b2090d13da 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -115,7 +115,7 @@ void perf_evlist__delete(struct perf_evlist *evlist)
 	perf_evlist__munmap(evlist);
 	perf_evlist__close(evlist);
 	cpu_map__put(evlist->cpus);
-	thread_map__delete(evlist->threads);
+	thread_map__put(evlist->threads);
 	evlist->cpus = NULL;
 	evlist->threads = NULL;
 	perf_evlist__purge(evlist);
@@ -1120,7 +1120,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 	return 0;
 
 out_delete_threads:
-	thread_map__delete(evlist->threads);
+	thread_map__put(evlist->threads);
 	evlist->threads = NULL;
 	return -1;
 }
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index b106d56df240..626422eda727 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -453,7 +453,7 @@ static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
 
 static void pyrf_thread_map__delete(struct pyrf_thread_map *pthreads)
 {
-	thread_map__delete(pthreads->threads);
+	thread_map__put(pthreads->threads);
 	pthreads->ob_type->tp_free((PyObject*)pthreads);
 }
 
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f7a49a693d27..26177ce254da 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -9,6 +9,7 @@
 #include "strlist.h"
 #include <string.h>
 #include <api/fs/fs.h>
+#include "asm/bug.h"
 #include "thread_map.h"
 #include "util.h"
 #include "debug.h"
@@ -89,6 +90,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 			comm_init(threads, i);
 		}
 		threads->nr = items;
+		atomic_set(&threads->refcnt, 1);
 	}
 
 	for (i=0; i<items; i++)
@@ -106,6 +108,7 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
 		thread_map__pid(threads, 0) = tid;
 		threads->nr		    = 1;
 		comm_init(threads, 0);
+		atomic_set(&threads->refcnt, 1);
 	}
 
 	return threads;
@@ -127,6 +130,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 		goto out_free_threads;
 
 	threads->nr = 0;
+	atomic_set(&threads->refcnt, 1);
 
 	while (!readdir_r(proc, &dirent, &next) && next) {
 		char *end;
@@ -256,6 +260,8 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 
 out:
 	strlist__delete(slist);
+	if (threads)
+		atomic_set(&threads->refcnt, 1);
 	return threads;
 
 out_free_namelist:
@@ -276,6 +282,7 @@ struct thread_map *thread_map__new_dummy(void)
 		thread_map__pid(threads, 0) = -1;
 		threads->nr		    = 1;
 		comm_init(threads, 0);
+		atomic_set(&threads->refcnt, 1);
 	}
 	return threads;
 }
@@ -319,6 +326,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 		comm_init(threads, ntasks - 1);
 	}
 out:
+	if (threads)
+		atomic_set(&threads->refcnt, 1);
 	return threads;
 
 out_free_threads:
@@ -338,16 +347,30 @@ struct thread_map *thread_map__new_str(const char *pid, const char *tid,
 	return thread_map__new_by_tid_str(tid);
 }
 
-void thread_map__delete(struct thread_map *threads)
+static void thread_map__delete(struct thread_map *threads)
 {
-	int i;
-
 	if (threads) {
+		int i;
+
+		WARN_ONCE(atomic_read(&threads->refcnt) != 0,
+			  "thread map refcnt disbalanced\n");
 		for (i = 0; i < threads->nr; i++)
 			free(thread_map__comm(threads, i));
+		free(threads);
 	}
+}
 
-	free(threads);
+struct thread_map *thread_map__get(struct thread_map *map)
+{
+	if (map)
+		atomic_inc(&map->refcnt);
+	return map;
+}
+
+void thread_map__put(struct thread_map *map)
+{
+	if (map && atomic_dec_and_test(&map->refcnt))
+		thread_map__delete(map);
 }
 
 size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 6933f9d316d9..91207cee7294 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -3,6 +3,7 @@
 
 #include <sys/types.h>
 #include <stdio.h>
+#include <linux/atomic.h>
 
 struct thread_map_data {
 	pid_t    pid;
@@ -10,6 +11,7 @@ struct thread_map_data {
 };
 
 struct thread_map {
+	atomic_t refcnt;
 	int nr;
 	struct thread_map_data map[];
 };
@@ -23,11 +25,12 @@ struct thread_map *thread_map__new_by_tid(pid_t tid);
 struct thread_map *thread_map__new_by_uid(uid_t uid);
 struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
 
+struct thread_map *thread_map__get(struct thread_map *map);
+void thread_map__put(struct thread_map *map);
+
 struct thread_map *thread_map__new_str(const char *pid,
 		const char *tid, uid_t uid);
 
-void thread_map__delete(struct thread_map *threads);
-
 size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
 
 static inline int thread_map__nr(struct thread_map *threads)
-- 
1.9.3


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

* [PATCH 05/26] perf tools: Propagate cpu maps through the evlist
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (3 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 04/26] perf tools: Add reference counting for thread_map object Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 06/26] perf tools: Propagate thread " Jiri Olsa
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Propagate evlist's cpu_map object through all the evsel objects,
while keeping already configured evsel->cpus.

It'll be handy to access evsel's cpus directly
in following patches.

Link: http://lkml.kernel.org/n/tip-myadl53clbkjvzeqolwp95w0@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evlist.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b8b2090d13da..084fe2e68ecb 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1101,6 +1101,29 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
 }
 
+static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
+				       struct target *target)
+{
+	struct perf_evsel *evsel;
+
+	evlist__for_each(evlist, evsel) {
+		/*
+		 * We already have cpus for evsel (via PMU sysfs) so
+		 * keep it, if there's no target cpu list defined.
+		 */
+		if (evsel->cpus && target->cpu_list)
+			cpu_map__put(evsel->cpus);
+
+		if (!evsel->cpus || target->cpu_list)
+			evsel->cpus = cpu_map__get(evlist->cpus);
+
+		if (!evsel->cpus)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
 int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 {
 	evlist->threads = thread_map__new_str(target->pid, target->tid,
@@ -1117,7 +1140,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 	if (evlist->cpus == NULL)
 		goto out_delete_threads;
 
-	return 0;
+	return perf_evlist__propagate_maps(evlist, target);
 
 out_delete_threads:
 	thread_map__put(evlist->threads);
-- 
1.9.3


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

* [PATCH 06/26] perf tools: Propagate thread maps through the evlist
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (4 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 05/26] perf tools: Propagate cpu maps through the evlist Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 07/26] perf tools: Make perf_evsel__(nr_)cpus generic Jiri Olsa
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Propagate evlist's thread_map object through all the
evsel objects.

It'll be handy to access evsel's threads directly
in following patches. The reason is there's no link
from evsel to evlist which hold threads map now and
evlist is not always available.

Link: http://lkml.kernel.org/n/tip-6vc92bytyy2d6c5entm5s698@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evlist.c | 4 +++-
 tools/perf/util/evsel.c  | 1 +
 tools/perf/util/evsel.h  | 1 +
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 084fe2e68ecb..f1cdf9373da6 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1117,7 +1117,9 @@ static int perf_evlist__propagate_maps(struct perf_evlist *evlist,
 		if (!evsel->cpus || target->cpu_list)
 			evsel->cpus = cpu_map__get(evlist->cpus);
 
-		if (!evsel->cpus)
+		evsel->threads = thread_map__get(evlist->threads);
+
+		if (!evsel->cpus || !evsel->threads)
 			return -ENOMEM;
 	}
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 31b0afb68825..1b2f480a3e82 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -886,6 +886,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
 	perf_evsel__free_id(evsel);
 	close_cgroup(evsel->cgrp);
 	cpu_map__put(evsel->cpus);
+	thread_map__put(evsel->threads);
 	zfree(&evsel->group_name);
 	zfree(&evsel->name);
 	perf_evsel__object.fini(evsel);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index bb0579e8a10a..9e16a5c4eb01 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -82,6 +82,7 @@ struct perf_evsel {
 	struct cgroup_sel	*cgrp;
 	void			*handler;
 	struct cpu_map		*cpus;
+	struct thread_map	*threads;
 	unsigned int		sample_size;
 	int			id_pos;
 	int			is_pos;
-- 
1.9.3


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

* [PATCH 07/26] perf tools: Make perf_evsel__(nr_)cpus generic
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (5 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 06/26] perf tools: Propagate thread " Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 08/26] perf tests: Add thread_map object tests Jiri Olsa
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Because we now propagate all evlist's cpu_maps and thread_map
objects through all evsels, the perf_evsel__(nr_)cpus no longer
need to be specific to stat object and check evlist and target
objects.

Link: http://lkml.kernel.org/n/tip-3pp2i969cmewv580k6qvd3up@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 10 ----------
 tools/perf/util/evsel.h   | 11 +++++++++++
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index fcf99bdeb19e..3e1636cae76b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -141,16 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
 	}
 }
 
-static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
-{
-	return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
-}
-
-static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
-{
-	return perf_evsel__cpus(evsel)->nr;
-}
-
 static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
 {
 	int i;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 9e16a5c4eb01..4dbf32d94dfb 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -8,6 +8,7 @@
 #include <linux/types.h>
 #include "xyarray.h"
 #include "symbol.h"
+#include "cpumap.h"
 
 struct perf_counts_values {
 	union {
@@ -114,6 +115,16 @@ struct thread_map;
 struct perf_evlist;
 struct record_opts;
 
+static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+{
+	return evsel->cpus;
+}
+
+static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
+{
+	return perf_evsel__cpus(evsel)->nr;
+}
+
 void perf_counts_values__scale(struct perf_counts_values *count,
 			       bool scale, s8 *pscaled);
 
-- 
1.9.3


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

* [PATCH 08/26] perf tests: Add thread_map object tests
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (6 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 07/26] perf tools: Make perf_evsel__(nr_)cpus generic Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 09/26] perf stat: Introduce perf_counts function Jiri Olsa
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Adding thread_map object tests for comm name values.

Link: http://lkml.kernel.org/n/tip-opjrl8os3je8wl93ujkm8sbh@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/Build          |  1 +
 tools/perf/tests/builtin-test.c |  4 ++++
 tools/perf/tests/tests.h        |  1 +
 tools/perf/tests/thread-map.c   | 28 ++++++++++++++++++++++++++++
 4 files changed, 34 insertions(+)
 create mode 100644 tools/perf/tests/thread-map.c

diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index ee41e705b2eb..d20d6e6ab65b 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -31,6 +31,7 @@ perf-y += code-reading.o
 perf-y += sample-parsing.o
 perf-y += parse-no-sample-id-all.o
 perf-y += kmod-path.o
+perf-y += thread-map.o
 
 perf-$(CONFIG_X86) += perf-time-to-tsc.o
 
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 87b9961646e4..c1dde733c3a6 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -171,6 +171,10 @@ static struct test {
 		.func = test__kmod_path__parse,
 	},
 	{
+		.desc = "Test thread map",
+		.func = test__thread_map,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 8e5038b48ba8..ebb47d96bc0b 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -61,6 +61,7 @@ int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
 int test__kmod_path__parse(void);
+int test__thread_map(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
new file mode 100644
index 000000000000..faf22f64b8af
--- /dev/null
+++ b/tools/perf/tests/thread-map.c
@@ -0,0 +1,28 @@
+#include <sys/types.h>
+#include <unistd.h>
+#include "tests.h"
+#include "thread_map.h"
+#include "debug.h"
+
+int test__thread_map(void)
+{
+	struct thread_map *map;
+
+	/* test map on current pid */
+	map = thread_map__new_by_pid(getpid());
+	TEST_ASSERT_VAL("wrong nr", map->nr == 1);
+	TEST_ASSERT_VAL("wrong pid",
+			thread_map__pid(map, 0) == getpid());
+	TEST_ASSERT_VAL("wrong pid",
+			!strcmp(thread_map__comm(map, 0), "perf"));
+	thread_map__put(map);
+
+	/* test dummy pid */
+	map = thread_map__new_dummy();
+	TEST_ASSERT_VAL("wrong nr", map->nr == 1);
+	TEST_ASSERT_VAL("wrong pid", thread_map__pid(map, 0) == -1);
+	TEST_ASSERT_VAL("wrong pid",
+			!strcmp(thread_map__comm(map, 0), "dummy"));
+	thread_map__put(map);
+	return 0;
+}
-- 
1.9.3


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

* [PATCH 09/26] perf stat: Introduce perf_counts function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (7 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 08/26] perf tests: Add thread_map object tests Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 10/26] perf stat: Use xyarray for cpu evsel counts Jiri Olsa
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Introducing perf_counts function, that returns
'struct perf_counts_values' pointer for given cpu.

Also moving perf_counts* structures into stat.h.

Link: http://lkml.kernel.org/n/tip-qu64zmm5zbpbkuybusnkg4gl@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c                  | 14 +++++++-------
 tools/perf/tests/openat-syscall-all-cpus.c |  4 ++--
 tools/perf/tests/openat-syscall.c          |  2 +-
 tools/perf/util/evsel.c                    |  6 +++---
 tools/perf/util/evsel.h                    | 18 +-----------------
 tools/perf/util/stat.h                     | 23 +++++++++++++++++++++++
 6 files changed, 37 insertions(+), 30 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3e1636cae76b..49b90374232c 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -316,7 +316,7 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, count);
 		perf_counts_values__scale(count, scale, NULL);
-		evsel->counts->cpu[cpu] = *count;
+		*perf_counts(evsel->counts, cpu) = *count;
 		if (aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
@@ -805,9 +805,9 @@ static void print_aggr(char *prefix)
 				s2 = aggr_get_id(evsel_list->cpus, cpu2);
 				if (s2 != id)
 					continue;
-				val += counter->counts->cpu[cpu].val;
-				ena += counter->counts->cpu[cpu].ena;
-				run += counter->counts->cpu[cpu].run;
+				val += perf_counts(counter->counts, cpu)->val;
+				ena += perf_counts(counter->counts, cpu)->ena;
+				run += perf_counts(counter->counts, cpu)->run;
 				nr++;
 			}
 			if (prefix)
@@ -915,9 +915,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 	int cpu;
 
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		val = counter->counts->cpu[cpu].val;
-		ena = counter->counts->cpu[cpu].ena;
-		run = counter->counts->cpu[cpu].run;
+		val = perf_counts(counter->counts, cpu)->val;
+		ena = perf_counts(counter->counts, cpu)->ena;
+		run = perf_counts(counter->counts, cpu)->run;
 
 		if (prefix)
 			fprintf(output, "%s", prefix);
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index b8d552b13950..e8d944fe1bd0 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void)
 		}
 
 		expected = nr_openat_calls + cpu;
-		if (evsel->counts->cpu[cpu].val != expected) {
+		if (perf_counts(evsel->counts, cpu)->val != expected) {
 			pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
-				 expected, cpus->map[cpu], evsel->counts->cpu[cpu].val);
+				 expected, cpus->map[cpu], perf_counts(evsel->counts, cpu)->val);
 			err = -1;
 		}
 	}
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index bdfa1f446681..e86fc477a74f 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -44,7 +44,7 @@ int test__openat_syscall_event(void)
 		goto out_close_fd;
 	}
 
-	if (evsel->counts->cpu[0].val != nr_openat_calls) {
+	if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) {
 		pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
 			 nr_openat_calls, evsel->counts->cpu[0].val);
 		goto out_close_fd;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 1b2f480a3e82..8401b042b9d4 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
 		tmp = evsel->prev_raw_counts->aggr;
 		evsel->prev_raw_counts->aggr = *count;
 	} else {
-		tmp = evsel->prev_raw_counts->cpu[cpu];
-		evsel->prev_raw_counts->cpu[cpu] = *count;
+		tmp = *perf_counts(evsel->prev_raw_counts, cpu);
+		*perf_counts(evsel->prev_raw_counts, cpu) = *count;
 	}
 
 	count->val = count->val - tmp.val;
@@ -972,7 +972,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
 
 	perf_evsel__compute_deltas(evsel, cpu, &count);
 	perf_counts_values__scale(&count, scale, NULL);
-	evsel->counts->cpu[cpu] = count;
+	*perf_counts(evsel->counts, cpu) = count;
 	return 0;
 }
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4dbf32d94dfb..b420f8f5fc5d 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -9,23 +9,7 @@
 #include "xyarray.h"
 #include "symbol.h"
 #include "cpumap.h"
-
-struct perf_counts_values {
-	union {
-		struct {
-			u64 val;
-			u64 ena;
-			u64 run;
-		};
-		u64 values[3];
-	};
-};
-
-struct perf_counts {
-	s8		   	  scaled;
-	struct perf_counts_values aggr;
-	struct perf_counts_values cpu[];
-};
+#include "stat.h"
 
 struct perf_evsel;
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 093dc3cb28dd..5e43348836a6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -31,6 +31,29 @@ enum aggr_mode {
 	AGGR_CORE,
 };
 
+struct perf_counts_values {
+	union {
+		struct {
+			u64 val;
+			u64 ena;
+			u64 run;
+		};
+		u64 values[3];
+	};
+};
+
+struct perf_counts {
+	s8			  scaled;
+	struct perf_counts_values aggr;
+	struct perf_counts_values cpu[];
+};
+
+static inline struct perf_counts_values*
+perf_counts(struct perf_counts *counts, int cpu)
+{
+	return &counts->cpu[cpu];
+}
+
 void update_stats(struct stats *stats, u64 val);
 double avg_stats(struct stats *stats);
 double stddev_stats(struct stats *stats);
-- 
1.9.3


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

* [PATCH 10/26] perf stat: Use xyarray for cpu evsel counts
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (8 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 09/26] perf stat: Introduce perf_counts function Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 11/26] perf stat: Make stats work over the thread dimension Jiri Olsa
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Switching single dimensional array of 'struct perf_counts_values'
with xyarray object, so we could store thread dimension counts.

Link: http://lkml.kernel.org/n/tip-t1wefzwb3z78sjlpzt95lw61@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c         |  2 +-
 tools/perf/tests/openat-syscall.c |  2 +-
 tools/perf/util/stat.c            | 31 ++++++++++++++++++++++---------
 tools/perf/util/stat.h            |  7 ++++---
 4 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 49b90374232c..055ce83dd6f2 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -218,7 +218,7 @@ static void perf_stat__reset_stats(struct perf_evlist *evlist)
 
 	evlist__for_each(evlist, evsel) {
 		perf_evsel__reset_stat_priv(evsel);
-		perf_evsel__reset_counts(evsel, perf_evsel__nr_cpus(evsel));
+		perf_evsel__reset_counts(evsel);
 	}
 
 	perf_stat__reset_shadow_stats();
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index e86fc477a74f..bd882f09ebbc 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -46,7 +46,7 @@ int test__openat_syscall_event(void)
 
 	if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) {
 		pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
-			 nr_openat_calls, evsel->counts->cpu[0].val);
+			 nr_openat_calls, perf_counts(evsel->counts, 0)->val);
 		goto out_close_fd;
 	}
 
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 4014b709f956..453480aa7650 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -97,26 +97,39 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 
 struct perf_counts *perf_counts__new(int ncpus)
 {
-	int size = sizeof(struct perf_counts) +
-		   ncpus * sizeof(struct perf_counts_values);
+	struct perf_counts *counts = zalloc(sizeof(*counts));
 
-	return zalloc(size);
+	if (counts) {
+		struct xyarray *cpu;
+
+		cpu = xyarray__new(ncpus, 1, sizeof(struct perf_counts_values));
+		if (!cpu) {
+			free(counts);
+			return NULL;
+		}
+
+		counts->cpu = cpu;
+	}
+
+	return counts;
 }
 
 void perf_counts__delete(struct perf_counts *counts)
 {
-	free(counts);
+	if (counts) {
+		xyarray__delete(counts->cpu);
+		free(counts);
+	}
 }
 
-static void perf_counts__reset(struct perf_counts *counts, int ncpus)
+static void perf_counts__reset(struct perf_counts *counts)
 {
-	memset(counts, 0, (sizeof(*counts) +
-	       (ncpus * sizeof(struct perf_counts_values))));
+	xyarray__reset(counts->cpu);
 }
 
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
+void perf_evsel__reset_counts(struct perf_evsel *evsel)
 {
-	perf_counts__reset(evsel->counts, ncpus);
+	perf_counts__reset(evsel->counts);
 }
 
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 5e43348836a6..6d07612545e0 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -3,6 +3,7 @@
 
 #include <linux/types.h>
 #include <stdio.h>
+#include "xyarray.h"
 
 struct stats
 {
@@ -45,13 +46,13 @@ struct perf_counts_values {
 struct perf_counts {
 	s8			  scaled;
 	struct perf_counts_values aggr;
-	struct perf_counts_values cpu[];
+	struct xyarray		  *cpu;
 };
 
 static inline struct perf_counts_values*
 perf_counts(struct perf_counts *counts, int cpu)
 {
-	return &counts->cpu[cpu];
+	return xyarray__entry(counts->cpu, cpu, 0);
 }
 
 void update_stats(struct stats *stats, u64 val);
@@ -88,7 +89,7 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
 struct perf_counts *perf_counts__new(int ncpus);
 void perf_counts__delete(struct perf_counts *counts);
 
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
+void perf_evsel__reset_counts(struct perf_evsel *evsel);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
 void perf_evsel__free_counts(struct perf_evsel *evsel);
 #endif
-- 
1.9.3


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

* [PATCH 11/26] perf stat: Make stats work over the thread dimension
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (9 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 10/26] perf stat: Use xyarray for cpu evsel counts Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 12/26] perf stat: Rename struct perf_counts::cpu member to values Jiri Olsa
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Now that we have space for thread dimension counts,
let's store it.

Link: http://lkml.kernel.org/n/tip-vvu96knzwli7ajpjz7qu8jfl@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c                  | 32 +++++++++++++++++-------------
 tools/perf/tests/openat-syscall-all-cpus.c |  6 +++---
 tools/perf/tests/openat-syscall.c          |  4 ++--
 tools/perf/util/evsel.c                    | 12 +++++------
 tools/perf/util/evsel.h                    |  2 +-
 tools/perf/util/stat.c                     |  8 ++++----
 tools/perf/util/stat.h                     |  8 ++++----
 7 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 055ce83dd6f2..983bcbbe8e0a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -166,11 +166,12 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 	zfree(&evsel->priv);
 }
 
-static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
+static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+					     int ncpus, int nthreads)
 {
 	struct perf_counts *counts;
 
-	counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
+	counts = perf_counts__new(ncpus, nthreads);
 	if (counts)
 		evsel->prev_raw_counts = counts;
 
@@ -197,11 +198,14 @@ static void perf_evlist__free_stats(struct perf_evlist *evlist)
 static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
 {
 	struct perf_evsel *evsel;
+	int nthreads = thread_map__nr(evsel_list->threads);
 
 	evlist__for_each(evlist, evsel) {
+		int ncpus = perf_evsel__nr_cpus(evsel);
+
 		if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
-		    perf_evsel__alloc_counts(evsel, perf_evsel__nr_cpus(evsel)) < 0 ||
-		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel) < 0))
+		    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
+		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
 			goto out_free;
 	}
 
@@ -294,7 +298,7 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
 	return 0;
 }
 
-static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
+static int read_cb(struct perf_evsel *evsel, int cpu, int thread,
 		   struct perf_counts_values *count)
 {
 	struct perf_counts_values *aggr = &evsel->counts->aggr;
@@ -314,9 +318,9 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread __maybe_unused,
 	case AGGR_SOCKET:
 	case AGGR_NONE:
 		if (!evsel->snapshot)
-			perf_evsel__compute_deltas(evsel, cpu, count);
+			perf_evsel__compute_deltas(evsel, cpu, thread, count);
 		perf_counts_values__scale(count, scale, NULL);
-		*perf_counts(evsel->counts, cpu) = *count;
+		*perf_counts(evsel->counts, cpu, thread) = *count;
 		if (aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
@@ -352,7 +356,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
 		return -1;
 
 	if (!counter->snapshot)
-		perf_evsel__compute_deltas(counter, -1, aggr);
+		perf_evsel__compute_deltas(counter, -1, -1, aggr);
 	perf_counts_values__scale(aggr, scale, &counter->counts->scaled);
 
 	for (i = 0; i < 3; i++)
@@ -805,9 +809,9 @@ static void print_aggr(char *prefix)
 				s2 = aggr_get_id(evsel_list->cpus, cpu2);
 				if (s2 != id)
 					continue;
-				val += perf_counts(counter->counts, cpu)->val;
-				ena += perf_counts(counter->counts, cpu)->ena;
-				run += perf_counts(counter->counts, cpu)->run;
+				val += perf_counts(counter->counts, cpu, 0)->val;
+				ena += perf_counts(counter->counts, cpu, 0)->ena;
+				run += perf_counts(counter->counts, cpu, 0)->run;
 				nr++;
 			}
 			if (prefix)
@@ -915,9 +919,9 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 	int cpu;
 
 	for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
-		val = perf_counts(counter->counts, cpu)->val;
-		ena = perf_counts(counter->counts, cpu)->ena;
-		run = perf_counts(counter->counts, cpu)->run;
+		val = perf_counts(counter->counts, cpu, 0)->val;
+		ena = perf_counts(counter->counts, cpu, 0)->ena;
+		run = perf_counts(counter->counts, cpu, 0)->run;
 
 		if (prefix)
 			fprintf(output, "%s", prefix);
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index e8d944fe1bd0..a572f87e9c8d 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -78,7 +78,7 @@ int test__openat_syscall_event_on_all_cpus(void)
 	 * we use the auto allocation it will allocate just for 1 cpu,
 	 * as we start by cpu 0.
 	 */
-	if (perf_evsel__alloc_counts(evsel, cpus->nr) < 0) {
+	if (perf_evsel__alloc_counts(evsel, cpus->nr, 1) < 0) {
 		pr_debug("perf_evsel__alloc_counts(ncpus=%d)\n", cpus->nr);
 		goto out_close_fd;
 	}
@@ -98,9 +98,9 @@ int test__openat_syscall_event_on_all_cpus(void)
 		}
 
 		expected = nr_openat_calls + cpu;
-		if (perf_counts(evsel->counts, cpu)->val != expected) {
+		if (perf_counts(evsel->counts, cpu, 0)->val != expected) {
 			pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls on cpu %d, got %" PRIu64 "\n",
-				 expected, cpus->map[cpu], perf_counts(evsel->counts, cpu)->val);
+				 expected, cpus->map[cpu], perf_counts(evsel->counts, cpu, 0)->val);
 			err = -1;
 		}
 	}
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index bd882f09ebbc..c9a37bc6b33a 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -44,9 +44,9 @@ int test__openat_syscall_event(void)
 		goto out_close_fd;
 	}
 
-	if (perf_counts(evsel->counts, 0)->val != nr_openat_calls) {
+	if (perf_counts(evsel->counts, 0, 0)->val != nr_openat_calls) {
 		pr_debug("perf_evsel__read_on_cpu: expected to intercept %d calls, got %" PRIu64 "\n",
-			 nr_openat_calls, perf_counts(evsel->counts, 0)->val);
+			 nr_openat_calls, perf_counts(evsel->counts, 0, 0)->val);
 		goto out_close_fd;
 	}
 
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8401b042b9d4..cd6ce7066f85 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -898,7 +898,7 @@ void perf_evsel__delete(struct perf_evsel *evsel)
 	free(evsel);
 }
 
-void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
+void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread,
 				struct perf_counts_values *count)
 {
 	struct perf_counts_values tmp;
@@ -910,8 +910,8 @@ void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
 		tmp = evsel->prev_raw_counts->aggr;
 		evsel->prev_raw_counts->aggr = *count;
 	} else {
-		tmp = *perf_counts(evsel->prev_raw_counts, cpu);
-		*perf_counts(evsel->prev_raw_counts, cpu) = *count;
+		tmp = *perf_counts(evsel->prev_raw_counts, cpu, thread);
+		*perf_counts(evsel->prev_raw_counts, cpu, thread) = *count;
 	}
 
 	count->val = count->val - tmp.val;
@@ -964,15 +964,15 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
 	if (FD(evsel, cpu, thread) < 0)
 		return -EINVAL;
 
-	if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1) < 0)
+	if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0)
 		return -ENOMEM;
 
 	if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0)
 		return -errno;
 
-	perf_evsel__compute_deltas(evsel, cpu, &count);
+	perf_evsel__compute_deltas(evsel, cpu, thread, &count);
 	perf_counts_values__scale(&count, scale, NULL);
-	*perf_counts(evsel->counts, cpu) = count;
+	*perf_counts(evsel->counts, cpu, thread) = count;
 	return 0;
 }
 
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index b420f8f5fc5d..020f7e13634a 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -112,7 +112,7 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
 void perf_counts_values__scale(struct perf_counts_values *count,
 			       bool scale, s8 *pscaled);
 
-void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu,
+void perf_evsel__compute_deltas(struct perf_evsel *evsel, int cpu, int thread,
 				struct perf_counts_values *count);
 
 int perf_evsel__object_config(size_t object_size,
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 453480aa7650..7bcc19b62dd1 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -95,14 +95,14 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 	}
 }
 
-struct perf_counts *perf_counts__new(int ncpus)
+struct perf_counts *perf_counts__new(int ncpus, int nthreads)
 {
 	struct perf_counts *counts = zalloc(sizeof(*counts));
 
 	if (counts) {
 		struct xyarray *cpu;
 
-		cpu = xyarray__new(ncpus, 1, sizeof(struct perf_counts_values));
+		cpu = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
 		if (!cpu) {
 			free(counts);
 			return NULL;
@@ -132,9 +132,9 @@ void perf_evsel__reset_counts(struct perf_evsel *evsel)
 	perf_counts__reset(evsel->counts);
 }
 
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads)
 {
-	evsel->counts = perf_counts__new(ncpus);
+	evsel->counts = perf_counts__new(ncpus, nthreads);
 	return evsel->counts != NULL ? 0 : -ENOMEM;
 }
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 6d07612545e0..e0b8dc50fbb6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -50,9 +50,9 @@ struct perf_counts {
 };
 
 static inline struct perf_counts_values*
-perf_counts(struct perf_counts *counts, int cpu)
+perf_counts(struct perf_counts *counts, int cpu, int thread)
 {
-	return xyarray__entry(counts->cpu, cpu, 0);
+	return xyarray__entry(counts->cpu, cpu, thread);
 }
 
 void update_stats(struct stats *stats, u64 val);
@@ -86,10 +86,10 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
 void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
 				   double avg, int cpu, enum aggr_mode aggr);
 
-struct perf_counts *perf_counts__new(int ncpus);
+struct perf_counts *perf_counts__new(int ncpus, int nthreads);
 void perf_counts__delete(struct perf_counts *counts);
 
 void perf_evsel__reset_counts(struct perf_evsel *evsel);
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads);
 void perf_evsel__free_counts(struct perf_evsel *evsel);
 #endif
-- 
1.9.3


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

* [PATCH 12/26] perf stat: Rename struct perf_counts::cpu member to values
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (10 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 11/26] perf stat: Make stats work over the thread dimension Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 13/26] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Jiri Olsa
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Renaming 'struct xyarray *cpu' pointer to more fitting/generic
values, because now we store both cpu and thread values.

Link: http://lkml.kernel.org/n/tip-fee055ta61vlnjfjzurmy6qi@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/stat.c | 12 ++++++------
 tools/perf/util/stat.h |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 7bcc19b62dd1..197a2db5f2c4 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -100,15 +100,15 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)
 	struct perf_counts *counts = zalloc(sizeof(*counts));
 
 	if (counts) {
-		struct xyarray *cpu;
+		struct xyarray *values;
 
-		cpu = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
-		if (!cpu) {
+		values = xyarray__new(ncpus, nthreads, sizeof(struct perf_counts_values));
+		if (!values) {
 			free(counts);
 			return NULL;
 		}
 
-		counts->cpu = cpu;
+		counts->values = values;
 	}
 
 	return counts;
@@ -117,14 +117,14 @@ struct perf_counts *perf_counts__new(int ncpus, int nthreads)
 void perf_counts__delete(struct perf_counts *counts)
 {
 	if (counts) {
-		xyarray__delete(counts->cpu);
+		xyarray__delete(counts->values);
 		free(counts);
 	}
 }
 
 static void perf_counts__reset(struct perf_counts *counts)
 {
-	xyarray__reset(counts->cpu);
+	xyarray__reset(counts->values);
 }
 
 void perf_evsel__reset_counts(struct perf_evsel *evsel)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index e0b8dc50fbb6..295d1e29d3d6 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -46,13 +46,13 @@ struct perf_counts_values {
 struct perf_counts {
 	s8			  scaled;
 	struct perf_counts_values aggr;
-	struct xyarray		  *cpu;
+	struct xyarray		  *values;
 };
 
 static inline struct perf_counts_values*
 perf_counts(struct perf_counts *counts, int cpu, int thread)
 {
-	return xyarray__entry(counts->cpu, cpu, thread);
+	return xyarray__entry(counts->values, cpu, thread);
 }
 
 void update_stats(struct stats *stats, u64 val);
-- 
1.9.3


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

* [PATCH 13/26] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (11 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 12/26] perf stat: Rename struct perf_counts::cpu member to values Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 14/26] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts " Jiri Olsa
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving perf_evsel__(alloc|free|reset)_stat_priv into stat object,
so it could be used outside stat command in following patches.

Link: http://lkml.kernel.org/n/tip-ti0tocuk8fuw0zb7puyuw4e7@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 25 -------------------------
 tools/perf/util/stat.c    | 25 +++++++++++++++++++++++++
 tools/perf/util/stat.h    |  4 ++++
 3 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 983bcbbe8e0a..59f66976a666 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -141,31 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
 	}
 }
 
-static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
-{
-	int i;
-	struct perf_stat *ps = evsel->priv;
-
-	for (i = 0; i < 3; i++)
-		init_stats(&ps->res_stats[i]);
-
-	perf_stat_evsel_id_init(evsel);
-}
-
-static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
-{
-	evsel->priv = zalloc(sizeof(struct perf_stat));
-	if (evsel->priv == NULL)
-		return -ENOMEM;
-	perf_evsel__reset_stat_priv(evsel);
-	return 0;
-}
-
-static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
-{
-	zfree(&evsel->priv);
-}
-
 static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
 					     int ncpus, int nthreads)
 {
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 197a2db5f2c4..b8c329f41f13 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -143,3 +143,28 @@ void perf_evsel__free_counts(struct perf_evsel *evsel)
 	perf_counts__delete(evsel->counts);
 	evsel->counts = NULL;
 }
+
+void perf_evsel__reset_stat_priv(struct perf_evsel *evsel)
+{
+	int i;
+	struct perf_stat *ps = evsel->priv;
+
+	for (i = 0; i < 3; i++)
+		init_stats(&ps->res_stats[i]);
+
+	perf_stat_evsel_id_init(evsel);
+}
+
+int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel)
+{
+	evsel->priv = zalloc(sizeof(struct perf_stat));
+	if (evsel->priv == NULL)
+		return -ENOMEM;
+	perf_evsel__reset_stat_priv(evsel);
+	return 0;
+}
+
+void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
+{
+	zfree(&evsel->priv);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 295d1e29d3d6..c441cb312565 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -92,4 +92,8 @@ void perf_counts__delete(struct perf_counts *counts);
 void perf_evsel__reset_counts(struct perf_evsel *evsel);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus, int nthreads);
 void perf_evsel__free_counts(struct perf_evsel *evsel);
+
+void perf_evsel__reset_stat_priv(struct perf_evsel *evsel);
+int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel);
+void perf_evsel__free_stat_priv(struct perf_evsel *evsel);
 #endif
-- 
1.9.3


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

* [PATCH 14/26] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (12 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 13/26] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 15/26] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object Jiri Olsa
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving perf_evsel__(alloc|free)_prev_raw_counts into stat object,
so it could be used in following patches.

Link: http://lkml.kernel.org/n/tip-am4oi22oasuy97bc4mt8i33e@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 18 ------------------
 tools/perf/util/stat.c    | 18 ++++++++++++++++++
 tools/perf/util/stat.h    |  4 ++++
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 59f66976a666..003f81f4e9ff 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -141,24 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
 	}
 }
 
-static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
-					     int ncpus, int nthreads)
-{
-	struct perf_counts *counts;
-
-	counts = perf_counts__new(ncpus, nthreads);
-	if (counts)
-		evsel->prev_raw_counts = counts;
-
-	return counts ? 0 : -ENOMEM;
-}
-
-static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
-{
-	perf_counts__delete(evsel->prev_raw_counts);
-	evsel->prev_raw_counts = NULL;
-}
-
 static void perf_evlist__free_stats(struct perf_evlist *evlist)
 {
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index b8c329f41f13..6221c3898397 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -168,3 +168,21 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 {
 	zfree(&evsel->priv);
 }
+
+int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+				      int ncpus, int nthreads)
+{
+	struct perf_counts *counts;
+
+	counts = perf_counts__new(ncpus, nthreads);
+	if (counts)
+		evsel->prev_raw_counts = counts;
+
+	return counts ? 0 : -ENOMEM;
+}
+
+void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
+{
+	perf_counts__delete(evsel->prev_raw_counts);
+	evsel->prev_raw_counts = NULL;
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index c441cb312565..454b26875aef 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -96,4 +96,8 @@ void perf_evsel__free_counts(struct perf_evsel *evsel);
 void perf_evsel__reset_stat_priv(struct perf_evsel *evsel);
 int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel);
 void perf_evsel__free_stat_priv(struct perf_evsel *evsel);
+
+int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
+				      int ncpus, int nthreads);
+void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel);
 #endif
-- 
1.9.3


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

* [PATCH 15/26] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (13 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 14/26] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts " Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 16/26] perf stat: Introduce perf_evsel__alloc_stats function Jiri Olsa
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving perf_evlist__(alloc|free)_stats into evsel object,
so it could be used in following patches.

Link: http://lkml.kernel.org/n/tip-8dwmf838kipxabe0vay8h0zn@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 32 --------------------------------
 tools/perf/util/evlist.h  |  1 -
 tools/perf/util/stat.c    | 34 ++++++++++++++++++++++++++++++++++
 tools/perf/util/stat.h    |  5 +++++
 4 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 003f81f4e9ff..4b1d1b835a68 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -141,38 +141,6 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
 	}
 }
 
-static void perf_evlist__free_stats(struct perf_evlist *evlist)
-{
-	struct perf_evsel *evsel;
-
-	evlist__for_each(evlist, evsel) {
-		perf_evsel__free_stat_priv(evsel);
-		perf_evsel__free_counts(evsel);
-		perf_evsel__free_prev_raw_counts(evsel);
-	}
-}
-
-static int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
-{
-	struct perf_evsel *evsel;
-	int nthreads = thread_map__nr(evsel_list->threads);
-
-	evlist__for_each(evlist, evsel) {
-		int ncpus = perf_evsel__nr_cpus(evsel);
-
-		if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
-		    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
-		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
-			goto out_free;
-	}
-
-	return 0;
-
-out_free:
-	perf_evlist__free_stats(evlist);
-	return -1;
-}
-
 static void perf_stat__reset_stats(struct perf_evlist *evlist)
 {
 	struct perf_evsel *evsel;
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a8489b9d2812..037633c1da9d 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -289,5 +289,4 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
 
 void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
 				     struct perf_evsel *tracking_evsel);
-
 #endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 6221c3898397..f4fb291ad428 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -1,6 +1,8 @@
 #include <math.h>
 #include "stat.h"
+#include "evlist.h"
 #include "evsel.h"
+#include "thread_map.h"
 
 void update_stats(struct stats *stats, u64 val)
 {
@@ -186,3 +188,35 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 	perf_counts__delete(evsel->prev_raw_counts);
 	evsel->prev_raw_counts = NULL;
 }
+
+int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
+{
+	struct perf_evsel *evsel;
+	int nthreads = thread_map__nr(evlist->threads);
+
+	evlist__for_each(evlist, evsel) {
+		int ncpus = perf_evsel__nr_cpus(evsel);
+
+		if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
+		    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
+		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
+			goto out_free;
+	}
+
+	return 0;
+
+out_free:
+	perf_evlist__free_stats(evlist);
+	return -1;
+}
+
+void perf_evlist__free_stats(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+
+	evlist__for_each(evlist, evsel) {
+		perf_evsel__free_stat_priv(evsel);
+		perf_evsel__free_counts(evsel);
+		perf_evsel__free_prev_raw_counts(evsel);
+	}
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 454b26875aef..fa13be8dbd5c 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -70,6 +70,8 @@ static inline void init_stats(struct stats *stats)
 }
 
 struct perf_evsel;
+struct perf_evlist;
+
 bool __perf_evsel_stat__is(struct perf_evsel *evsel,
 			   enum perf_stat_evsel_id id);
 
@@ -100,4 +102,7 @@ void perf_evsel__free_stat_priv(struct perf_evsel *evsel);
 int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
 				      int ncpus, int nthreads);
 void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel);
+
+int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
+void perf_evlist__free_stats(struct perf_evlist *evlist);
 #endif
-- 
1.9.3


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

* [PATCH 16/26] perf stat: Introduce perf_evsel__alloc_stats function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (14 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 15/26] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 17/26] perf stat: Introduce perf_evsel__read function Jiri Olsa
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Move all stat allocation logic related to stat
object under single function. This way we can
use it separately for stat object out of evlist
object.

Link: http://lkml.kernel.org/n/tip-hclg66nszn5mx8t9uwrxxw6b@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/stat.c | 20 ++++++++++++++------
 tools/perf/util/stat.h |  2 ++
 2 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index f4fb291ad428..9f5dd7897002 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -189,17 +189,25 @@ void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 	evsel->prev_raw_counts = NULL;
 }
 
+int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw)
+{
+	int ncpus = perf_evsel__nr_cpus(evsel);
+	int nthreads = thread_map__nr(evsel->threads);
+
+	if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
+	    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
+	    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
+		return -ENOMEM;
+
+	return 0;
+}
+
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
 {
 	struct perf_evsel *evsel;
-	int nthreads = thread_map__nr(evlist->threads);
 
 	evlist__for_each(evlist, evsel) {
-		int ncpus = perf_evsel__nr_cpus(evsel);
-
-		if (perf_evsel__alloc_stat_priv(evsel) < 0 ||
-		    perf_evsel__alloc_counts(evsel, ncpus, nthreads) < 0 ||
-		    (alloc_raw && perf_evsel__alloc_prev_raw_counts(evsel, ncpus, nthreads) < 0))
+		if (perf_evsel__alloc_stats(evsel, alloc_raw))
 			goto out_free;
 	}
 
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index fa13be8dbd5c..870256735a77 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -103,6 +103,8 @@ int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel,
 				      int ncpus, int nthreads);
 void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel);
 
+int perf_evsel__alloc_stats(struct perf_evsel *evsel, bool alloc_raw);
+
 int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw);
 void perf_evlist__free_stats(struct perf_evlist *evlist);
 #endif
-- 
1.9.3


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

* [PATCH 17/26] perf stat: Introduce perf_evsel__read function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (15 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 16/26] perf stat: Introduce perf_evsel__alloc_stats function Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 18/26] perf stat: Introduce read_counters function Jiri Olsa
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Adding simple read function that reads/store data
into given struct perf_counts_values *count object.

Link: http://lkml.kernel.org/n/tip-9r2zmzq0vkw8l300usq824sg@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evsel.c | 14 ++++++++++++++
 tools/perf/util/evsel.h |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index cd6ce7066f85..2e0a4e064f44 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -955,6 +955,20 @@ int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
 	return cb(evsel, cpu, thread, &count);
 }
 
+int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
+		     struct perf_counts_values *count)
+{
+	memset(count, 0, sizeof(*count));
+
+	if (FD(evsel, cpu, thread) < 0)
+		return -EINVAL;
+
+	if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) < 0)
+		return -errno;
+
+	return 0;
+}
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
 			      int cpu, int thread, bool scale)
 {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 020f7e13634a..a79944a21e8f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -236,6 +236,9 @@ typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,
 int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
 			perf_evsel__read_cb_t cb);
 
+int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
+		     struct perf_counts_values *count);
+
 int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
 			      int cpu, int thread, bool scale);
 
-- 
1.9.3


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

* [PATCH 18/26] perf stat: Introduce read_counters function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (16 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 17/26] perf stat: Introduce perf_evsel__read function Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 19/26] perf stat: Separate counters reading and processing Jiri Olsa
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving read counters logic into single read_counters function,
which will be called for both interval and overall processing
legs.

The reason is to split reading and processing (following patches)
counters code, so we could read counters from other sources
(like perf.data) and process them in the same way as 'perf stat'
command does.

Link: http://lkml.kernel.org/n/tip-yi40dw75mmzib0m37u11m767@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 47 ++++++++++++++++++++++-------------------------
 1 file changed, 22 insertions(+), 25 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 4b1d1b835a68..72d43484507e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -329,27 +329,35 @@ static int read_counter(struct perf_evsel *counter)
 	return 0;
 }
 
-static void print_interval(void)
+static void read_counters(bool close)
 {
-	static int num_print_interval;
 	struct perf_evsel *counter;
 	struct perf_stat *ps;
-	struct timespec ts, rs;
-	char prefix[64];
 
-	if (aggr_mode == AGGR_GLOBAL) {
-		evlist__for_each(evsel_list, counter) {
-			ps = counter->priv;
-			memset(ps->res_stats, 0, sizeof(ps->res_stats));
+	evlist__for_each(evsel_list, counter) {
+		ps = counter->priv;
+		memset(ps->res_stats, 0, sizeof(ps->res_stats));
+
+		if (aggr_mode == AGGR_GLOBAL)
 			read_counter_aggr(counter);
-		}
-	} else	{
-		evlist__for_each(evsel_list, counter) {
-			ps = counter->priv;
-			memset(ps->res_stats, 0, sizeof(ps->res_stats));
+		else
 			read_counter(counter);
+
+		if (close) {
+			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
+					     thread_map__nr(evsel_list->threads));
 		}
 	}
+}
+
+static void print_interval(void)
+{
+	static int num_print_interval;
+	struct perf_evsel *counter;
+	struct timespec ts, rs;
+	char prefix[64];
+
+	read_counters(false);
 
 	clock_gettime(CLOCK_MONOTONIC, &ts);
 	diff_timespec(&rs, &ts, &ref_time);
@@ -531,18 +539,7 @@ static int __run_perf_stat(int argc, const char **argv)
 
 	update_stats(&walltime_nsecs_stats, t1 - t0);
 
-	if (aggr_mode == AGGR_GLOBAL) {
-		evlist__for_each(evsel_list, counter) {
-			read_counter_aggr(counter);
-			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
-					     thread_map__nr(evsel_list->threads));
-		}
-	} else {
-		evlist__for_each(evsel_list, counter) {
-			read_counter(counter);
-			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
-		}
-	}
+	read_counters(true);
 
 	return WEXITSTATUS(status);
 }
-- 
1.9.3


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

* [PATCH 19/26] perf stat: Separate counters reading and processing
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (17 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 18/26] perf stat: Introduce read_counters function Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:48 ` [PATCH 20/26] perf stat: Move zero_per_pkg into counter process code Jiri Olsa
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Separating counters reading and processing so we could use
the processing part in following patches.

Using simple reading via perf_evsel__read function
to read counters now, because part of the processing
was in the read_cb callback.

Link: http://lkml.kernel.org/n/tip-u2z2wndrt664tkk3v3sh9bxz@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 56 +++++++++++++++++++++++++++++++++--------------
 1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 72d43484507e..3b923e179d90 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -223,8 +223,9 @@ static int check_per_pkg(struct perf_evsel *counter, int cpu, bool *skip)
 	return 0;
 }
 
-static int read_cb(struct perf_evsel *evsel, int cpu, int thread,
-		   struct perf_counts_values *count)
+static int
+process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
+		       struct perf_counts_values *count)
 {
 	struct perf_counts_values *aggr = &evsel->counts->aggr;
 	static struct perf_counts_values zero;
@@ -245,7 +246,6 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,
 		if (!evsel->snapshot)
 			perf_evsel__compute_deltas(evsel, cpu, thread, count);
 		perf_counts_values__scale(count, scale, NULL);
-		*perf_counts(evsel->counts, cpu, thread) = *count;
 		if (aggr_mode == AGGR_NONE)
 			perf_stat__update_shadow_stats(evsel, count->values, cpu);
 		break;
@@ -262,23 +262,41 @@ static int read_cb(struct perf_evsel *evsel, int cpu, int thread,
 	return 0;
 }
 
-static int read_counter(struct perf_evsel *counter);
+static int process_counter_maps(struct perf_evsel *counter)
+{
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = perf_evsel__nr_cpus(counter);
+	int cpu, thread;
 
-/*
- * Read out the results of a single counter:
- * aggregate counts across CPUs in system-wide mode
- */
-static int read_counter_aggr(struct perf_evsel *counter)
+	if (counter->system_wide)
+		nthreads = 1;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			if (process_counter_values(counter, cpu, thread,
+						   perf_counts(counter->counts, cpu, thread)))
+				return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int process_counter(struct perf_evsel *counter)
 {
 	struct perf_counts_values *aggr = &counter->counts->aggr;
 	struct perf_stat *ps = counter->priv;
 	u64 *count = counter->counts->aggr.values;
-	int i;
+	int i, ret;
 
 	aggr->val = aggr->ena = aggr->run = 0;
 
-	if (read_counter(counter))
-		return -1;
+	ret = process_counter_maps(counter);
+	if (ret)
+		return ret;
+
+	if (aggr_mode != AGGR_GLOBAL)
+		return 0;
 
 	if (!counter->snapshot)
 		perf_evsel__compute_deltas(counter, -1, -1, aggr);
@@ -321,7 +339,10 @@ static int read_counter(struct perf_evsel *counter)
 
 	for (thread = 0; thread < nthreads; thread++) {
 		for (cpu = 0; cpu < ncpus; cpu++) {
-			if (perf_evsel__read_cb(counter, cpu, thread, read_cb))
+			struct perf_counts_values *count;
+
+			count = perf_counts(counter->counts, cpu, thread);
+			if (perf_evsel__read(counter, cpu, thread, count))
 				return -1;
 		}
 	}
@@ -338,10 +359,11 @@ static void read_counters(bool close)
 		ps = counter->priv;
 		memset(ps->res_stats, 0, sizeof(ps->res_stats));
 
-		if (aggr_mode == AGGR_GLOBAL)
-			read_counter_aggr(counter);
-		else
-			read_counter(counter);
+		if (read_counter(counter))
+			pr_warning("failed to read counter %s\n", counter->name);
+
+		if (process_counter(counter))
+			pr_warning("failed to process counter %s\n", counter->name);
 
 		if (close) {
 			perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
-- 
1.9.3


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

* [PATCH 20/26] perf stat: Move zero_per_pkg into counter process code
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (18 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 19/26] perf stat: Separate counters reading and processing Jiri Olsa
@ 2015-06-18 21:48 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 21/26] perf stat: Move perf_stat initialization " Jiri Olsa
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:48 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving zero_per_pkg into counter process code,
to make the reading path free of processing logic.

Link: http://lkml.kernel.org/n/tip-wi2ces8lzpzip39yes2f9vea@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3b923e179d90..632bdb454c8a 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -291,6 +291,9 @@ static int process_counter(struct perf_evsel *counter)
 
 	aggr->val = aggr->ena = aggr->run = 0;
 
+	if (counter->per_pkg)
+		zero_per_pkg(counter);
+
 	ret = process_counter_maps(counter);
 	if (ret)
 		return ret;
@@ -334,9 +337,6 @@ static int read_counter(struct perf_evsel *counter)
 	if (counter->system_wide)
 		nthreads = 1;
 
-	if (counter->per_pkg)
-		zero_per_pkg(counter);
-
 	for (thread = 0; thread < nthreads; thread++) {
 		for (cpu = 0; cpu < ncpus; cpu++) {
 			struct perf_counts_values *count;
-- 
1.9.3


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

* [PATCH 21/26] perf stat: Move perf_stat initialization counter process code
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (19 preceding siblings ...)
  2015-06-18 21:48 ` [PATCH 20/26] perf stat: Move zero_per_pkg into counter process code Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 22/26] perf stat: Remove perf_evsel__read_cb function Jiri Olsa
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Moving perf_stat initialization counter process code,
to make the reading path free of processing logic.

Link: http://lkml.kernel.org/n/tip-ne0sgdk0ip9f81tfiqauprc7@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 632bdb454c8a..3ad4a40bde05 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -290,6 +290,7 @@ static int process_counter(struct perf_evsel *counter)
 	int i, ret;
 
 	aggr->val = aggr->ena = aggr->run = 0;
+	memset(ps->res_stats, 0, sizeof(ps->res_stats));
 
 	if (counter->per_pkg)
 		zero_per_pkg(counter);
@@ -353,12 +354,8 @@ static int read_counter(struct perf_evsel *counter)
 static void read_counters(bool close)
 {
 	struct perf_evsel *counter;
-	struct perf_stat *ps;
 
 	evlist__for_each(evsel_list, counter) {
-		ps = counter->priv;
-		memset(ps->res_stats, 0, sizeof(ps->res_stats));
-
 		if (read_counter(counter))
 			pr_warning("failed to read counter %s\n", counter->name);
 
-- 
1.9.3


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

* [PATCH 22/26] perf stat: Remove perf_evsel__read_cb function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (20 preceding siblings ...)
  2015-06-18 21:49 ` [PATCH 21/26] perf stat: Move perf_stat initialization " Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 23/26] perf stat: Rename print_interval to process_interval Jiri Olsa
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

It's no longer used, the stat command uses perf_evsel__read now.

Link: http://lkml.kernel.org/n/tip-5yh5pg1mw9wefhup1vvtssh9@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/evsel.c | 16 ----------------
 tools/perf/util/evsel.h |  7 -------
 2 files changed, 23 deletions(-)

diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 2e0a4e064f44..2936b3080722 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -939,22 +939,6 @@ void perf_counts_values__scale(struct perf_counts_values *count,
 		*pscaled = scaled;
 }
 
-int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
-			perf_evsel__read_cb_t cb)
-{
-	struct perf_counts_values count;
-
-	memset(&count, 0, sizeof(count));
-
-	if (FD(evsel, cpu, thread) < 0)
-		return -EINVAL;
-
-	if (readn(FD(evsel, cpu, thread), &count, sizeof(count)) < 0)
-		return -errno;
-
-	return cb(evsel, cpu, thread, &count);
-}
-
 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 		     struct perf_counts_values *count)
 {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a79944a21e8f..4a7ed5656cf0 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -229,13 +229,6 @@ static inline bool perf_evsel__match2(struct perf_evsel *e1,
 	 (a)->attr.type == (b)->attr.type &&	\
 	 (a)->attr.config == (b)->attr.config)
 
-typedef int (perf_evsel__read_cb_t)(struct perf_evsel *evsel,
-				    int cpu, int thread,
-				    struct perf_counts_values *count);
-
-int perf_evsel__read_cb(struct perf_evsel *evsel, int cpu, int thread,
-			perf_evsel__read_cb_t cb);
-
 int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 		     struct perf_counts_values *count);
 
-- 
1.9.3


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

* [PATCH 23/26] perf stat: Rename print_interval to process_interval
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (21 preceding siblings ...)
  2015-06-18 21:49 ` [PATCH 22/26] perf stat: Remove perf_evsel__read_cb function Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 24/26] perf stat: Using init_stats instead of memset Jiri Olsa
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

It suits better, because the function also reads counter's data.

Also the 'print_interval' name will be used in following
generalization of counters display.

Link: http://lkml.kernel.org/n/tip-8dwmf838kipxabe0vay8h0zn@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 3ad4a40bde05..c21d54846a78 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -369,7 +369,7 @@ static void read_counters(bool close)
 	}
 }
 
-static void print_interval(void)
+static void process_interval(void)
 {
 	static int num_print_interval;
 	struct perf_evsel *counter;
@@ -532,7 +532,7 @@ static int __run_perf_stat(int argc, const char **argv)
 		if (interval) {
 			while (!waitpid(child_pid, &status, WNOHANG)) {
 				nanosleep(&ts, NULL);
-				print_interval();
+				process_interval();
 			}
 		}
 		wait(&status);
@@ -550,7 +550,7 @@ static int __run_perf_stat(int argc, const char **argv)
 		while (!done) {
 			nanosleep(&ts, NULL);
 			if (interval)
-				print_interval();
+				process_interval();
 		}
 	}
 
-- 
1.9.3


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

* [PATCH 24/26] perf stat: Using init_stats instead of memset
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (22 preceding siblings ...)
  2015-06-18 21:49 ` [PATCH 23/26] perf stat: Rename print_interval to process_interval Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 25/26] perf stat: Introduce print_counters function Jiri Olsa
  2015-06-18 21:49 ` [PATCH 26/26] perf stat: Introduce --per-thread option Jiri Olsa
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

The init_stats function is meant to init 'struct stats'.

Link: http://lkml.kernel.org/n/tip-secivjava21t7921lkpy0pfj@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index c21d54846a78..8b74377c7676 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -290,7 +290,7 @@ static int process_counter(struct perf_evsel *counter)
 	int i, ret;
 
 	aggr->val = aggr->ena = aggr->run = 0;
-	memset(ps->res_stats, 0, sizeof(ps->res_stats));
+	init_stats(ps->res_stats);
 
 	if (counter->per_pkg)
 		zero_per_pkg(counter);
-- 
1.9.3


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

* [PATCH 25/26] perf stat: Introduce print_counters function
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (23 preceding siblings ...)
  2015-06-18 21:49 ` [PATCH 24/26] perf stat: Using init_stats instead of memset Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  2015-06-18 21:49 ` [PATCH 26/26] perf stat: Introduce --per-thread option Jiri Olsa
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Centralize counters print code into single
print_counters function.

Link: http://lkml.kernel.org/n/tip-1vae9jeuab2db5wxq820sb9v@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/builtin-stat.c | 127 +++++++++++++++++++++++-----------------------
 1 file changed, 64 insertions(+), 63 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 8b74377c7676..cefc905343f7 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -67,10 +67,7 @@
 #define CNTR_NOT_SUPPORTED	"<not supported>"
 #define CNTR_NOT_COUNTED	"<not counted>"
 
-static void print_stat(int argc, const char **argv);
-static void print_counter_aggr(struct perf_evsel *counter, char *prefix);
-static void print_counter(struct perf_evsel *counter, char *prefix);
-static void print_aggr(char *prefix);
+static void print_counters(struct timespec *ts, int argc, const char **argv);
 
 /* Default events used for perf stat -T */
 static const char *transaction_attrs = {
@@ -371,53 +368,14 @@ static void read_counters(bool close)
 
 static void process_interval(void)
 {
-	static int num_print_interval;
-	struct perf_evsel *counter;
 	struct timespec ts, rs;
-	char prefix[64];
 
 	read_counters(false);
 
 	clock_gettime(CLOCK_MONOTONIC, &ts);
 	diff_timespec(&rs, &ts, &ref_time);
-	sprintf(prefix, "%6lu.%09lu%s", rs.tv_sec, rs.tv_nsec, csv_sep);
-
-	if (num_print_interval == 0 && !csv_output) {
-		switch (aggr_mode) {
-		case AGGR_SOCKET:
-			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_CORE:
-			fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_NONE:
-			fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
-			break;
-		case AGGR_GLOBAL:
-		default:
-			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
-		}
-	}
-
-	if (++num_print_interval == 25)
-		num_print_interval = 0;
 
-	switch (aggr_mode) {
-	case AGGR_CORE:
-	case AGGR_SOCKET:
-		print_aggr(prefix);
-		break;
-	case AGGR_NONE:
-		evlist__for_each(evsel_list, counter)
-			print_counter(counter, prefix);
-		break;
-	case AGGR_GLOBAL:
-	default:
-		evlist__for_each(evsel_list, counter)
-			print_counter_aggr(counter, prefix);
-	}
-
-	fflush(output);
+	print_counters(&rs, 0, NULL);
 }
 
 static void handle_initial_delay(void)
@@ -907,9 +865,35 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 	}
 }
 
-static void print_stat(int argc, const char **argv)
+static void print_interval(char *prefix, struct timespec *ts)
+{
+	static int num_print_interval;
+
+	sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
+
+	if (num_print_interval == 0 && !csv_output) {
+		switch (aggr_mode) {
+		case AGGR_SOCKET:
+			fprintf(output, "#           time socket cpus             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_CORE:
+			fprintf(output, "#           time core         cpus             counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_NONE:
+			fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
+			break;
+		case AGGR_GLOBAL:
+		default:
+			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
+		}
+	}
+
+	if (++num_print_interval == 25)
+		num_print_interval = 0;
+}
+
+static void print_header(int argc, const char **argv)
 {
-	struct perf_evsel *counter;
 	int i;
 
 	fflush(stdout);
@@ -935,36 +919,53 @@ static void print_stat(int argc, const char **argv)
 			fprintf(output, " (%d runs)", run_count);
 		fprintf(output, ":\n\n");
 	}
+}
+
+static void print_footer(void)
+{
+	if (!null_run)
+		fprintf(output, "\n");
+	fprintf(output, " %17.9f seconds time elapsed",
+			avg_stats(&walltime_nsecs_stats)/1e9);
+	if (run_count > 1) {
+		fprintf(output, "                                        ");
+		print_noise_pct(stddev_stats(&walltime_nsecs_stats),
+				avg_stats(&walltime_nsecs_stats));
+	}
+	fprintf(output, "\n\n");
+}
+
+static void print_counters(struct timespec *ts, int argc, const char **argv)
+{
+	struct perf_evsel *counter;
+	char buf[64], *prefix = NULL;
+
+	if (interval)
+		print_interval(prefix = buf, ts);
+	else
+		print_header(argc, argv);
 
 	switch (aggr_mode) {
 	case AGGR_CORE:
 	case AGGR_SOCKET:
-		print_aggr(NULL);
+		print_aggr(prefix);
 		break;
 	case AGGR_GLOBAL:
 		evlist__for_each(evsel_list, counter)
-			print_counter_aggr(counter, NULL);
+			print_counter_aggr(counter, prefix);
 		break;
 	case AGGR_NONE:
 		evlist__for_each(evsel_list, counter)
-			print_counter(counter, NULL);
+			print_counter(counter, prefix);
 		break;
 	default:
 		break;
 	}
 
-	if (!csv_output) {
-		if (!null_run)
-			fprintf(output, "\n");
-		fprintf(output, " %17.9f seconds time elapsed",
-				avg_stats(&walltime_nsecs_stats)/1e9);
-		if (run_count > 1) {
-			fprintf(output, "                                        ");
-			print_noise_pct(stddev_stats(&walltime_nsecs_stats),
-					avg_stats(&walltime_nsecs_stats));
-		}
-		fprintf(output, "\n\n");
-	}
+	if (!interval && !csv_output)
+		print_footer();
+
+	fflush(output);
 }
 
 static volatile int signr = -1;
@@ -1413,13 +1414,13 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 
 		status = run_perf_stat(argc, argv);
 		if (forever && status != -1) {
-			print_stat(argc, argv);
+			print_counters(NULL, argc, argv);
 			perf_stat__reset_stats(evsel_list);
 		}
 	}
 
 	if (!forever && status != -1 && !interval)
-		print_stat(argc, argv);
+		print_counters(NULL, argc, argv);
 
 	perf_evlist__free_stats(evsel_list);
 out:
-- 
1.9.3


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

* [PATCH 26/26] perf stat: Introduce --per-thread option
  2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
                   ` (24 preceding siblings ...)
  2015-06-18 21:49 ` [PATCH 25/26] perf stat: Introduce print_counters function Jiri Olsa
@ 2015-06-18 21:49 ` Jiri Olsa
  25 siblings, 0 replies; 32+ messages in thread
From: Jiri Olsa @ 2015-06-18 21:49 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Currently all the -p option PID arguments tasks values
get aggregated and printed as single values.

Adding --per-tasks option to print values per task.

  $ perf stat  -e cycles,instructions --per-thread -p 30190,30242
  ^C
   Performance counter stats for process id '30190,30242':

               cat-30190                     0      cycles
               yes-30242         3,842,525,421      cycles
               cat-30190                     0      instructions
               yes-30242        10,370,817,010      instructions

         1.143155657 seconds time elapsed

Also works under interval mode:

  $ perf stat  -e cycles,instructions --per-thread -p 30190,30242 -I 1000
  #           time             comm-pid                  counts unit events
       1.000073435              cat-30190                89,058      cycles
       1.000073435              yes-30242         3,360,786,902      cycles                     (100.00%)
       1.000073435              cat-30190                14,066      instructions
       1.000073435              yes-30242         9,069,937,462      instructions
       2.000204830              cat-30190                     0      cycles
       2.000204830              yes-30242         3,351,667,626      cycles
       2.000204830              cat-30190                     0      instructions
       2.000204830              yes-30242         9,045,796,885      instructions
  ^C     2.771286639              cat-30190                     0      cycles
       2.771286639              yes-30242         2,593,884,166      cycles
       2.771286639              cat-30190                     0      instructions
       2.771286639              yes-30242         7,001,171,191      instructions

It works only with -t and -p options, otherwise following
error is printed:

  $ perf stat  -e cycles --per-thread  -I 1000 ls
  The --per-thread option is only available when monitoring via -p -t options.
      -p, --pid <pid>       stat events on existing process id
      -t, --tid <tid>       stat events on existing thread id

Link: http://lkml.kernel.org/n/tip-0v0ixd9k7o9z1u8hqngm1coe@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/Documentation/perf-stat.txt |  4 ++
 tools/perf/builtin-stat.c              | 68 +++++++++++++++++++++++++++++++++-
 tools/perf/util/stat.h                 |  1 +
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 04e150d83e7d..47469abdcc1c 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -144,6 +144,10 @@ is a useful mode to detect imbalance between physical cores.  To enable this mod
 use --per-core in addition to -a. (system-wide).  The output includes the
 core number and the number of online logical processors on that physical processor.
 
+--per-thread::
+Aggregate counts per monitored threads, when monitoring threads (-t option)
+or processes (-p option).
+
 -D msecs::
 --delay msecs::
 After starting the program, wait msecs before measuring. This is useful to
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index cefc905343f7..2df36605dded 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -237,6 +237,7 @@ process_counter_values(struct perf_evsel *evsel, int cpu, int thread,
 		count = &zero;
 
 	switch (aggr_mode) {
+	case AGGR_THREAD:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 	case AGGR_NONE:
@@ -608,6 +609,14 @@ static void aggr_printout(struct perf_evsel *evsel, int id, int nr)
 			csv_output ? 0 : -4,
 			perf_evsel__cpus(evsel)->map[id], csv_sep);
 		break;
+	case AGGR_THREAD:
+		fprintf(output, "%*s-%*d%s",
+			csv_output ? 0 : 16,
+			thread_map__comm(evsel->threads, id),
+			csv_output ? 0 : -8,
+			thread_map__pid(evsel->threads, id),
+			csv_sep);
+		break;
 	case AGGR_GLOBAL:
 	default:
 		break;
@@ -756,6 +765,40 @@ static void print_aggr(char *prefix)
 	}
 }
 
+static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
+{
+	int nthreads = thread_map__nr(counter->threads);
+	int ncpus = cpu_map__nr(counter->cpus);
+	int cpu, thread;
+	double uval;
+
+	for (thread = 0; thread < nthreads; thread++) {
+		u64 ena = 0, run = 0, val = 0;
+
+		for (cpu = 0; cpu < ncpus; cpu++) {
+			val += perf_counts(counter->counts, cpu, thread)->val;
+			ena += perf_counts(counter->counts, cpu, thread)->ena;
+			run += perf_counts(counter->counts, cpu, thread)->run;
+		}
+
+		if (prefix)
+			fprintf(output, "%s", prefix);
+
+		uval = val * counter->scale;
+
+		if (nsec_counter(counter))
+			nsec_printout(thread, 0, counter, uval);
+		else
+			abs_printout(thread, 0, counter, uval);
+
+		if (!csv_output)
+			print_noise(counter, 1.0);
+
+		print_running(run, ena);
+		fputc('\n', output);
+	}
+}
+
 /*
  * Print out the results of a single counter:
  * aggregated counts in system-wide mode
@@ -882,6 +925,9 @@ static void print_interval(char *prefix, struct timespec *ts)
 		case AGGR_NONE:
 			fprintf(output, "#           time CPU                counts %*s events\n", unit_width, "unit");
 			break;
+		case AGGR_THREAD:
+			fprintf(output, "#           time             comm-pid                  counts %*s events\n", unit_width, "unit");
+			break;
 		case AGGR_GLOBAL:
 		default:
 			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
@@ -950,6 +996,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	case AGGR_SOCKET:
 		print_aggr(prefix);
 		break;
+	case AGGR_THREAD:
+		evlist__for_each(evsel_list, counter)
+			print_aggr_thread(counter, prefix);
+		break;
 	case AGGR_GLOBAL:
 		evlist__for_each(evsel_list, counter)
 			print_counter_aggr(counter, prefix);
@@ -1037,6 +1087,7 @@ static int perf_stat_init_aggr_mode(void)
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
+	case AGGR_THREAD:
 	default:
 		break;
 	}
@@ -1261,6 +1312,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "aggregate counts per processor socket", AGGR_SOCKET),
 	OPT_SET_UINT(0, "per-core", &aggr_mode,
 		     "aggregate counts per physical processor core", AGGR_CORE),
+	OPT_SET_UINT(0, "per-thread", &aggr_mode,
+		     "aggregate counts per thread", AGGR_THREAD),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
 	OPT_END()
@@ -1352,8 +1405,19 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		run_count = 1;
 	}
 
-	/* no_aggr, cgroup are for system-wide only */
-	if ((aggr_mode != AGGR_GLOBAL || nr_cgroups) &&
+	if ((aggr_mode == AGGR_THREAD) && !target__has_task(&target)) {
+		fprintf(stderr, "The --per-thread option is only available "
+			"when monitoring via -p -t options.\n");
+		parse_options_usage(NULL, options, "p", 1);
+		parse_options_usage(NULL, options, "t", 1);
+		goto out;
+	}
+
+	/*
+	 * no_aggr, cgroup are for system-wide only
+	 * --per-thread is aggregated per thread, we dont mix it with cpu mode
+	 */
+	if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_THREAD) || nr_cgroups) &&
 	    !target__has_cpu(&target)) {
 		fprintf(stderr, "both cgroup and no-aggregation "
 			"modes only available in system-wide mode\n");
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 870256735a77..42339ad997ee 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -30,6 +30,7 @@ enum aggr_mode {
 	AGGR_GLOBAL,
 	AGGR_SOCKET,
 	AGGR_CORE,
+	AGGR_THREAD,
 };
 
 struct perf_counts_values {
-- 
1.9.3


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

* Re: [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-18 21:48 ` [PATCH 01/26] perf tools: Change thread_map::map into struct Jiri Olsa
@ 2015-06-19 21:07   ` Arnaldo Carvalho de Melo
  2015-06-19 22:05     ` Jiri Olsa
  0 siblings, 1 reply; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-19 21:07 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Thu, Jun 18, 2015 at 11:48:40PM +0200, Jiri Olsa escreveu:
> We need to store command names with the pid. Changing
> map to be struct holding pid. Process name is coming
> in shortly.
> 
> Link: http://lkml.kernel.org/n/tip-z4zuyvcxa6glzqm8qubk6vg7@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/builtin-trace.c                  |  4 ++--
>  tools/perf/tests/openat-syscall-tp-fields.c |  2 +-
>  tools/perf/util/auxtrace.c                  |  4 ++--
>  tools/perf/util/event.c                     |  6 +++---
>  tools/perf/util/evlist.c                    |  4 ++--
>  tools/perf/util/evsel.c                     |  2 +-
>  tools/perf/util/thread_map.c                | 22 +++++++++++-----------
>  tools/perf/util/thread_map.h                |  8 +++++++-
>  8 files changed, 29 insertions(+), 23 deletions(-)
> 
> diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> index 4bf805b2fbf6..b75a68c385ea 100644
> --- a/tools/perf/builtin-trace.c
> +++ b/tools/perf/builtin-trace.c
> @@ -2324,7 +2324,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
>  	 */
>  	if (trace->filter_pids.nr > 0)
>  		err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
> -	else if (evlist->threads->map[0] == -1)
> +	else if (thread_map__pid(evlist->threads, 0) == -1)
>  		err = perf_evlist__set_filter_pid(evlist, getpid());
>  
>  	if (err < 0) {
> @@ -2342,7 +2342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
>  	if (forks)
>  		perf_evlist__start_workload(evlist);
>  
> -	trace->multiple_threads = evlist->threads->map[0] == -1 ||
> +	trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
>  				  evlist->threads->nr > 1 ||
>  				  perf_evlist__first(evlist)->attr.inherit;
>  again:
> diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
> index 6245221479d7..ebc6e7938c9a 100644
> --- a/tools/perf/tests/openat-syscall-tp-fields.c
> +++ b/tools/perf/tests/openat-syscall-tp-fields.c
> @@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)
>  
>  	perf_evsel__config(evsel, &opts);
>  
> -	evlist->threads->map[0] = getpid();
> +	thread_map__pid(evlist->threads, 0) = getpid();

So this 'function(parms) = something' idiom looks ugly/unfamiliar, can't
we keep using:

	evlist->thread->map[0].pid = getpid();

I.e. just add the .pid to the existing usage.

- Arnaldo

>  
>  	err = perf_evlist__open(evlist);
>  	if (err < 0) {
> diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
> index df66966cfde7..3dab006b4a03 100644
> --- a/tools/perf/util/auxtrace.c
> +++ b/tools/perf/util/auxtrace.c
> @@ -119,12 +119,12 @@ void auxtrace_mmap_params__set_idx(struct auxtrace_mmap_params *mp,
>  	if (per_cpu) {
>  		mp->cpu = evlist->cpus->map[idx];
>  		if (evlist->threads)
> -			mp->tid = evlist->threads->map[0];
> +			mp->tid = thread_map__pid(evlist->threads, 0);
>  		else
>  			mp->tid = -1;
>  	} else {
>  		mp->cpu = -1;
> -		mp->tid = evlist->threads->map[idx];
> +		mp->tid = thread_map__pid(evlist->threads, idx);
>  	}
>  }
>  
> diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
> index 793b1503d437..51a1bedf90fb 100644
> --- a/tools/perf/util/event.c
> +++ b/tools/perf/util/event.c
> @@ -479,7 +479,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
>  	for (thread = 0; thread < threads->nr; ++thread) {
>  		if (__event__synthesize_thread(comm_event, mmap_event,
>  					       fork_event,
> -					       threads->map[thread], 0,
> +					       thread_map__pid(threads, thread), 0,
>  					       process, tool, machine,
>  					       mmap_data)) {
>  			err = -1;
> @@ -490,12 +490,12 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
>  		 * comm.pid is set to thread group id by
>  		 * perf_event__synthesize_comm
>  		 */
> -		if ((int) comm_event->comm.pid != threads->map[thread]) {
> +		if ((int) comm_event->comm.pid != thread_map__pid(threads, thread)) {
>  			bool need_leader = true;
>  
>  			/* is thread group leader in thread_map? */
>  			for (j = 0; j < threads->nr; ++j) {
> -				if ((int) comm_event->comm.pid == threads->map[j]) {
> +				if ((int) comm_event->comm.pid == thread_map__pid(threads, j)) {
>  					need_leader = false;
>  					break;
>  				}
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index 8366511b45f8..a62b3adcc32b 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -548,7 +548,7 @@ static void perf_evlist__set_sid_idx(struct perf_evlist *evlist,
>  	else
>  		sid->cpu = -1;
>  	if (!evsel->system_wide && evlist->threads && thread >= 0)
> -		sid->tid = evlist->threads->map[thread];
> +		sid->tid = thread_map__pid(evlist->threads, thread);
>  	else
>  		sid->tid = -1;
>  }
> @@ -1475,7 +1475,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tar
>  				__func__, __LINE__);
>  			goto out_close_pipes;
>  		}
> -		evlist->threads->map[0] = evlist->workload.pid;
> +		thread_map__pid(evlist->threads, 0) = evlist->workload.pid;
>  	}
>  
>  	close(child_ready_pipe[1]);
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 33449decf7bd..1b56047af96b 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -1167,7 +1167,7 @@ retry_sample_id:
>  			int group_fd;
>  
>  			if (!evsel->cgrp && !evsel->system_wide)
> -				pid = threads->map[thread];
> +				pid = thread_map__pid(threads, thread);
>  
>  			group_fd = get_group_fd(evsel, cpu, thread);
>  retry_open:
> diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
> index f4822bd03709..7f03f9facfdd 100644
> --- a/tools/perf/util/thread_map.c
> +++ b/tools/perf/util/thread_map.c
> @@ -22,7 +22,7 @@ static int filter(const struct dirent *dir)
>  
>  static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
>  {
> -	size_t size = sizeof(*map) + sizeof(pid_t) * nr;
> +	size_t size = sizeof(*map) + sizeof(struct thread_map_data) * nr;
>  
>  	return realloc(map, size);
>  }
> @@ -45,7 +45,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
>  	threads = thread_map__alloc(items);
>  	if (threads != NULL) {
>  		for (i = 0; i < items; i++)
> -			threads->map[i] = atoi(namelist[i]->d_name);
> +			thread_map__pid(threads, i) = atoi(namelist[i]->d_name);
>  		threads->nr = items;
>  	}
>  
> @@ -61,8 +61,8 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
>  	struct thread_map *threads = thread_map__alloc(1);
>  
>  	if (threads != NULL) {
> -		threads->map[0] = tid;
> -		threads->nr	= 1;
> +		thread_map__pid(threads, 0) = tid;
> +		threads->nr		    = 1;
>  	}
>  
>  	return threads;
> @@ -124,7 +124,7 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
>  		}
>  
>  		for (i = 0; i < items; i++)
> -			threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
> +			thread_map__pid(threads, threads->nr + i) = atoi(namelist[i]->d_name);
>  
>  		for (i = 0; i < items; i++)
>  			zfree(&namelist[i]);
> @@ -201,7 +201,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
>  		threads = nt;
>  
>  		for (i = 0; i < items; i++) {
> -			threads->map[j++] = atoi(namelist[i]->d_name);
> +			thread_map__pid(threads, j++) = atoi(namelist[i]->d_name);
>  			zfree(&namelist[i]);
>  		}
>  		threads->nr = total_tasks;
> @@ -227,8 +227,8 @@ struct thread_map *thread_map__new_dummy(void)
>  	struct thread_map *threads = thread_map__alloc(1);
>  
>  	if (threads != NULL) {
> -		threads->map[0]	= -1;
> -		threads->nr	= 1;
> +		thread_map__pid(threads, 0) = -1;
> +		threads->nr		    = 1;
>  	}
>  	return threads;
>  }
> @@ -267,8 +267,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
>  			goto out_free_threads;
>  
>  		threads = nt;
> -		threads->map[ntasks - 1] = tid;
> -		threads->nr		 = ntasks;
> +		thread_map__pid(threads, ntasks - 1) = tid;
> +		threads->nr			     = ntasks;
>  	}
>  out:
>  	return threads;
> @@ -301,7 +301,7 @@ size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
>  	size_t printed = fprintf(fp, "%d thread%s: ",
>  				 threads->nr, threads->nr > 1 ? "s" : "");
>  	for (i = 0; i < threads->nr; ++i)
> -		printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]);
> +		printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i));
>  
>  	return printed + fprintf(fp, "\n");
>  }
> diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
> index 95313f43cc0f..9377850c7b71 100644
> --- a/tools/perf/util/thread_map.h
> +++ b/tools/perf/util/thread_map.h
> @@ -4,11 +4,17 @@
>  #include <sys/types.h>
>  #include <stdio.h>
>  
> +struct thread_map_data {
> +	pid_t    pid;
> +};
> +
>  struct thread_map {
>  	int nr;
> -	pid_t map[];
> +	struct thread_map_data map[];
>  };
>  
> +#define thread_map__pid(__m, __t)  __m->map[__t].pid
> +
>  struct thread_map *thread_map__new_dummy(void);
>  struct thread_map *thread_map__new_by_pid(pid_t pid);
>  struct thread_map *thread_map__new_by_tid(pid_t tid);
> -- 
> 1.9.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-19 21:07   ` Arnaldo Carvalho de Melo
@ 2015-06-19 22:05     ` Jiri Olsa
  2015-06-22 14:40       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 32+ messages in thread
From: Jiri Olsa @ 2015-06-19 22:05 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, lkml, Adrian Hunter, Andi Kleen, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra, Stephane Eranian

On Fri, Jun 19, 2015 at 06:07:13PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Thu, Jun 18, 2015 at 11:48:40PM +0200, Jiri Olsa escreveu:
> > We need to store command names with the pid. Changing
> > map to be struct holding pid. Process name is coming
> > in shortly.
> > 
> > Link: http://lkml.kernel.org/n/tip-z4zuyvcxa6glzqm8qubk6vg7@git.kernel.org
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> >  tools/perf/builtin-trace.c                  |  4 ++--
> >  tools/perf/tests/openat-syscall-tp-fields.c |  2 +-
> >  tools/perf/util/auxtrace.c                  |  4 ++--
> >  tools/perf/util/event.c                     |  6 +++---
> >  tools/perf/util/evlist.c                    |  4 ++--
> >  tools/perf/util/evsel.c                     |  2 +-
> >  tools/perf/util/thread_map.c                | 22 +++++++++++-----------
> >  tools/perf/util/thread_map.h                |  8 +++++++-
> >  8 files changed, 29 insertions(+), 23 deletions(-)
> > 
> > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> > index 4bf805b2fbf6..b75a68c385ea 100644
> > --- a/tools/perf/builtin-trace.c
> > +++ b/tools/perf/builtin-trace.c
> > @@ -2324,7 +2324,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
> >  	 */
> >  	if (trace->filter_pids.nr > 0)
> >  		err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
> > -	else if (evlist->threads->map[0] == -1)
> > +	else if (thread_map__pid(evlist->threads, 0) == -1)
> >  		err = perf_evlist__set_filter_pid(evlist, getpid());
> >  
> >  	if (err < 0) {
> > @@ -2342,7 +2342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
> >  	if (forks)
> >  		perf_evlist__start_workload(evlist);
> >  
> > -	trace->multiple_threads = evlist->threads->map[0] == -1 ||
> > +	trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
> >  				  evlist->threads->nr > 1 ||
> >  				  perf_evlist__first(evlist)->attr.inherit;
> >  again:
> > diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
> > index 6245221479d7..ebc6e7938c9a 100644
> > --- a/tools/perf/tests/openat-syscall-tp-fields.c
> > +++ b/tools/perf/tests/openat-syscall-tp-fields.c
> > @@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)
> >  
> >  	perf_evsel__config(evsel, &opts);
> >  
> > -	evlist->threads->map[0] = getpid();
> > +	thread_map__pid(evlist->threads, 0) = getpid();
> 
> So this 'function(parms) = something' idiom looks ugly/unfamiliar, can't
> we keep using:
> 
> 	evlist->thread->map[0].pid = getpid();

hum, I like it more than above line.. what's ugly about that assignment?

I'm adding thread_map__comm to access new 'comm' member,
so I wanted to introduce easy accessors for both members

get/set functions seem like overkill..  we could use upper case to state
that it's a macro:

  THREAD_MAP__PID(evlist->threads, 0) = getpid();

anyway I can keep the original way if you insist ;-)

jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-19 22:05     ` Jiri Olsa
@ 2015-06-22 14:40       ` Arnaldo Carvalho de Melo
  2015-06-22 17:37         ` Jiri Olsa
  0 siblings, 1 reply; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-22 14:40 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, lkml, Adrian Hunter, Andi Kleen, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sat, Jun 20, 2015 at 12:05:31AM +0200, Jiri Olsa escreveu:
> On Fri, Jun 19, 2015 at 06:07:13PM -0300, Arnaldo Carvalho de Melo wrote:
> > Em Thu, Jun 18, 2015 at 11:48:40PM +0200, Jiri Olsa escreveu:
> > > We need to store command names with the pid. Changing
> > > map to be struct holding pid. Process name is coming
> > > in shortly.
> > > 
> > > Link: http://lkml.kernel.org/n/tip-z4zuyvcxa6glzqm8qubk6vg7@git.kernel.org
> > > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > > ---
> > >  tools/perf/builtin-trace.c                  |  4 ++--
> > >  tools/perf/tests/openat-syscall-tp-fields.c |  2 +-
> > >  tools/perf/util/auxtrace.c                  |  4 ++--
> > >  tools/perf/util/event.c                     |  6 +++---
> > >  tools/perf/util/evlist.c                    |  4 ++--
> > >  tools/perf/util/evsel.c                     |  2 +-
> > >  tools/perf/util/thread_map.c                | 22 +++++++++++-----------
> > >  tools/perf/util/thread_map.h                |  8 +++++++-
> > >  8 files changed, 29 insertions(+), 23 deletions(-)
> > > 
> > > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
> > > index 4bf805b2fbf6..b75a68c385ea 100644
> > > --- a/tools/perf/builtin-trace.c
> > > +++ b/tools/perf/builtin-trace.c
> > > @@ -2324,7 +2324,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
> > >  	 */
> > >  	if (trace->filter_pids.nr > 0)
> > >  		err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
> > > -	else if (evlist->threads->map[0] == -1)
> > > +	else if (thread_map__pid(evlist->threads, 0) == -1)
> > >  		err = perf_evlist__set_filter_pid(evlist, getpid());
> > >  
> > >  	if (err < 0) {
> > > @@ -2342,7 +2342,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
> > >  	if (forks)
> > >  		perf_evlist__start_workload(evlist);
> > >  
> > > -	trace->multiple_threads = evlist->threads->map[0] == -1 ||
> > > +	trace->multiple_threads = thread_map__pid(evlist->threads, 0) == -1 ||
> > >  				  evlist->threads->nr > 1 ||
> > >  				  perf_evlist__first(evlist)->attr.inherit;
> > >  again:
> > > diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
> > > index 6245221479d7..ebc6e7938c9a 100644
> > > --- a/tools/perf/tests/openat-syscall-tp-fields.c
> > > +++ b/tools/perf/tests/openat-syscall-tp-fields.c
> > > @@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)
> > >  
> > >  	perf_evsel__config(evsel, &opts);
> > >  
> > > -	evlist->threads->map[0] = getpid();
> > > +	thread_map__pid(evlist->threads, 0) = getpid();
> > 
> > So this 'function(parms) = something' idiom looks ugly/unfamiliar, can't
> > we keep using:
> > 
> > 	evlist->thread->map[0].pid = getpid();
> 
> hum, I like it more than above line.. what's ugly about that assignment?
> 
> I'm adding thread_map__comm to access new 'comm' member,
> so I wanted to introduce easy accessors for both members
> 
> get/set functions seem like overkill..  we could use upper case to state
> that it's a macro:
> 
>   THREAD_MAP__PID(evlist->threads, 0) = getpid();
> 
> anyway I can keep the original way if you insist ;-)

I really think that 

		foo(a, b, c) = bla;

is ugly :-\

		*foo(a, b, c) = bla;

Is uglier tho, bored right now to go beyond aesthetics tho :-\

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-22 14:40       ` Arnaldo Carvalho de Melo
@ 2015-06-22 17:37         ` Jiri Olsa
  2015-06-22 17:48           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 32+ messages in thread
From: Jiri Olsa @ 2015-06-22 17:37 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, lkml, Adrian Hunter, Andi Kleen, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra, Stephane Eranian

On Mon, Jun 22, 2015 at 11:40:16AM -0300, Arnaldo Carvalho de Melo wrote:

SNIP

> > > > +++ b/tools/perf/tests/openat-syscall-tp-fields.c
> > > > @@ -45,7 +45,7 @@ int test__syscall_openat_tp_fields(void)
> > > >  
> > > >  	perf_evsel__config(evsel, &opts);
> > > >  
> > > > -	evlist->threads->map[0] = getpid();
> > > > +	thread_map__pid(evlist->threads, 0) = getpid();
> > > 
> > > So this 'function(parms) = something' idiom looks ugly/unfamiliar, can't
> > > we keep using:
> > > 
> > > 	evlist->thread->map[0].pid = getpid();
> > 
> > hum, I like it more than above line.. what's ugly about that assignment?
> > 
> > I'm adding thread_map__comm to access new 'comm' member,
> > so I wanted to introduce easy accessors for both members
> > 
> > get/set functions seem like overkill..  we could use upper case to state
> > that it's a macro:
> > 
> >   THREAD_MAP__PID(evlist->threads, 0) = getpid();
> > 
> > anyway I can keep the original way if you insist ;-)
> 
> I really think that 
> 
> 		foo(a, b, c) = bla;
> 
> is ugly :-\
> 
> 		*foo(a, b, c) = bla;
> 
> Is uglier tho, bored right now to go beyond aesthetics tho :-\

discussed on irc and decided to go with:

  thread_map__pid(threads, i)			// to get pid
  thread_map__set_pid(threads, i, pid)		// to set pid

  thread_map__comm(threads, i)			// to get comm
  thread_map__set_comm(threads, i, comm)	// to set comm

jirka
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [PATCH 01/26] perf tools: Change thread_map::map into struct
  2015-06-22 17:37         ` Jiri Olsa
@ 2015-06-22 17:48           ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 32+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-22 17:48 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Jiri Olsa, lkml, Adrian Hunter, Andi Kleen, David Ahern,
	Ingo Molnar, Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Mon, Jun 22, 2015 at 07:37:45PM +0200, Jiri Olsa escreveu:
> On Mon, Jun 22, 2015 at 11:40:16AM -0300, Arnaldo Carvalho de Melo wrote:
> > > get/set functions seem like overkill..  we could use upper case to state
> > > that it's a macro:

> > >   THREAD_MAP__PID(evlist->threads, 0) = getpid();

> > > anyway I can keep the original way if you insist ;-)

> > I really think that 

> > 		foo(a, b, c) = bla;

> > is ugly :-\

> > 		*foo(a, b, c) = bla;

> > Is uglier tho, bored right now to go beyond aesthetics tho :-\

> discussed on irc and decided to go with:

>   thread_map__pid(threads, i)			// to get pid
>   thread_map__set_pid(threads, i, pid)		// to set pid

>   thread_map__comm(threads, i)			// to get comm
>   thread_map__set_comm(threads, i, comm)	// to set comm

Ack.

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

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

end of thread, other threads:[~2015-06-22 17:48 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-18 21:48 [PATCHv3 00/26] perf stat: Introduce --per-thread option Jiri Olsa
2015-06-18 21:48 ` [PATCH 01/26] perf tools: Change thread_map::map into struct Jiri Olsa
2015-06-19 21:07   ` Arnaldo Carvalho de Melo
2015-06-19 22:05     ` Jiri Olsa
2015-06-22 14:40       ` Arnaldo Carvalho de Melo
2015-06-22 17:37         ` Jiri Olsa
2015-06-22 17:48           ` Arnaldo Carvalho de Melo
2015-06-18 21:48 ` [PATCH 02/26] perf tools: Add comm string into struct thread_map Jiri Olsa
2015-06-18 21:48 ` [PATCH 03/26] perf tools: Add reference counting for cpu_map object Jiri Olsa
2015-06-18 21:48 ` [PATCH 04/26] perf tools: Add reference counting for thread_map object Jiri Olsa
2015-06-18 21:48 ` [PATCH 05/26] perf tools: Propagate cpu maps through the evlist Jiri Olsa
2015-06-18 21:48 ` [PATCH 06/26] perf tools: Propagate thread " Jiri Olsa
2015-06-18 21:48 ` [PATCH 07/26] perf tools: Make perf_evsel__(nr_)cpus generic Jiri Olsa
2015-06-18 21:48 ` [PATCH 08/26] perf tests: Add thread_map object tests Jiri Olsa
2015-06-18 21:48 ` [PATCH 09/26] perf stat: Introduce perf_counts function Jiri Olsa
2015-06-18 21:48 ` [PATCH 10/26] perf stat: Use xyarray for cpu evsel counts Jiri Olsa
2015-06-18 21:48 ` [PATCH 11/26] perf stat: Make stats work over the thread dimension Jiri Olsa
2015-06-18 21:48 ` [PATCH 12/26] perf stat: Rename struct perf_counts::cpu member to values Jiri Olsa
2015-06-18 21:48 ` [PATCH 13/26] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Jiri Olsa
2015-06-18 21:48 ` [PATCH 14/26] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts " Jiri Olsa
2015-06-18 21:48 ` [PATCH 15/26] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object Jiri Olsa
2015-06-18 21:48 ` [PATCH 16/26] perf stat: Introduce perf_evsel__alloc_stats function Jiri Olsa
2015-06-18 21:48 ` [PATCH 17/26] perf stat: Introduce perf_evsel__read function Jiri Olsa
2015-06-18 21:48 ` [PATCH 18/26] perf stat: Introduce read_counters function Jiri Olsa
2015-06-18 21:48 ` [PATCH 19/26] perf stat: Separate counters reading and processing Jiri Olsa
2015-06-18 21:48 ` [PATCH 20/26] perf stat: Move zero_per_pkg into counter process code Jiri Olsa
2015-06-18 21:49 ` [PATCH 21/26] perf stat: Move perf_stat initialization " Jiri Olsa
2015-06-18 21:49 ` [PATCH 22/26] perf stat: Remove perf_evsel__read_cb function Jiri Olsa
2015-06-18 21:49 ` [PATCH 23/26] perf stat: Rename print_interval to process_interval Jiri Olsa
2015-06-18 21:49 ` [PATCH 24/26] perf stat: Using init_stats instead of memset Jiri Olsa
2015-06-18 21:49 ` [PATCH 25/26] perf stat: Introduce print_counters function Jiri Olsa
2015-06-18 21:49 ` [PATCH 26/26] perf stat: Introduce --per-thread option 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).