All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 00/30] perf stat: Introduce --per-task option
@ 2015-06-14  8:19 Jiri Olsa
  2015-06-14  8:19 ` [PATCH 01/30] perf tools: Introduce xyarray__reset function Jiri Olsa
                   ` (29 more replies)
  0 siblings, 30 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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-task -p 25388,25442 -a
  ^C
   Performance counter stats for process id '25388,25442':

  cat-25388               100,122      cycles
  vim-25442             4,167,876      cycles
  cat-25388                20,080      instructions
  vim-25442             3,232,735      instructions

         6.057130572 seconds time elapsed


Also works under interval mode:

  $ perf stat  -e cycles,instructions --per-task -p 25388,25442 -a -I 1000
  #           time task                      counts unit events
       1.000190002 cat-25388                54,196      cycles
       1.000190002 vim-25442                     0      cycles
       1.000190002 cat-25388                11,660      instructions
       1.000190002 vim-25442                     0      instructions
       2.000742579 cat-25388                55,247      cycles
       2.000742579 vim-25442             1,752,951      cycles
       2.000742579 cat-25388                11,872      instructions
       2.000742579 vim-25442             1,238,512      instructions
       3.001057871 cat-25388                     0      cycles
       3.001057871 vim-25442                     0      cycles
       3.001057871 cat-25388                     0      instructions
       3.001057871 vim-25442                     0      instructions
  ^C     3.242519732 cat-25388                     0      cycles
       3.242519732 vim-25442                     0      cycles
       3.242519732 cat-25388                     0      instructions
       3.242519732 vim-25442                     0      instructions


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 for comments,
jirka


---
Jiri Olsa (30):
      perf tools: Introduce xyarray__reset function
      perf tools: Add thread_map__(alloc|realloc) helpers
      perf tools: Change thread_map::map into struct
      perf tools: Add comm string into struct thread_map
      perf tests: Add thread_map object tests
      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 tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
      perf stat: Introduce perf_counts__(alloc|free|reset) functions
      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-task option

 tools/perf/Documentation/perf-stat.txt      |   3 +
 tools/perf/builtin-stat.c                   | 398 ++++++++++++++--------------
 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  |   9 +-
 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                    |  25 +-
 tools/perf/util/cpumap.h                    |   6 +-
 tools/perf/util/event.c                     |   6 +-
 tools/perf/util/evlist.c                    |  38 ++-
 tools/perf/util/evlist.h                    |   1 -
 tools/perf/util/evsel.c                     |  47 ++--
 tools/perf/util/evsel.h                     |  43 ++-
 tools/perf/util/parse-events.c              |   5 +-
 tools/perf/util/python-ext-sources          |   2 +
 tools/perf/util/python.c                    |   4 +-
 tools/perf/util/record.c                    |   4 +-
 tools/perf/util/session.c                   |   2 +-
 tools/perf/util/stat.c                      | 134 ++++++++++
 tools/perf/util/stat.h                      |  46 ++++
 tools/perf/util/svghelper.c                 |   2 +-
 tools/perf/util/thread_map.c                | 131 +++++++--
 tools/perf/util/thread_map.h                |  17 +-
 tools/perf/util/xyarray.c                   |   8 +
 tools/perf/util/xyarray.h                   |   2 +
 35 files changed, 672 insertions(+), 329 deletions(-)
 create mode 100644 tools/perf/tests/thread-map.c

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

* [PATCH 01/30] perf tools: Introduce xyarray__reset function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-18  8:13   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2015-06-14  8:19 ` [PATCH 02/30] perf tools: Add thread_map__(alloc|realloc) helpers Jiri Olsa
                   ` (28 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

To zero all the xyarray contents. It will be used
in following patches.

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

diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 22afbf6c536a..c10ba41ef3f6 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
 	if (xy != NULL) {
 		xy->entry_size = entry_size;
 		xy->row_size   = row_size;
+		xy->entries    = xlen * ylen;
 	}
 
 	return xy;
 }
 
+void xyarray__reset(struct xyarray *xy)
+{
+	size_t n = xy->entries * xy->entry_size;
+
+	memset(xy->contents, 0, n);
+}
+
 void xyarray__delete(struct xyarray *xy)
 {
 	free(xy);
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index c488a07275dd..7f30af371b7e 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -6,11 +6,13 @@
 struct xyarray {
 	size_t row_size;
 	size_t entry_size;
+	size_t entries;
 	char contents[];
 };
 
 struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
 void xyarray__delete(struct xyarray *xy);
+void xyarray__reset(struct xyarray *xy);
 
 static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
 {
-- 
1.9.3


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

* [PATCH 02/30] perf tools: Add thread_map__(alloc|realloc) helpers
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
  2015-06-14  8:19 ` [PATCH 01/30] perf tools: Introduce xyarray__reset function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-18  8:14   ` [tip:perf/core] " tip-bot for Jiri Olsa
  2015-06-14  8:19 ` [PATCH 03/30] perf tools: Change thread_map::map into struct Jiri Olsa
                   ` (27 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

In order to have 'struct thread_map' allocation on single
place and can change it easily in following patch.

Using alloc|realloc for static helpers, because thread_map__new
is already used in public interface.

Link: http://lkml.kernel.org/n/tip-05va5v9fmxvd5s3fm9vt93vt@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/util/thread_map.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f93b9734735b..f4822bd03709 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)
 		return 1;
 }
 
+static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
+{
+	size_t size = sizeof(*map) + sizeof(pid_t) * nr;
+
+	return realloc(map, size);
+}
+
+#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
+
 struct thread_map *thread_map__new_by_pid(pid_t pid)
 {
 	struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 	if (items <= 0)
 		return NULL;
 
-	threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
+	threads = thread_map__alloc(items);
 	if (threads != NULL) {
 		for (i = 0; i < items; i++)
 			threads->map[i] = atoi(namelist[i]->d_name);
@@ -49,7 +58,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 
 struct thread_map *thread_map__new_by_tid(pid_t tid)
 {
-	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
 		threads->map[0] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 	int max_threads = 32, items, i;
 	char path[256];
 	struct dirent dirent, *next, **namelist = NULL;
-	struct thread_map *threads = malloc(sizeof(*threads) +
-					    max_threads * sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(max_threads);
+
 	if (threads == NULL)
 		goto out;
 
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 			goto out_free_threads;
 
 		total_tasks += items;
-		nt = realloc(threads, (sizeof(*threads) +
-				       sizeof(pid_t) * total_tasks));
+		nt = thread_map__realloc(threads, total_tasks);
 		if (nt == NULL)
 			goto out_free_namelist;
 
@@ -216,7 +224,7 @@ out_free_threads:
 
 struct thread_map *thread_map__new_dummy(void)
 {
-	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
 		threads->map[0]	= -1;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 			continue;
 
 		ntasks++;
-		nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks);
+		nt = thread_map__realloc(threads, ntasks);
 
 		if (nt == NULL)
 			goto out_free_threads;
-- 
1.9.3


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

* [PATCH 03/30] perf tools: Change thread_map::map into struct
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
  2015-06-14  8:19 ` [PATCH 01/30] perf tools: Introduce xyarray__reset function Jiri Olsa
  2015-06-14  8:19 ` [PATCH 02/30] perf tools: Add thread_map__(alloc|realloc) helpers Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 19:04   ` Arnaldo Carvalho de Melo
  2015-06-14  8:19 ` [PATCH 04/30] perf tools: Add comm string into struct thread_map Jiri Olsa
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 dc1dc2c181ef..50115253f4fa 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -539,7 +539,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;
 }
@@ -1459,7 +1459,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 d4f9994ae47f..e6e0a97f329a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1184,7 +1184,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	[flat|nested] 45+ messages in thread

* [PATCH 04/30] perf tools: Add comm string into struct thread_map
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (2 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 03/30] perf tools: Change thread_map::map into struct Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 19:17   ` Arnaldo Carvalho de Melo
  2015-06-14  8:19 ` [PATCH 05/30] perf tests: Add thread_map object tests Jiri Olsa
                   ` (25 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 4d28624a1eca..55ba8968a263 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -19,3 +19,4 @@ util/rblist.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	[flat|nested] 45+ messages in thread

* [PATCH 05/30] perf tests: Add thread_map object tests
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (3 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 04/30] perf tools: Add comm string into struct thread_map Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 06/30] perf tools: Add reference counting for cpu_map object Jiri Olsa
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 06/30] perf tools: Add reference counting for cpu_map object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (4 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 05/30] perf tests: Add thread_map object tests Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 07/30] perf tools: Add reference counting for thread_map object Jiri Olsa
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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           | 25 +++++++++++++++++++++++--
 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, 44 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..19540e56704e 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,31 @@ 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)
+{
+	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 +283,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 50115253f4fa..bd747215caa4 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;
@@ -1337,7 +1337,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 e6e0a97f329a..fe5c0ae8b116 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -902,6 +902,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 f31e024ddf7d..cd0b768b6c7a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1838,7 +1838,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	[flat|nested] 45+ messages in thread

* [PATCH 07/30] perf tools: Add reference counting for thread_map object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (5 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 06/30] perf tools: Add reference counting for cpu_map object Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 19:25   ` Arnaldo Carvalho de Melo
  2015-06-14  8:19 ` [PATCH 08/30] perf tools: Propagate cpu maps through the evlist Jiri Olsa
                   ` (22 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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               | 30 ++++++++++++++++++++++++++----
 tools/perf/util/thread_map.h               |  7 +++++--
 11 files changed, 41 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 e34dfdf96b5a..8801983a38f0 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -110,6 +110,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 bd747215caa4..f7d80ca58136 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);
@@ -1104,7 +1104,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..584fa978e50a 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,29 @@ 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)
+{
+	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	[flat|nested] 45+ messages in thread

* [PATCH 08/30] perf tools: Propagate cpu maps through the evlist
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (6 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 07/30] perf tools: Add reference counting for thread_map object Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 19:34   ` Arnaldo Carvalho de Melo
  2015-06-14  8:19 ` [PATCH 09/30] perf tools: Propagate thread " Jiri Olsa
                   ` (21 subsequent siblings)
  29 siblings, 1 reply; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f7d80ca58136..c0d3058c1868 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
 	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
 }
 
+static int 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,
@@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
 	if (evlist->cpus == NULL)
 		goto out_delete_threads;
 
-	return 0;
+	return propagate_maps(evlist, target);
 
 out_delete_threads:
 	thread_map__put(evlist->threads);
-- 
1.9.3


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

* [PATCH 09/30] perf tools: Propagate thread maps through the evlist
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (7 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 08/30] perf tools: Propagate cpu maps through the evlist Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 10/30] perf tools: Make perf_evsel__(nr_)cpus generic Jiri Olsa
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 c0d3058c1868..b4c22f8f2423 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1100,7 +1100,9 @@ static int propagate_maps(struct perf_evlist *evlist, struct target *target)
 		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 fe5c0ae8b116..6ef818475aa3 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -903,6 +903,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 21ec08247d47..d18572223b08 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	[flat|nested] 45+ messages in thread

* [PATCH 10/30] perf tools: Make perf_evsel__(nr_)cpus generic
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (8 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 09/30] perf tools: Propagate thread " Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object Jiri Olsa
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 b24ecee95fec..a2f752ae15ca 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 d18572223b08..54afdc80a651 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	[flat|nested] 45+ messages in thread

* [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (9 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 10/30] perf tools: Make perf_evsel__(nr_)cpus generic Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 20:13   ` Arnaldo Carvalho de Melo
  2015-06-18  8:14   ` [tip:perf/core] perf tools: Move perf_evsel__(alloc|free|reset) _counts " tip-bot for Jiri Olsa
  2015-06-14  8:19 ` [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions Jiri Olsa
                   ` (18 subsequent siblings)
  29 siblings, 2 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 stat specific. Updating python build objects with stat.c.

Link: http://lkml.kernel.org/n/tip-36bz60viixc7bd5vh8oywazc@git.kernel.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/perf/tests/openat-syscall-all-cpus.c |  1 +
 tools/perf/util/evsel.c                    | 19 +------------------
 tools/perf/util/evsel.h                    |  3 ---
 tools/perf/util/python-ext-sources         |  1 +
 tools/perf/util/stat.c                     | 18 ++++++++++++++++++
 tools/perf/util/stat.h                     |  3 +++
 6 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 8801983a38f0..b8d552b13950 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -3,6 +3,7 @@
 #include "thread_map.h"
 #include "cpumap.h"
 #include "debug.h"
+#include "stat.h"
 
 int test__openat_syscall_event_on_all_cpus(void)
 {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 6ef818475aa3..1b2f480a3e82 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -26,6 +26,7 @@
 #include "perf_regs.h"
 #include "debug.h"
 #include "trace-event.h"
+#include "stat.h"
 
 static struct {
 	bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
 	return 0;
 }
 
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
-{
-	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
-				 (ncpus * sizeof(struct perf_counts_values))));
-}
-
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
-{
-	evsel->counts = zalloc((sizeof(*evsel->counts) +
-				(ncpus * sizeof(struct perf_counts_values))));
-	return evsel->counts != NULL ? 0 : -ENOMEM;
-}
-
 static void perf_evsel__free_fd(struct perf_evsel *evsel)
 {
 	xyarray__delete(evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 		}
 }
 
-void perf_evsel__free_counts(struct perf_evsel *evsel)
-{
-	zfree(&evsel->counts);
-}
-
 void perf_evsel__exit(struct perf_evsel *evsel)
 {
 	assert(list_empty(&evsel->node));
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 54afdc80a651..4dbf32d94dfb 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -182,9 +182,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
 int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
-void perf_evsel__free_counts(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 55ba8968a263..572d39ab7bdf 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -20,3 +20,4 @@ util/strlist.c
 util/trace-event.c
 ../../lib/rbtree.c
 util/string.c
+util/stat.c
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 60b92822f655..ac589b6b8bce 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 		}
 	}
 }
+
+void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
+{
+	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
+				 (ncpus * sizeof(struct perf_counts_values))));
+}
+
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
+{
+	evsel->counts = zalloc((sizeof(*evsel->counts) +
+				(ncpus * sizeof(struct perf_counts_values))));
+	return evsel->counts != NULL ? 0 : -ENOMEM;
+}
+
+void perf_evsel__free_counts(struct perf_evsel *evsel)
+{
+	zfree(&evsel->counts);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 615c779eb42a..6a782601c1c7 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -62,4 +62,7 @@ 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);
 
+void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
+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	[flat|nested] 45+ messages in thread

* [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (10 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-15 20:16   ` Arnaldo Carvalho de Melo
  2015-06-18  8:14   ` [tip:perf/core] perf stat: Introduce perf_counts__( new|delete|reset) functions tip-bot for Jiri Olsa
  2015-06-14  8:19 ` [PATCH 13/30] perf stat: Introduce perf_counts function Jiri Olsa
                   ` (17 subsequent siblings)
  29 siblings, 2 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 'struct perf_counts' allocation|free|reset code into
separate functions.

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

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index a2f752ae15ca..3e1636cae76b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 
 static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
 {
-	void *addr;
-	size_t sz;
+	struct perf_counts *counts;
 
-	sz = sizeof(*evsel->counts) +
-	     (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values));
+	counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
+	if (counts)
+		evsel->prev_raw_counts = counts;
 
-	addr = zalloc(sz);
-	if (!addr)
-		return -ENOMEM;
-
-	evsel->prev_raw_counts =  addr;
-
-	return 0;
+	return counts ? 0 : -ENOMEM;
 }
 
 static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 {
-	zfree(&evsel->prev_raw_counts);
+	perf_counts__delete(evsel->prev_raw_counts);
+	evsel->prev_raw_counts = NULL;
 }
 
 static void perf_evlist__free_stats(struct perf_evlist *evlist)
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index ac589b6b8bce..4014b709f956 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -95,20 +95,38 @@ 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);
+
+	return zalloc(size);
+}
+
+void perf_counts__delete(struct perf_counts *counts)
+{
+	free(counts);
+}
+
+static void perf_counts__reset(struct perf_counts *counts, int ncpus)
+{
+	memset(counts, 0, (sizeof(*counts) +
+	       (ncpus * sizeof(struct perf_counts_values))));
+}
+
 void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
 {
-	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
-				 (ncpus * sizeof(struct perf_counts_values))));
+	perf_counts__reset(evsel->counts, ncpus);
 }
 
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
 {
-	evsel->counts = zalloc((sizeof(*evsel->counts) +
-				(ncpus * sizeof(struct perf_counts_values))));
+	evsel->counts = perf_counts__new(ncpus);
 	return evsel->counts != NULL ? 0 : -ENOMEM;
 }
 
 void perf_evsel__free_counts(struct perf_evsel *evsel)
 {
-	zfree(&evsel->counts);
+	perf_counts__delete(evsel->counts);
+	evsel->counts = NULL;
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 6a782601c1c7..093dc3cb28dd 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -62,6 +62,9 @@ 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);
+void perf_counts__delete(struct perf_counts *counts);
+
 void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
 void perf_evsel__free_counts(struct perf_evsel *evsel);
-- 
1.9.3


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

* [PATCH 13/30] perf stat: Introduce perf_counts function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (11 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 14/30] perf stat: Use xyarray for cpu evsel counts Jiri Olsa
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 14/30] perf stat: Use xyarray for cpu evsel counts
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (12 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 13/30] perf stat: Introduce perf_counts function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 15/30] perf stat: Make stats work over the thread dimension Jiri Olsa
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 15/30] perf stat: Make stats work over the thread dimension
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (13 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 14/30] perf stat: Use xyarray for cpu evsel counts Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 16/30] perf stat: Rename struct perf_counts::cpu member to values Jiri Olsa
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 16/30] perf stat: Rename struct perf_counts::cpu member to values
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (14 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 15/30] perf stat: Make stats work over the thread dimension Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 17/30] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Jiri Olsa
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 17/30] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (15 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 16/30] perf stat: Rename struct perf_counts::cpu member to values Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 18/30] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts " Jiri Olsa
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 18/30] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts into stat object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (16 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 17/30] perf stat: Move perf_evsel__(alloc|free|reset)_stat_priv into stat object Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 19/30] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object Jiri Olsa
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 19/30] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (17 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 18/30] perf stat: Move perf_evsel__(alloc|free)_prev_raw_counts " Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 20/30] perf stat: Introduce perf_evsel__alloc_stats function Jiri Olsa
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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 955bf31b7dd3..308797588fdc 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -287,5 +287,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	[flat|nested] 45+ messages in thread

* [PATCH 20/30] perf stat: Introduce perf_evsel__alloc_stats function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (18 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 19/30] perf stat: Move perf_evlist__(alloc|free)_stats into evlist object Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 21/30] perf stat: Introduce perf_evsel__read function Jiri Olsa
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 21/30] perf stat: Introduce perf_evsel__read function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (19 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 20/30] perf stat: Introduce perf_evsel__alloc_stats function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 22/30] perf stat: Introduce read_counters function Jiri Olsa
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 22/30] perf stat: Introduce read_counters function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (20 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 21/30] perf stat: Introduce perf_evsel__read function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 23/30] perf stat: Separate counters reading and processing Jiri Olsa
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 23/30] perf stat: Separate counters reading and processing
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (21 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 22/30] perf stat: Introduce read_counters function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 24/30] perf stat: Move zero_per_pkg into counter process code Jiri Olsa
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 24/30] perf stat: Move zero_per_pkg into counter process code
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (22 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 23/30] perf stat: Separate counters reading and processing Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 25/30] perf stat: Move perf_stat initialization " Jiri Olsa
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 25/30] perf stat: Move perf_stat initialization counter process code
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (23 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 24/30] perf stat: Move zero_per_pkg into counter process code Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 26/30] perf stat: Remove perf_evsel__read_cb function Jiri Olsa
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 26/30] perf stat: Remove perf_evsel__read_cb function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (24 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 25/30] perf stat: Move perf_stat initialization " Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 27/30] perf stat: Rename print_interval to process_interval Jiri Olsa
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 27/30] perf stat: Rename print_interval to process_interval
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (25 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 26/30] perf stat: Remove perf_evsel__read_cb function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 28/30] perf stat: Using init_stats instead of memset Jiri Olsa
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 28/30] perf stat: Using init_stats instead of memset
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (26 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 27/30] perf stat: Rename print_interval to process_interval Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 29/30] perf stat: Introduce print_counters function Jiri Olsa
  2015-06-14  8:19 ` [PATCH 30/30] perf stat: Introduce --per-task option Jiri Olsa
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 29/30] perf stat: Introduce print_counters function
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (27 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 28/30] perf stat: Using init_stats instead of memset Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  2015-06-14  8:19 ` [PATCH 30/30] perf stat: Introduce --per-task option Jiri Olsa
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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	[flat|nested] 45+ messages in thread

* [PATCH 30/30] perf stat: Introduce --per-task option
  2015-06-14  8:19 [PATCHv2 00/30] perf stat: Introduce --per-task option Jiri Olsa
                   ` (28 preceding siblings ...)
  2015-06-14  8:19 ` [PATCH 29/30] perf stat: Introduce print_counters function Jiri Olsa
@ 2015-06-14  8:19 ` Jiri Olsa
  29 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-14  8:19 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-task -p 25388,25442 -a
  ^C
   Performance counter stats for process id '25388,25442':

  cat-25388               100,122      cycles
  vim-25442             4,167,876      cycles
  cat-25388                20,080      instructions
  vim-25442             3,232,735      instructions

         6.057130572 seconds time elapsed

Also works under interval mode:

  $ perf stat  -e cycles,instructions --per-task -p 25388,25442 -a -I 1000
  #           time task                      counts unit events
       1.000190002 cat-25388                54,196      cycles
       1.000190002 vim-25442                     0      cycles
       1.000190002 cat-25388                11,660      instructions
       1.000190002 vim-25442                     0      instructions
       2.000742579 cat-25388                55,247      cycles
       2.000742579 vim-25442             1,752,951      cycles
       2.000742579 cat-25388                11,872      instructions
       2.000742579 vim-25442             1,238,512      instructions
       3.001057871 cat-25388                     0      cycles
       3.001057871 vim-25442                     0      cycles
       3.001057871 cat-25388                     0      instructions
       3.001057871 vim-25442                     0      instructions
  ^C     3.242519732 cat-25388                     0      cycles
       3.242519732 vim-25442                     0      cycles
       3.242519732 cat-25388                     0      instructions
       3.242519732 vim-25442                     0      instructions

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

  $ perf stat  -e cycles --per-task  -I 1000 ls
  The --per-task option is only available when monitoring tasks 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 |  3 ++
 tools/perf/builtin-stat.c              | 67 +++++++++++++++++++++++++++++++++-
 tools/perf/util/stat.h                 |  1 +
 3 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 04e150d83e7d..b83cc5bbfa9a 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -144,6 +144,9 @@ 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-task::
+Aggregate counts per monitored 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..c202c5d629bf 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_TASK:
 	case AGGR_CORE:
 	case AGGR_SOCKET:
 	case AGGR_NONE:
@@ -608,6 +609,13 @@ 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_TASK:
+		fprintf(output, "%s-%*d%s",
+			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 +764,40 @@ static void print_aggr(char *prefix)
 	}
 }
 
+static void print_aggr_task(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 +924,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_TASK:
+			fprintf(output, "#           time task                      counts %*s events\n", unit_width, "unit");
+			break;
 		case AGGR_GLOBAL:
 		default:
 			fprintf(output, "#           time             counts %*s events\n", unit_width, "unit");
@@ -950,6 +995,10 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
 	case AGGR_SOCKET:
 		print_aggr(prefix);
 		break;
+	case AGGR_TASK:
+		evlist__for_each(evsel_list, counter)
+			print_aggr_task(counter, prefix);
+		break;
 	case AGGR_GLOBAL:
 		evlist__for_each(evsel_list, counter)
 			print_counter_aggr(counter, prefix);
@@ -1037,6 +1086,7 @@ static int perf_stat_init_aggr_mode(void)
 		break;
 	case AGGR_NONE:
 	case AGGR_GLOBAL:
+	case AGGR_TASK:
 	default:
 		break;
 	}
@@ -1261,6 +1311,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-task", &aggr_mode,
+		     "aggregate counts per task", AGGR_TASK),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
 	OPT_END()
@@ -1352,8 +1404,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_TASK) && !target__has_task(&target)) {
+		fprintf(stderr, "The --per-task option is only available "
+			"when monitoring tasks 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-task is aggregated per task, we dont mix it with cpu mode
+	 */
+	if (((aggr_mode != AGGR_GLOBAL && aggr_mode != AGGR_TASK) || 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..deb9a0faccf7 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_TASK,
 };
 
 struct perf_counts_values {
-- 
1.9.3


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

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

Em Sun, Jun 14, 2015 at 10:19:18AM +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.

<SNIP>
 
> +++ 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;
> +};
> +

What 'data' is this? That is way vague term.

 Will try looking at the other patches to try to suggest some other name
for this :-\

>  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	[flat|nested] 45+ messages in thread

* Re: [PATCH 04/30] perf tools: Add comm string into struct thread_map
  2015-06-14  8:19 ` [PATCH 04/30] perf tools: Add comm string into struct thread_map Jiri Olsa
@ 2015-06-15 19:17   ` Arnaldo Carvalho de Melo
  2015-06-15 21:55     ` Jiri Olsa
  0 siblings, 1 reply; 45+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-15 19:17 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sun, Jun 14, 2015 at 10:19:19AM +0200, Jiri Olsa escreveu:
> 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.

Humm, so you want to extend the thread_map, that was just for pids, to
have some more info about the thread, if that is the case, why not
synthesize the whole thread, and have a pointer to 'struct thread', that
is the representation for a thread in perf instead of creating a new,
partial thing like 'thread_map_data'?

You wouldn't have to use the existing synthesizing code if that seems to
overkill, i.e. instead of having 'pid_t' as the array element in a
thread_map, you would have 'struct thread', i.e. the whole shebang, but
would just set what you need now, i.e. thread->pid and thread->comm, but
later could do the rest instead of recreating it in that thread_map_data
:-)

I.e. besides --per-task, don't you want --per-pid, --per-thread, or
other stuff that will use other thread characteristics?

That or rename that 'thread_map_data' to something like mini_thread,
...}.

Got carried away, but that was the reaction to that vague name
'thread_map_data' 8-)


Anyway, applied the first two, looking at the rest...


- Arnaldo
 
> 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 4d28624a1eca..55ba8968a263 100644
> --- a/tools/perf/util/python-ext-sources
> +++ b/tools/perf/util/python-ext-sources
> @@ -19,3 +19,4 @@ util/rblist.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	[flat|nested] 45+ messages in thread

* Re: [PATCH 07/30] perf tools: Add reference counting for thread_map object
  2015-06-14  8:19 ` [PATCH 07/30] perf tools: Add reference counting for thread_map object Jiri Olsa
@ 2015-06-15 19:25   ` Arnaldo Carvalho de Melo
  2015-06-15 21:28     ` Jiri Olsa
  0 siblings, 1 reply; 45+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-15 19:25 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sun, Jun 14, 2015 at 10:19:22AM +0200, Jiri Olsa escreveu:
> 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.
 
<SNIP>

> +struct thread_map *thread_map__get(struct thread_map *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);
>  }

See comment on the other struct being refcounted, get/put should
both accept NULL maps, to avoid having to check it in the users,
just like with free().

- Arnaldo

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

* Re: [PATCH 08/30] perf tools: Propagate cpu maps through the evlist
  2015-06-14  8:19 ` [PATCH 08/30] perf tools: Propagate cpu maps through the evlist Jiri Olsa
@ 2015-06-15 19:34   ` Arnaldo Carvalho de Melo
  2015-06-15 21:29     ` Jiri Olsa
  0 siblings, 1 reply; 45+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-15 19:34 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sun, Jun 14, 2015 at 10:19:23AM +0200, Jiri Olsa escreveu:
> 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 | 24 +++++++++++++++++++++++-
>  1 file changed, 23 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> index f7d80ca58136..c0d3058c1868 100644
> --- a/tools/perf/util/evlist.c
> +++ b/tools/perf/util/evlist.c
> @@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
>  	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
>  }
>  
> +static int propagate_maps(struct perf_evlist *evlist, struct target *target)

Please rename this to perf_evlist__set_maps()

> +{
> +	struct perf_evsel *evsel;

> +	evlist__for_each(evlist, evsel) {
> +		/*
> +		 * We already have cpus for evsel (via PMU sysfs) so

                   If we already...

> +		 * keep it, if there's no target cpu list defined.
                          ^ The comma here confused me
> +		 */
> +		if (evsel->cpus && target->cpu_list)
> +			cpu_map__put(evsel->cpus);

If you drop the reference, and then will test it... use a
cpu_map__zput(&evsel->cpus), so that after the put you don't access
something you don't hold a reference for anymore...

But the logic is still confusing! Can you try to rewrite it in a more
clear way? 

> +		if (!evsel->cpus || target->cpu_list)
> +			evsel->cpus = cpu_map__get(evlist->cpus);

Something like:

		if (evsel->cpus) {
			something
		} else {
			something else
		}
> +
> +		if (!evsel->cpus)
> +			return -ENOMEM;

Where was that we tried to allocate memory in this operation?

> +	}
> +
> +	return 0;
> +}
> +
>  int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
>  {
>  	evlist->threads = thread_map__new_str(target->pid, target->tid,
> @@ -1101,7 +1123,7 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
>  	if (evlist->cpus == NULL)
>  		goto out_delete_threads;
>  
> -	return 0;
> +	return propagate_maps(evlist, target);
>  
>  out_delete_threads:
>  	thread_map__put(evlist->threads);
> -- 
> 1.9.3

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

* Re: [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object
  2015-06-14  8:19 ` [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object Jiri Olsa
@ 2015-06-15 20:13   ` Arnaldo Carvalho de Melo
  2015-06-18  8:14   ` [tip:perf/core] perf tools: Move perf_evsel__(alloc|free|reset) _counts " tip-bot for Jiri Olsa
  1 sibling, 0 replies; 45+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-15 20:13 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sun, Jun 14, 2015 at 10:19:26AM +0200, Jiri Olsa escreveu:
> It's stat specific. Updating python build objects with stat.c.
> 
> Link: http://lkml.kernel.org/n/tip-36bz60viixc7bd5vh8oywazc@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>

thanks, applied.

- Arnaldo

> ---
>  tools/perf/tests/openat-syscall-all-cpus.c |  1 +
>  tools/perf/util/evsel.c                    | 19 +------------------
>  tools/perf/util/evsel.h                    |  3 ---
>  tools/perf/util/python-ext-sources         |  1 +
>  tools/perf/util/stat.c                     | 18 ++++++++++++++++++
>  tools/perf/util/stat.h                     |  3 +++
>  6 files changed, 24 insertions(+), 21 deletions(-)
> 
> diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
> index 8801983a38f0..b8d552b13950 100644
> --- a/tools/perf/tests/openat-syscall-all-cpus.c
> +++ b/tools/perf/tests/openat-syscall-all-cpus.c
> @@ -3,6 +3,7 @@
>  #include "thread_map.h"
>  #include "cpumap.h"
>  #include "debug.h"
> +#include "stat.h"
>  
>  int test__openat_syscall_event_on_all_cpus(void)
>  {
> diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
> index 6ef818475aa3..1b2f480a3e82 100644
> --- a/tools/perf/util/evsel.c
> +++ b/tools/perf/util/evsel.c
> @@ -26,6 +26,7 @@
>  #include "perf_regs.h"
>  #include "debug.h"
>  #include "trace-event.h"
> +#include "stat.h"
>  
>  static struct {
>  	bool sample_id_all;
> @@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
>  	return 0;
>  }
>  
> -void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
> -{
> -	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
> -				 (ncpus * sizeof(struct perf_counts_values))));
> -}
> -
> -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
> -{
> -	evsel->counts = zalloc((sizeof(*evsel->counts) +
> -				(ncpus * sizeof(struct perf_counts_values))));
> -	return evsel->counts != NULL ? 0 : -ENOMEM;
> -}
> -
>  static void perf_evsel__free_fd(struct perf_evsel *evsel)
>  {
>  	xyarray__delete(evsel->fd);
> @@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
>  		}
>  }
>  
> -void perf_evsel__free_counts(struct perf_evsel *evsel)
> -{
> -	zfree(&evsel->counts);
> -}
> -
>  void perf_evsel__exit(struct perf_evsel *evsel)
>  {
>  	assert(list_empty(&evsel->node));
> diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
> index 54afdc80a651..4dbf32d94dfb 100644
> --- a/tools/perf/util/evsel.h
> +++ b/tools/perf/util/evsel.h
> @@ -182,9 +182,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
>  int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
>  
>  int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
> -int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
> -void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
> -void perf_evsel__free_counts(struct perf_evsel *evsel);
>  void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
>  
>  void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
> diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
> index 55ba8968a263..572d39ab7bdf 100644
> --- a/tools/perf/util/python-ext-sources
> +++ b/tools/perf/util/python-ext-sources
> @@ -20,3 +20,4 @@ util/strlist.c
>  util/trace-event.c
>  ../../lib/rbtree.c
>  util/string.c
> +util/stat.c
> diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
> index 60b92822f655..ac589b6b8bce 100644
> --- a/tools/perf/util/stat.c
> +++ b/tools/perf/util/stat.c
> @@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
>  		}
>  	}
>  }
> +
> +void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
> +{
> +	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
> +				 (ncpus * sizeof(struct perf_counts_values))));
> +}
> +
> +int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
> +{
> +	evsel->counts = zalloc((sizeof(*evsel->counts) +
> +				(ncpus * sizeof(struct perf_counts_values))));
> +	return evsel->counts != NULL ? 0 : -ENOMEM;
> +}
> +
> +void perf_evsel__free_counts(struct perf_evsel *evsel)
> +{
> +	zfree(&evsel->counts);
> +}
> diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
> index 615c779eb42a..6a782601c1c7 100644
> --- a/tools/perf/util/stat.h
> +++ b/tools/perf/util/stat.h
> @@ -62,4 +62,7 @@ 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);
>  
> +void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
> +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	[flat|nested] 45+ messages in thread

* Re: [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions
  2015-06-14  8:19 ` [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions Jiri Olsa
@ 2015-06-15 20:16   ` Arnaldo Carvalho de Melo
  2015-06-18  8:14   ` [tip:perf/core] perf stat: Introduce perf_counts__( new|delete|reset) functions tip-bot for Jiri Olsa
  1 sibling, 0 replies; 45+ messages in thread
From: Arnaldo Carvalho de Melo @ 2015-06-15 20:16 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: lkml, Adrian Hunter, Andi Kleen, David Ahern, Ingo Molnar,
	Namhyung Kim, Peter Zijlstra, Stephane Eranian

Em Sun, Jun 14, 2015 at 10:19:27AM +0200, Jiri Olsa escreveu:
> Move 'struct perf_counts' allocation|free|reset code into
> separate functions.

Applied, after fixing up the Subject to match new/delete.

- Arnaldo
 
> Link: http://lkml.kernel.org/n/tip-qu64zmm5zbpbkuybusnkg4gl@git.kernel.org
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  tools/perf/builtin-stat.c | 19 +++++++------------
>  tools/perf/util/stat.c    | 28 +++++++++++++++++++++++-----
>  tools/perf/util/stat.h    |  3 +++
>  3 files changed, 33 insertions(+), 17 deletions(-)
> 
> diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
> index a2f752ae15ca..3e1636cae76b 100644
> --- a/tools/perf/builtin-stat.c
> +++ b/tools/perf/builtin-stat.c
> @@ -168,24 +168,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
>  
>  static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
>  {
> -	void *addr;
> -	size_t sz;
> +	struct perf_counts *counts;
>  
> -	sz = sizeof(*evsel->counts) +
> -	     (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values));
> +	counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
> +	if (counts)
> +		evsel->prev_raw_counts = counts;
>  
> -	addr = zalloc(sz);
> -	if (!addr)
> -		return -ENOMEM;
> -
> -	evsel->prev_raw_counts =  addr;
> -
> -	return 0;
> +	return counts ? 0 : -ENOMEM;
>  }
>  
>  static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
>  {
> -	zfree(&evsel->prev_raw_counts);
> +	perf_counts__delete(evsel->prev_raw_counts);
> +	evsel->prev_raw_counts = NULL;
>  }
>  
>  static void perf_evlist__free_stats(struct perf_evlist *evlist)
> diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
> index ac589b6b8bce..4014b709f956 100644
> --- a/tools/perf/util/stat.c
> +++ b/tools/perf/util/stat.c
> @@ -95,20 +95,38 @@ 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);
> +
> +	return zalloc(size);
> +}
> +
> +void perf_counts__delete(struct perf_counts *counts)
> +{
> +	free(counts);
> +}
> +
> +static void perf_counts__reset(struct perf_counts *counts, int ncpus)
> +{
> +	memset(counts, 0, (sizeof(*counts) +
> +	       (ncpus * sizeof(struct perf_counts_values))));
> +}
> +
>  void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
>  {
> -	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
> -				 (ncpus * sizeof(struct perf_counts_values))));
> +	perf_counts__reset(evsel->counts, ncpus);
>  }
>  
>  int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
>  {
> -	evsel->counts = zalloc((sizeof(*evsel->counts) +
> -				(ncpus * sizeof(struct perf_counts_values))));
> +	evsel->counts = perf_counts__new(ncpus);
>  	return evsel->counts != NULL ? 0 : -ENOMEM;
>  }
>  
>  void perf_evsel__free_counts(struct perf_evsel *evsel)
>  {
> -	zfree(&evsel->counts);
> +	perf_counts__delete(evsel->counts);
> +	evsel->counts = NULL;
>  }
> diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
> index 6a782601c1c7..093dc3cb28dd 100644
> --- a/tools/perf/util/stat.h
> +++ b/tools/perf/util/stat.h
> @@ -62,6 +62,9 @@ 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);
> +void perf_counts__delete(struct perf_counts *counts);
> +
>  void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
>  int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
>  void perf_evsel__free_counts(struct perf_evsel *evsel);
> -- 
> 1.9.3

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

* Re: [PATCH 07/30] perf tools: Add reference counting for thread_map object
  2015-06-15 19:25   ` Arnaldo Carvalho de Melo
@ 2015-06-15 21:28     ` Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-15 21:28 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 15, 2015 at 04:25:44PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sun, Jun 14, 2015 at 10:19:22AM +0200, Jiri Olsa escreveu:
> > 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.
>  
> <SNIP>
> 
> > +struct thread_map *thread_map__get(struct thread_map *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);
> >  }
> 
> See comment on the other struct being refcounted, get/put should
> both accept NULL maps, to avoid having to check it in the users,
> just like with free().

ook, will repost with the get function fix

thanks,
jirka

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

* Re: [PATCH 08/30] perf tools: Propagate cpu maps through the evlist
  2015-06-15 19:34   ` Arnaldo Carvalho de Melo
@ 2015-06-15 21:29     ` Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-15 21:29 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 15, 2015 at 04:34:18PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sun, Jun 14, 2015 at 10:19:23AM +0200, Jiri Olsa escreveu:
> > 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 | 24 +++++++++++++++++++++++-
> >  1 file changed, 23 insertions(+), 1 deletion(-)
> > 
> > diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
> > index f7d80ca58136..c0d3058c1868 100644
> > --- a/tools/perf/util/evlist.c
> > +++ b/tools/perf/util/evlist.c
> > @@ -1085,6 +1085,28 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
> >  	return perf_evlist__mmap_ex(evlist, pages, overwrite, 0, false);
> >  }
> >  
> > +static int propagate_maps(struct perf_evlist *evlist, struct target *target)
> 
> Please rename this to perf_evlist__set_maps()

we already have this one.. how about perf_evlist__ropagate_maps ?

jirka

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

* Re: [PATCH 03/30] perf tools: Change thread_map::map into struct
  2015-06-15 19:04   ` Arnaldo Carvalho de Melo
@ 2015-06-15 21:33     ` Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-15 21:33 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 15, 2015 at 04:04:04PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sun, Jun 14, 2015 at 10:19:18AM +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.
> 
> <SNIP>
>  
> > +++ 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;
> > +};
> > +
> 
> What 'data' is this? That is way vague term.

data related to thread_mmap ;-)

jirka

> 
>  Will try looking at the other patches to try to suggest some other name
> for this :-\
> 
> >  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	[flat|nested] 45+ messages in thread

* Re: [PATCH 04/30] perf tools: Add comm string into struct thread_map
  2015-06-15 19:17   ` Arnaldo Carvalho de Melo
@ 2015-06-15 21:55     ` Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: Jiri Olsa @ 2015-06-15 21:55 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 15, 2015 at 04:17:07PM -0300, Arnaldo Carvalho de Melo wrote:
> Em Sun, Jun 14, 2015 at 10:19:19AM +0200, Jiri Olsa escreveu:
> > 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.
> 
> Humm, so you want to extend the thread_map, that was just for pids, to
> have some more info about the thread, if that is the case, why not
> synthesize the whole thread, and have a pointer to 'struct thread', that
> is the representation for a thread in perf instead of creating a new,
> partial thing like 'thread_map_data'?
> 
> You wouldn't have to use the existing synthesizing code if that seems to
> overkill, i.e. instead of having 'pid_t' as the array element in a
> thread_map, you would have 'struct thread', i.e. the whole shebang, but
> would just set what you need now, i.e. thread->pid and thread->comm, but
> later could do the rest instead of recreating it in that thread_map_data
> :-)

hum, I guess I could find some parts of code that could be shared,
but I fear not all of it.. 'struct thread' seems to be fairly
customized for usage in sampling report code

maybe introduce 'machine' storage and provide interface to fill in
live server data.. but it feels like overkill just for 2 lines of
code that need print pid's name ;-)

> 
> I.e. besides --per-task, don't you want --per-pid, --per-thread, or
> other stuff that will use other thread characteristics?

with --per-task we dont do any grouping, just displaying
what we store (now) for each separated thread

it might be better to use --per-thread instead of --per-task probably,
I dont have strong feeling about that

also we could add --per-process that would group all threads
based on process

jirka

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

* [tip:perf/core] perf tools: Introduce xyarray__reset function
  2015-06-14  8:19 ` [PATCH 01/30] perf tools: Introduce xyarray__reset function Jiri Olsa
@ 2015-06-18  8:13   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-06-18  8:13 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: eranian, linux-kernel, ak, jolsa, acme, hpa, tglx, namhyung,
	mingo, a.p.zijlstra, dsahern, adrian.hunter

Commit-ID:  b45f65e8fddc89ac6b46388908d3f6ac728be372
Gitweb:     http://git.kernel.org/tip/b45f65e8fddc89ac6b46388908d3f6ac728be372
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Sun, 14 Jun 2015 10:19:16 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 16 Jun 2015 10:34:39 -0300

perf tools: Introduce xyarray__reset function

To zero all the xyarray contents. It will be used in following patches.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1434269985-521-2-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/xyarray.c | 8 ++++++++
 tools/perf/util/xyarray.h | 2 ++
 2 files changed, 10 insertions(+)

diff --git a/tools/perf/util/xyarray.c b/tools/perf/util/xyarray.c
index 22afbf6..c10ba41 100644
--- a/tools/perf/util/xyarray.c
+++ b/tools/perf/util/xyarray.c
@@ -9,11 +9,19 @@ struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size)
 	if (xy != NULL) {
 		xy->entry_size = entry_size;
 		xy->row_size   = row_size;
+		xy->entries    = xlen * ylen;
 	}
 
 	return xy;
 }
 
+void xyarray__reset(struct xyarray *xy)
+{
+	size_t n = xy->entries * xy->entry_size;
+
+	memset(xy->contents, 0, n);
+}
+
 void xyarray__delete(struct xyarray *xy)
 {
 	free(xy);
diff --git a/tools/perf/util/xyarray.h b/tools/perf/util/xyarray.h
index c488a07..7f30af3 100644
--- a/tools/perf/util/xyarray.h
+++ b/tools/perf/util/xyarray.h
@@ -6,11 +6,13 @@
 struct xyarray {
 	size_t row_size;
 	size_t entry_size;
+	size_t entries;
 	char contents[];
 };
 
 struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
 void xyarray__delete(struct xyarray *xy);
+void xyarray__reset(struct xyarray *xy);
 
 static inline void *xyarray__entry(struct xyarray *xy, int x, int y)
 {

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

* [tip:perf/core] perf tools: Add thread_map__(alloc|realloc) helpers
  2015-06-14  8:19 ` [PATCH 02/30] perf tools: Add thread_map__(alloc|realloc) helpers Jiri Olsa
@ 2015-06-18  8:14   ` tip-bot for Jiri Olsa
  0 siblings, 0 replies; 45+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-06-18  8:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, a.p.zijlstra, namhyung, adrian.hunter, tglx, hpa, acme,
	linux-kernel, jolsa, dsahern, ak, eranian

Commit-ID:  9d7e8c3a96e5a903a4e0951e08f7fa6957170bef
Gitweb:     http://git.kernel.org/tip/9d7e8c3a96e5a903a4e0951e08f7fa6957170bef
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Sun, 14 Jun 2015 10:19:17 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 16 Jun 2015 10:34:40 -0300

perf tools: Add thread_map__(alloc|realloc) helpers

In order to have 'struct thread_map' allocation on single place and can
change it easily in following patch.

Using alloc|realloc for static helpers, because thread_map__new is
already used in public interface.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1434269985-521-3-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/thread_map.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index f93b973..f4822bd 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -20,6 +20,15 @@ static int filter(const struct dirent *dir)
 		return 1;
 }
 
+static struct thread_map *thread_map__realloc(struct thread_map *map, int nr)
+{
+	size_t size = sizeof(*map) + sizeof(pid_t) * nr;
+
+	return realloc(map, size);
+}
+
+#define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr)
+
 struct thread_map *thread_map__new_by_pid(pid_t pid)
 {
 	struct thread_map *threads;
@@ -33,7 +42,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 	if (items <= 0)
 		return NULL;
 
-	threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
+	threads = thread_map__alloc(items);
 	if (threads != NULL) {
 		for (i = 0; i < items; i++)
 			threads->map[i] = atoi(namelist[i]->d_name);
@@ -49,7 +58,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
 
 struct thread_map *thread_map__new_by_tid(pid_t tid)
 {
-	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
 		threads->map[0] = tid;
@@ -65,8 +74,8 @@ struct thread_map *thread_map__new_by_uid(uid_t uid)
 	int max_threads = 32, items, i;
 	char path[256];
 	struct dirent dirent, *next, **namelist = NULL;
-	struct thread_map *threads = malloc(sizeof(*threads) +
-					    max_threads * sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(max_threads);
+
 	if (threads == NULL)
 		goto out;
 
@@ -185,8 +194,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
 			goto out_free_threads;
 
 		total_tasks += items;
-		nt = realloc(threads, (sizeof(*threads) +
-				       sizeof(pid_t) * total_tasks));
+		nt = thread_map__realloc(threads, total_tasks);
 		if (nt == NULL)
 			goto out_free_namelist;
 
@@ -216,7 +224,7 @@ out_free_threads:
 
 struct thread_map *thread_map__new_dummy(void)
 {
-	struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t));
+	struct thread_map *threads = thread_map__alloc(1);
 
 	if (threads != NULL) {
 		threads->map[0]	= -1;
@@ -253,7 +261,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
 			continue;
 
 		ntasks++;
-		nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks);
+		nt = thread_map__realloc(threads, ntasks);
 
 		if (nt == NULL)
 			goto out_free_threads;

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

* [tip:perf/core] perf tools: Move perf_evsel__(alloc|free|reset) _counts into stat object
  2015-06-14  8:19 ` [PATCH 11/30] perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object Jiri Olsa
  2015-06-15 20:13   ` Arnaldo Carvalho de Melo
@ 2015-06-18  8:14   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 45+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-06-18  8:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, eranian, tglx, adrian.hunter, a.p.zijlstra, hpa, mingo,
	linux-kernel, dsahern, ak, acme, namhyung

Commit-ID:  a9a3a4d92d8f2fb68f4b99d98505bebc70518599
Gitweb:     http://git.kernel.org/tip/a9a3a4d92d8f2fb68f4b99d98505bebc70518599
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Sun, 14 Jun 2015 10:19:26 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 16 Jun 2015 10:34:40 -0300

perf tools: Move perf_evsel__(alloc|free|reset)_counts into stat object

It's stat specific. Updating python build objects with stat.c.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1434269985-521-12-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/tests/openat-syscall-all-cpus.c |  1 +
 tools/perf/util/evsel.c                    | 19 +------------------
 tools/perf/util/evsel.h                    |  3 ---
 tools/perf/util/python-ext-sources         |  1 +
 tools/perf/util/stat.c                     | 18 ++++++++++++++++++
 tools/perf/util/stat.h                     |  3 +++
 6 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index e34dfdf..9a7a116 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -3,6 +3,7 @@
 #include "thread_map.h"
 #include "cpumap.h"
 #include "debug.h"
+#include "stat.h"
 
 int test__openat_syscall_event_on_all_cpus(void)
 {
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d4f9994..33449de 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -26,6 +26,7 @@
 #include "perf_regs.h"
 #include "debug.h"
 #include "trace-event.h"
+#include "stat.h"
 
 static struct {
 	bool sample_id_all;
@@ -851,19 +852,6 @@ int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
 	return 0;
 }
 
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
-{
-	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
-				 (ncpus * sizeof(struct perf_counts_values))));
-}
-
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
-{
-	evsel->counts = zalloc((sizeof(*evsel->counts) +
-				(ncpus * sizeof(struct perf_counts_values))));
-	return evsel->counts != NULL ? 0 : -ENOMEM;
-}
-
 static void perf_evsel__free_fd(struct perf_evsel *evsel)
 {
 	xyarray__delete(evsel->fd);
@@ -891,11 +879,6 @@ void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
 		}
 }
 
-void perf_evsel__free_counts(struct perf_evsel *evsel)
-{
-	zfree(&evsel->counts);
-}
-
 void perf_evsel__exit(struct perf_evsel *evsel)
 {
 	assert(list_empty(&evsel->node));
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 21ec082..bb0579e 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -170,9 +170,6 @@ const char *perf_evsel__group_name(struct perf_evsel *evsel);
 int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size);
 
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
-int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
-void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
-void perf_evsel__free_counts(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 void __perf_evsel__set_sample_bit(struct perf_evsel *evsel,
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 4d28624..5925fec 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -16,6 +16,7 @@ util/util.c
 util/xyarray.c
 util/cgroup.c
 util/rblist.c
+util/stat.c
 util/strlist.c
 util/trace-event.c
 ../../lib/rbtree.c
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 60b9282..ac589b6 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -94,3 +94,21 @@ void perf_stat_evsel_id_init(struct perf_evsel *evsel)
 		}
 	}
 }
+
+void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
+{
+	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
+				 (ncpus * sizeof(struct perf_counts_values))));
+}
+
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
+{
+	evsel->counts = zalloc((sizeof(*evsel->counts) +
+				(ncpus * sizeof(struct perf_counts_values))));
+	return evsel->counts != NULL ? 0 : -ENOMEM;
+}
+
+void perf_evsel__free_counts(struct perf_evsel *evsel)
+{
+	zfree(&evsel->counts);
+}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 615c779..6a78260 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -62,4 +62,7 @@ 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);
 
+void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
+int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
+void perf_evsel__free_counts(struct perf_evsel *evsel);
 #endif

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

* [tip:perf/core] perf stat: Introduce perf_counts__( new|delete|reset) functions
  2015-06-14  8:19 ` [PATCH 12/30] perf stat: Introduce perf_counts__(alloc|free|reset) functions Jiri Olsa
  2015-06-15 20:16   ` Arnaldo Carvalho de Melo
@ 2015-06-18  8:14   ` tip-bot for Jiri Olsa
  1 sibling, 0 replies; 45+ messages in thread
From: tip-bot for Jiri Olsa @ 2015-06-18  8:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, dsahern, a.p.zijlstra, ak, hpa, tglx, eranian,
	acme, mingo, namhyung, adrian.hunter, jolsa

Commit-ID:  9df38e82e2a103cf42177c164a4de9d58052ac3a
Gitweb:     http://git.kernel.org/tip/9df38e82e2a103cf42177c164a4de9d58052ac3a
Author:     Jiri Olsa <jolsa@kernel.org>
AuthorDate: Sun, 14 Jun 2015 10:19:27 +0200
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 16 Jun 2015 10:34:41 -0300

perf stat: Introduce perf_counts__(new|delete|reset) functions

Move 'struct perf_counts' allocation|free|reset code into separate
functions.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1434269985-521-13-git-send-email-jolsa@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-stat.c | 19 +++++++------------
 tools/perf/util/stat.c    | 28 +++++++++++++++++++++++-----
 tools/perf/util/stat.h    |  3 +++
 3 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index b24ecee..fcf99bd 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -178,24 +178,19 @@ static void perf_evsel__free_stat_priv(struct perf_evsel *evsel)
 
 static int perf_evsel__alloc_prev_raw_counts(struct perf_evsel *evsel)
 {
-	void *addr;
-	size_t sz;
+	struct perf_counts *counts;
 
-	sz = sizeof(*evsel->counts) +
-	     (perf_evsel__nr_cpus(evsel) * sizeof(struct perf_counts_values));
+	counts = perf_counts__new(perf_evsel__nr_cpus(evsel));
+	if (counts)
+		evsel->prev_raw_counts = counts;
 
-	addr = zalloc(sz);
-	if (!addr)
-		return -ENOMEM;
-
-	evsel->prev_raw_counts =  addr;
-
-	return 0;
+	return counts ? 0 : -ENOMEM;
 }
 
 static void perf_evsel__free_prev_raw_counts(struct perf_evsel *evsel)
 {
-	zfree(&evsel->prev_raw_counts);
+	perf_counts__delete(evsel->prev_raw_counts);
+	evsel->prev_raw_counts = NULL;
 }
 
 static void perf_evlist__free_stats(struct perf_evlist *evlist)
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index ac589b6..4014b70 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -95,20 +95,38 @@ 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);
+
+	return zalloc(size);
+}
+
+void perf_counts__delete(struct perf_counts *counts)
+{
+	free(counts);
+}
+
+static void perf_counts__reset(struct perf_counts *counts, int ncpus)
+{
+	memset(counts, 0, (sizeof(*counts) +
+	       (ncpus * sizeof(struct perf_counts_values))));
+}
+
 void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus)
 {
-	memset(evsel->counts, 0, (sizeof(*evsel->counts) +
-				 (ncpus * sizeof(struct perf_counts_values))));
+	perf_counts__reset(evsel->counts, ncpus);
 }
 
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)
 {
-	evsel->counts = zalloc((sizeof(*evsel->counts) +
-				(ncpus * sizeof(struct perf_counts_values))));
+	evsel->counts = perf_counts__new(ncpus);
 	return evsel->counts != NULL ? 0 : -ENOMEM;
 }
 
 void perf_evsel__free_counts(struct perf_evsel *evsel)
 {
-	zfree(&evsel->counts);
+	perf_counts__delete(evsel->counts);
+	evsel->counts = NULL;
 }
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 6a78260..093dc3c 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -62,6 +62,9 @@ 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);
+void perf_counts__delete(struct perf_counts *counts);
+
 void perf_evsel__reset_counts(struct perf_evsel *evsel, int ncpus);
 int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
 void perf_evsel__free_counts(struct perf_evsel *evsel);

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

end of thread, other threads:[~2015-06-18  8:16 UTC | newest]

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.