aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-01-26 06:11:41 -0500
committerIngo Molnar <mingo@elte.hu>2012-01-26 06:11:41 -0500
commit939ddcfa60dabfaed390987bf0103a6654c0fe30 (patch)
treebaa9b89a2b268d99496805f761ab9a00c272c0dc /tools
parent96070c83b295b31912ad92d3ffb66baec2b86d50 (diff)
parentf8f4b2872295dca88339ec0c403b2217b1197353 (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull in the latest perf/core improvements and fixes. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-record.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt4
-rw-r--r--tools/perf/Makefile11
-rw-r--r--tools/perf/bench/bench.h1
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm-def.h8
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S6
-rw-r--r--tools/perf/bench/mem-memcpy.c11
-rw-r--r--tools/perf/bench/mem-memset-arch.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm-def.h12
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S6
-rw-r--r--tools/perf/bench/mem-memset.c298
-rw-r--r--tools/perf/builtin-bench.c3
-rw-r--r--tools/perf/builtin-probe.c2
-rw-r--r--tools/perf/builtin-record.c12
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/builtin-test.c8
-rw-r--r--tools/perf/builtin-top.c22
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/util/cpumap.c11
-rw-r--r--tools/perf/util/cpumap.h4
-rw-r--r--tools/perf/util/evlist.c6
-rw-r--r--tools/perf/util/evlist.h2
-rw-r--r--tools/perf/util/header.c2
-rw-r--r--tools/perf/util/hist.h1
-rw-r--r--tools/perf/util/include/asm/dwarf2.h4
-rw-r--r--tools/perf/util/probe-event.c8
-rw-r--r--tools/perf/util/python.c10
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/thread_map.c109
-rw-r--r--tools/perf/util/thread_map.h7
-rw-r--r--tools/perf/util/top.c3
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/trace-event-parse.c3
-rw-r--r--tools/perf/util/ui/browsers/hists.c5
-rw-r--r--tools/perf/util/ui/helpline.c1
-rw-r--r--tools/perf/util/usage.c39
-rw-r--r--tools/perf/util/util.h3
37 files changed, 597 insertions, 47 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 2937f7e14bb7..ff9a66e0d4e4 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -58,6 +58,10 @@ OPTIONS
58--tid=:: 58--tid=::
59 Record events on existing thread ID. 59 Record events on existing thread ID.
60 60
61-u::
62--uid=::
63 Record events in threads owned by uid. Name or number.
64
61-r:: 65-r::
62--realtime=:: 66--realtime=::
63 Collect data with this RT SCHED_FIFO priority. 67 Collect data with this RT SCHED_FIFO priority.
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index b1a5bbbfebef..ab1454ed450f 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -78,6 +78,10 @@ Default is to monitor all CPUS.
78--tid=<tid>:: 78--tid=<tid>::
79 Profile events on existing thread ID. 79 Profile events on existing thread ID.
80 80
81-u::
82--uid=::
83 Record events in threads owned by uid. Name or number.
84
81-r <priority>:: 85-r <priority>::
82--realtime=<priority>:: 86--realtime=<priority>::
83 Collect data with this RT SCHED_FIFO priority. 87 Collect data with this RT SCHED_FIFO priority.
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index ac86d67b636e..d64f5819a380 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -61,7 +61,7 @@ ifeq ($(ARCH),x86_64)
61 ifeq (${IS_X86_64}, 1) 61 ifeq (${IS_X86_64}, 1)
62 RAW_ARCH := x86_64 62 RAW_ARCH := x86_64
63 ARCH_CFLAGS := -DARCH_X86_64 63 ARCH_CFLAGS := -DARCH_X86_64
64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S 64 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
65 endif 65 endif
66endif 66endif
67 67
@@ -104,7 +104,7 @@ endif
104 104
105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 105CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
106EXTLIBS = -lpthread -lrt -lelf -lm 106EXTLIBS = -lpthread -lrt -lelf -lm
107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 107ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
108ALL_LDFLAGS = $(LDFLAGS) 108ALL_LDFLAGS = $(LDFLAGS)
109STRIP ?= strip 109STRIP ?= strip
110 110
@@ -168,10 +168,7 @@ endif
168 168
169### --- END CONFIGURATION SECTION --- 169### --- END CONFIGURATION SECTION ---
170 170
171# Those must not be GNU-specific; they are shared with perl/ which may 171BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
172# be built by a different compiler. (Note that this is an artifact now
173# but it still might be nice to keep that distinction.)
174BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include
175BASIC_LDFLAGS = 172BASIC_LDFLAGS =
176 173
177# Guard against environment variables 174# Guard against environment variables
@@ -362,8 +359,10 @@ BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o
362BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o 359BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o
363ifeq ($(RAW_ARCH),x86_64) 360ifeq ($(RAW_ARCH),x86_64)
364BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o 361BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o
362BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o
365endif 363endif
366BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 364BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
365BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o
367 366
368BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 367BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
369BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o 368BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h
index f7781c6267c0..a09bece6dad2 100644
--- a/tools/perf/bench/bench.h
+++ b/tools/perf/bench/bench.h
@@ -4,6 +4,7 @@
4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); 4extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); 5extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); 6extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used);
7extern int bench_mem_memset(int argc, const char **argv, const char *prefix);
7 8
8#define BENCH_FORMAT_DEFAULT_STR "default" 9#define BENCH_FORMAT_DEFAULT_STR "default"
9#define BENCH_FORMAT_DEFAULT 0 10#define BENCH_FORMAT_DEFAULT 0
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
index d588b87696fc..d66ab799b35f 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm-def.h
@@ -2,3 +2,11 @@
2MEMCPY_FN(__memcpy, 2MEMCPY_FN(__memcpy,
3 "x86-64-unrolled", 3 "x86-64-unrolled",
4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S") 4 "unrolled memcpy() in arch/x86/lib/memcpy_64.S")
5
6MEMCPY_FN(memcpy_c,
7 "x86-64-movsq",
8 "movsq-based memcpy() in arch/x86/lib/memcpy_64.S")
9
10MEMCPY_FN(memcpy_c_e,
11 "x86-64-movsb",
12 "movsb-based memcpy() in arch/x86/lib/memcpy_64.S")
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index a57b66e853c2..a20780bd0771 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,2 +1,6 @@
1 1#define memcpy MEMCPY /* don't hide glibc's memcpy() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemcpy_c globl memcpy_c; memcpy_c
5#define Lmemcpy_c_e globl memcpy_c_e; memcpy_c_e
2#include "../../../arch/x86/lib/memcpy_64.S" 6#include "../../../arch/x86/lib/memcpy_64.S"
diff --git a/tools/perf/bench/mem-memcpy.c b/tools/perf/bench/mem-memcpy.c
index db82021f4b91..6ad2b1c6b27b 100644
--- a/tools/perf/bench/mem-memcpy.c
+++ b/tools/perf/bench/mem-memcpy.c
@@ -24,6 +24,7 @@
24 24
25static const char *length_str = "1MB"; 25static const char *length_str = "1MB";
26static const char *routine = "default"; 26static const char *routine = "default";
27static int iterations = 1;
27static bool use_clock; 28static bool use_clock;
28static int clock_fd; 29static int clock_fd;
29static bool only_prefault; 30static bool only_prefault;
@@ -35,6 +36,8 @@ static const struct option options[] = {
35 "available unit: B, MB, GB (upper and lower)"), 36 "available unit: B, MB, GB (upper and lower)"),
36 OPT_STRING('r', "routine", &routine, "default", 37 OPT_STRING('r', "routine", &routine, "default",
37 "Specify routine to copy"), 38 "Specify routine to copy"),
39 OPT_INTEGER('i', "iterations", &iterations,
40 "repeat memcpy() invocation this number of times"),
38 OPT_BOOLEAN('c', "clock", &use_clock, 41 OPT_BOOLEAN('c', "clock", &use_clock,
39 "Use CPU clock for measuring"), 42 "Use CPU clock for measuring"),
40 OPT_BOOLEAN('o', "only-prefault", &only_prefault, 43 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
@@ -121,6 +124,7 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
121{ 124{
122 u64 clock_start = 0ULL, clock_end = 0ULL; 125 u64 clock_start = 0ULL, clock_end = 0ULL;
123 void *src = NULL, *dst = NULL; 126 void *src = NULL, *dst = NULL;
127 int i;
124 128
125 alloc_mem(&src, &dst, len); 129 alloc_mem(&src, &dst, len);
126 130
@@ -128,7 +132,8 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
128 fn(dst, src, len); 132 fn(dst, src, len);
129 133
130 clock_start = get_clock(); 134 clock_start = get_clock();
131 fn(dst, src, len); 135 for (i = 0; i < iterations; ++i)
136 fn(dst, src, len);
132 clock_end = get_clock(); 137 clock_end = get_clock();
133 138
134 free(src); 139 free(src);
@@ -140,6 +145,7 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
140{ 145{
141 struct timeval tv_start, tv_end, tv_diff; 146 struct timeval tv_start, tv_end, tv_diff;
142 void *src = NULL, *dst = NULL; 147 void *src = NULL, *dst = NULL;
148 int i;
143 149
144 alloc_mem(&src, &dst, len); 150 alloc_mem(&src, &dst, len);
145 151
@@ -147,7 +153,8 @@ static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
147 fn(dst, src, len); 153 fn(dst, src, len);
148 154
149 BUG_ON(gettimeofday(&tv_start, NULL)); 155 BUG_ON(gettimeofday(&tv_start, NULL));
150 fn(dst, src, len); 156 for (i = 0; i < iterations; ++i)
157 fn(dst, src, len);
151 BUG_ON(gettimeofday(&tv_end, NULL)); 158 BUG_ON(gettimeofday(&tv_end, NULL));
152 159
153 timersub(&tv_end, &tv_start, &tv_diff); 160 timersub(&tv_end, &tv_start, &tv_diff);
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h
new file mode 100644
index 000000000000..a040fa77665b
--- /dev/null
+++ b/tools/perf/bench/mem-memset-arch.h
@@ -0,0 +1,12 @@
1
2#ifdef ARCH_X86_64
3
4#define MEMSET_FN(fn, name, desc) \
5 extern void *fn(void *, int, size_t);
6
7#include "mem-memset-x86-64-asm-def.h"
8
9#undef MEMSET_FN
10
11#endif
12
diff --git a/tools/perf/bench/mem-memset-x86-64-asm-def.h b/tools/perf/bench/mem-memset-x86-64-asm-def.h
new file mode 100644
index 000000000000..a71dff97c1f5
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm-def.h
@@ -0,0 +1,12 @@
1
2MEMSET_FN(__memset,
3 "x86-64-unrolled",
4 "unrolled memset() in arch/x86/lib/memset_64.S")
5
6MEMSET_FN(memset_c,
7 "x86-64-stosq",
8 "movsq-based memset() in arch/x86/lib/memset_64.S")
9
10MEMSET_FN(memset_c_e,
11 "x86-64-stosb",
12 "movsb-based memset() in arch/x86/lib/memset_64.S")
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
new file mode 100644
index 000000000000..cb9217063776
--- /dev/null
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -0,0 +1,6 @@
1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text
3#define globl p2align 4; .globl
4#define Lmemset_c globl memset_c; memset_c
5#define Lmemset_c_e globl memset_c_e; memset_c_e
6#include "../../../arch/x86/lib/memset_64.S"
diff --git a/tools/perf/bench/mem-memset.c b/tools/perf/bench/mem-memset.c
new file mode 100644
index 000000000000..59d4933eff44
--- /dev/null
+++ b/tools/perf/bench/mem-memset.c
@@ -0,0 +1,298 @@
1/*
2 * mem-memset.c
3 *
4 * memset: Simple memory set in various ways
5 *
6 * Trivial clone of mem-memcpy.c.
7 */
8#include <ctype.h>
9
10#include "../perf.h"
11#include "../util/util.h"
12#include "../util/parse-options.h"
13#include "../util/header.h"
14#include "bench.h"
15#include "mem-memset-arch.h"
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/time.h>
21#include <errno.h>
22
23#define K 1024
24
25static const char *length_str = "1MB";
26static const char *routine = "default";
27static int iterations = 1;
28static bool use_clock;
29static int clock_fd;
30static bool only_prefault;
31static bool no_prefault;
32
33static const struct option options[] = {
34 OPT_STRING('l', "length", &length_str, "1MB",
35 "Specify length of memory to copy. "
36 "available unit: B, MB, GB (upper and lower)"),
37 OPT_STRING('r', "routine", &routine, "default",
38 "Specify routine to copy"),
39 OPT_INTEGER('i', "iterations", &iterations,
40 "repeat memset() invocation this number of times"),
41 OPT_BOOLEAN('c', "clock", &use_clock,
42 "Use CPU clock for measuring"),
43 OPT_BOOLEAN('o', "only-prefault", &only_prefault,
44 "Show only the result with page faults before memset()"),
45 OPT_BOOLEAN('n', "no-prefault", &no_prefault,
46 "Show only the result without page faults before memset()"),
47 OPT_END()
48};
49
50typedef void *(*memset_t)(void *, int, size_t);
51
52struct routine {
53 const char *name;
54 const char *desc;
55 memset_t fn;
56};
57
58static const struct routine routines[] = {
59 { "default",
60 "Default memset() provided by glibc",
61 memset },
62#ifdef ARCH_X86_64
63
64#define MEMSET_FN(fn, name, desc) { name, desc, fn },
65#include "mem-memset-x86-64-asm-def.h"
66#undef MEMSET_FN
67
68#endif
69
70 { NULL,
71 NULL,
72 NULL }
73};
74
75static const char * const bench_mem_memset_usage[] = {
76 "perf bench mem memset <options>",
77 NULL
78};
79
80static struct perf_event_attr clock_attr = {
81 .type = PERF_TYPE_HARDWARE,
82 .config = PERF_COUNT_HW_CPU_CYCLES
83};
84
85static void init_clock(void)
86{
87 clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
88
89 if (clock_fd < 0 && errno == ENOSYS)
90 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
91 else
92 BUG_ON(clock_fd < 0);
93}
94
95static u64 get_clock(void)
96{
97 int ret;
98 u64 clk;
99
100 ret = read(clock_fd, &clk, sizeof(u64));
101 BUG_ON(ret != sizeof(u64));
102
103 return clk;
104}
105
106static double timeval2double(struct timeval *ts)
107{
108 return (double)ts->tv_sec +
109 (double)ts->tv_usec / (double)1000000;
110}
111
112static void alloc_mem(void **dst, size_t length)
113{
114 *dst = zalloc(length);
115 if (!dst)
116 die("memory allocation failed - maybe length is too large?\n");
117}
118
119static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
120{
121 u64 clock_start = 0ULL, clock_end = 0ULL;
122 void *dst = NULL;
123 int i;
124
125 alloc_mem(&dst, len);
126
127 if (prefault)
128 fn(dst, -1, len);
129
130 clock_start = get_clock();
131 for (i = 0; i < iterations; ++i)
132 fn(dst, i, len);
133 clock_end = get_clock();
134
135 free(dst);
136 return clock_end - clock_start;
137}
138
139static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
140{
141 struct timeval tv_start, tv_end, tv_diff;
142 void *dst = NULL;
143 int i;
144
145 alloc_mem(&dst, len);
146
147 if (prefault)
148 fn(dst, -1, len);
149
150 BUG_ON(gettimeofday(&tv_start, NULL));
151 for (i = 0; i < iterations; ++i)
152 fn(dst, i, len);
153 BUG_ON(gettimeofday(&tv_end, NULL));
154
155 timersub(&tv_end, &tv_start, &tv_diff);
156
157 free(dst);
158 return (double)((double)len / timeval2double(&tv_diff));
159}
160
161#define pf (no_prefault ? 0 : 1)
162
163#define print_bps(x) do { \
164 if (x < K) \
165 printf(" %14lf B/Sec", x); \
166 else if (x < K * K) \
167 printf(" %14lfd KB/Sec", x / K); \
168 else if (x < K * K * K) \
169 printf(" %14lf MB/Sec", x / K / K); \
170 else \
171 printf(" %14lf GB/Sec", x / K / K / K); \
172 } while (0)
173
174int bench_mem_memset(int argc, const char **argv,
175 const char *prefix __used)
176{
177 int i;
178 size_t len;
179 double result_bps[2];
180 u64 result_clock[2];
181
182 argc = parse_options(argc, argv, options,
183 bench_mem_memset_usage, 0);
184
185 if (use_clock)
186 init_clock();
187
188 len = (size_t)perf_atoll((char *)length_str);
189
190 result_clock[0] = result_clock[1] = 0ULL;
191 result_bps[0] = result_bps[1] = 0.0;
192
193 if ((s64)len <= 0) {
194 fprintf(stderr, "Invalid length:%s\n", length_str);
195 return 1;
196 }
197
198 /* same to without specifying either of prefault and no-prefault */
199 if (only_prefault && no_prefault)
200 only_prefault = no_prefault = false;
201
202 for (i = 0; routines[i].name; i++) {
203 if (!strcmp(routines[i].name, routine))
204 break;
205 }
206 if (!routines[i].name) {
207 printf("Unknown routine:%s\n", routine);
208 printf("Available routines...\n");
209 for (i = 0; routines[i].name; i++) {
210 printf("\t%s ... %s\n",
211 routines[i].name, routines[i].desc);
212 }
213 return 1;
214 }
215
216 if (bench_format == BENCH_FORMAT_DEFAULT)
217 printf("# Copying %s Bytes ...\n\n", length_str);
218
219 if (!only_prefault && !no_prefault) {
220 /* show both of results */
221 if (use_clock) {
222 result_clock[0] =
223 do_memset_clock(routines[i].fn, len, false);
224 result_clock[1] =
225 do_memset_clock(routines[i].fn, len, true);
226 } else {
227 result_bps[0] =
228 do_memset_gettimeofday(routines[i].fn,
229 len, false);
230 result_bps[1] =
231 do_memset_gettimeofday(routines[i].fn,
232 len, true);
233 }
234 } else {
235 if (use_clock) {
236 result_clock[pf] =
237 do_memset_clock(routines[i].fn,
238 len, only_prefault);
239 } else {
240 result_bps[pf] =
241 do_memset_gettimeofday(routines[i].fn,
242 len, only_prefault);
243 }
244 }
245
246 switch (bench_format) {
247 case BENCH_FORMAT_DEFAULT:
248 if (!only_prefault && !no_prefault) {
249 if (use_clock) {
250 printf(" %14lf Clock/Byte\n",
251 (double)result_clock[0]
252 / (double)len);
253 printf(" %14lf Clock/Byte (with prefault)\n ",
254 (double)result_clock[1]
255 / (double)len);
256 } else {
257 print_bps(result_bps[0]);
258 printf("\n");
259 print_bps(result_bps[1]);
260 printf(" (with prefault)\n");
261 }
262 } else {
263 if (use_clock) {
264 printf(" %14lf Clock/Byte",
265 (double)result_clock[pf]
266 / (double)len);
267 } else
268 print_bps(result_bps[pf]);
269
270 printf("%s\n", only_prefault ? " (with prefault)" : "");
271 }
272 break;
273 case BENCH_FORMAT_SIMPLE:
274 if (!only_prefault && !no_prefault) {
275 if (use_clock) {
276 printf("%lf %lf\n",
277 (double)result_clock[0] / (double)len,
278 (double)result_clock[1] / (double)len);
279 } else {
280 printf("%lf %lf\n",
281 result_bps[0], result_bps[1]);
282 }
283 } else {
284 if (use_clock) {
285 printf("%lf\n", (double)result_clock[pf]
286 / (double)len);
287 } else
288 printf("%lf\n", result_bps[pf]);
289 }
290 break;
291 default:
292 /* reaching this means there's some disaster: */
293 die("unknown format: %d\n", bench_format);
294 break;
295 }
296
297 return 0;
298}
diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c
index fcb96269852a..b0e74ab2d7a2 100644
--- a/tools/perf/builtin-bench.c
+++ b/tools/perf/builtin-bench.c
@@ -52,6 +52,9 @@ static struct bench_suite mem_suites[] = {
52 { "memcpy", 52 { "memcpy",
53 "Simple memory copy in various ways", 53 "Simple memory copy in various ways",
54 bench_mem_memcpy }, 54 bench_mem_memcpy },
55 { "memset",
56 "Simple memory set in various ways",
57 bench_mem_memset },
55 suite_all, 58 suite_all,
56 { NULL, 59 { NULL,
57 NULL, 60 NULL,
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 59d43abfbfec..fb8566181f27 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -20,7 +20,6 @@
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 * 21 *
22 */ 22 */
23#define _GNU_SOURCE
24#include <sys/utsname.h> 23#include <sys/utsname.h>
25#include <sys/types.h> 24#include <sys/types.h>
26#include <sys/stat.h> 25#include <sys/stat.h>
@@ -31,7 +30,6 @@
31#include <stdlib.h> 30#include <stdlib.h>
32#include <string.h> 31#include <string.h>
33 32
34#undef _GNU_SOURCE
35#include "perf.h" 33#include "perf.h"
36#include "builtin.h" 34#include "builtin.h"
37#include "util/util.h" 35#include "util/util.h"
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 0abfb18b911f..32870eef952f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -44,6 +44,7 @@ struct perf_record {
44 struct perf_evlist *evlist; 44 struct perf_evlist *evlist;
45 struct perf_session *session; 45 struct perf_session *session;
46 const char *progname; 46 const char *progname;
47 const char *uid_str;
47 int output; 48 int output;
48 unsigned int page_size; 49 unsigned int page_size;
49 int realtime_prio; 50 int realtime_prio;
@@ -727,6 +728,7 @@ const struct option record_options[] = {
727 OPT_CALLBACK('G', "cgroup", &record.evlist, "name", 728 OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
728 "monitor event in cgroup name only", 729 "monitor event in cgroup name only",
729 parse_cgroups), 730 parse_cgroups),
731 OPT_STRING('u', "uid", &record.uid_str, "user", "user to profile"),
730 OPT_END() 732 OPT_END()
731}; 733};
732 734
@@ -748,7 +750,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
748 argc = parse_options(argc, argv, record_options, record_usage, 750 argc = parse_options(argc, argv, record_options, record_usage,
749 PARSE_OPT_STOP_AT_NON_OPTION); 751 PARSE_OPT_STOP_AT_NON_OPTION);
750 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 && 752 if (!argc && rec->opts.target_pid == -1 && rec->opts.target_tid == -1 &&
751 !rec->opts.system_wide && !rec->opts.cpu_list) 753 !rec->opts.system_wide && !rec->opts.cpu_list && !rec->uid_str)
752 usage_with_options(record_usage, record_options); 754 usage_with_options(record_usage, record_options);
753 755
754 if (rec->force && rec->append_file) { 756 if (rec->force && rec->append_file) {
@@ -788,11 +790,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
788 goto out_symbol_exit; 790 goto out_symbol_exit;
789 } 791 }
790 792
793 rec->opts.uid = parse_target_uid(rec->uid_str, rec->opts.target_tid,
794 rec->opts.target_pid);
795 if (rec->uid_str != NULL && rec->opts.uid == UINT_MAX - 1)
796 goto out_free_fd;
797
791 if (rec->opts.target_pid != -1) 798 if (rec->opts.target_pid != -1)
792 rec->opts.target_tid = rec->opts.target_pid; 799 rec->opts.target_tid = rec->opts.target_pid;
793 800
794 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid, 801 if (perf_evlist__create_maps(evsel_list, rec->opts.target_pid,
795 rec->opts.target_tid, rec->opts.cpu_list) < 0) 802 rec->opts.target_tid, rec->opts.uid,
803 rec->opts.cpu_list) < 0)
796 usage_with_options(record_usage, record_options); 804 usage_with_options(record_usage, record_options);
797 805
798 list_for_each_entry(pos, &evsel_list->entries, node) { 806 list_for_each_entry(pos, &evsel_list->entries, node) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f5d2a63eba66..459b8620a5d9 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1201,7 +1201,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
1201 if (target_pid != -1) 1201 if (target_pid != -1)
1202 target_tid = target_pid; 1202 target_tid = target_pid;
1203 1203
1204 evsel_list->threads = thread_map__new(target_pid, target_tid); 1204 evsel_list->threads = thread_map__new(target_pid, target_tid, UINT_MAX);
1205 if (evsel_list->threads == NULL) { 1205 if (evsel_list->threads == NULL) {
1206 pr_err("Problems finding threads of monitor\n"); 1206 pr_err("Problems finding threads of monitor\n");
1207 usage_with_options(stat_usage, options); 1207 usage_with_options(stat_usage, options);
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 3854e869dce1..3ce709e97462 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -276,7 +276,7 @@ static int test__open_syscall_event(void)
276 return -1; 276 return -1;
277 } 277 }
278 278
279 threads = thread_map__new(-1, getpid()); 279 threads = thread_map__new(-1, getpid(), UINT_MAX);
280 if (threads == NULL) { 280 if (threads == NULL) {
281 pr_debug("thread_map__new\n"); 281 pr_debug("thread_map__new\n");
282 return -1; 282 return -1;
@@ -342,7 +342,7 @@ static int test__open_syscall_event_on_all_cpus(void)
342 return -1; 342 return -1;
343 } 343 }
344 344
345 threads = thread_map__new(-1, getpid()); 345 threads = thread_map__new(-1, getpid(), UINT_MAX);
346 if (threads == NULL) { 346 if (threads == NULL) {
347 pr_debug("thread_map__new\n"); 347 pr_debug("thread_map__new\n");
348 return -1; 348 return -1;
@@ -490,7 +490,7 @@ static int test__basic_mmap(void)
490 expected_nr_events[i] = random() % 257; 490 expected_nr_events[i] = random() % 257;
491 } 491 }
492 492
493 threads = thread_map__new(-1, getpid()); 493 threads = thread_map__new(-1, getpid(), UINT_MAX);
494 if (threads == NULL) { 494 if (threads == NULL) {
495 pr_debug("thread_map__new\n"); 495 pr_debug("thread_map__new\n");
496 return -1; 496 return -1;
@@ -1054,7 +1054,7 @@ static int test__PERF_RECORD(void)
1054 * we're monitoring, the one forked there. 1054 * we're monitoring, the one forked there.
1055 */ 1055 */
1056 err = perf_evlist__create_maps(evlist, opts.target_pid, 1056 err = perf_evlist__create_maps(evlist, opts.target_pid,
1057 opts.target_tid, opts.cpu_list); 1057 opts.target_tid, UINT_MAX, opts.cpu_list);
1058 if (err < 0) { 1058 if (err < 0) {
1059 pr_debug("Not enough memory to create thread/cpu maps\n"); 1059 pr_debug("Not enough memory to create thread/cpu maps\n");
1060 goto out_delete_evlist; 1060 goto out_delete_evlist;
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 8f80df896038..e8b033c074f9 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -64,7 +64,6 @@
64#include <linux/unistd.h> 64#include <linux/unistd.h>
65#include <linux/types.h> 65#include <linux/types.h>
66 66
67
68void get_term_dimensions(struct winsize *ws) 67void get_term_dimensions(struct winsize *ws)
69{ 68{
70 char *s = getenv("LINES"); 69 char *s = getenv("LINES");
@@ -537,10 +536,20 @@ static void perf_top__sort_new_samples(void *arg)
537 536
538static void *display_thread_tui(void *arg) 537static void *display_thread_tui(void *arg)
539{ 538{
539 struct perf_evsel *pos;
540 struct perf_top *top = arg; 540 struct perf_top *top = arg;
541 const char *help = "For a higher level overview, try: perf top --sort comm,dso"; 541 const char *help = "For a higher level overview, try: perf top --sort comm,dso";
542 542
543 perf_top__sort_new_samples(top); 543 perf_top__sort_new_samples(top);
544
545 /*
546 * Initialize the uid_filter_str, in the future the TUI will allow
547 * Zooming in/out UIDs. For now juse use whatever the user passed
548 * via --uid.
549 */
550 list_for_each_entry(pos, &top->evlist->entries, node)
551 pos->hists.uid_filter_str = top->uid_str;
552
544 perf_evlist__tui_browse_hists(top->evlist, help, 553 perf_evlist__tui_browse_hists(top->evlist, help,
545 perf_top__sort_new_samples, 554 perf_top__sort_new_samples,
546 top, top->delay_secs); 555 top, top->delay_secs);
@@ -949,7 +958,7 @@ static int __cmd_top(struct perf_top *top)
949 if (ret) 958 if (ret)
950 goto out_delete; 959 goto out_delete;
951 960
952 if (top->target_tid != -1) 961 if (top->target_tid != -1 || top->uid != UINT_MAX)
953 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, 962 perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
954 perf_event__process, 963 perf_event__process,
955 &top->session->host_machine); 964 &top->session->host_machine);
@@ -1089,6 +1098,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1089 .delay_secs = 2, 1098 .delay_secs = 2,
1090 .target_pid = -1, 1099 .target_pid = -1,
1091 .target_tid = -1, 1100 .target_tid = -1,
1101 .uid = UINT_MAX,
1092 .freq = 1000, /* 1 KHz */ 1102 .freq = 1000, /* 1 KHz */
1093 .sample_id_all_avail = true, 1103 .sample_id_all_avail = true,
1094 .mmap_pages = 128, 1104 .mmap_pages = 128,
@@ -1162,6 +1172,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1162 "Display raw encoding of assembly instructions (default)"), 1172 "Display raw encoding of assembly instructions (default)"),
1163 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", 1173 OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
1164 "Specify disassembler style (e.g. -M intel for intel syntax)"), 1174 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1175 OPT_STRING('u', "uid", &top.uid_str, "user", "user to profile"),
1165 OPT_END() 1176 OPT_END()
1166 }; 1177 };
1167 1178
@@ -1187,6 +1198,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1187 1198
1188 setup_browser(false); 1199 setup_browser(false);
1189 1200
1201 top.uid = parse_target_uid(top.uid_str, top.target_tid, top.target_pid);
1202 if (top.uid_str != NULL && top.uid == UINT_MAX - 1)
1203 goto out_delete_evlist;
1204
1190 /* CPU and PID are mutually exclusive */ 1205 /* CPU and PID are mutually exclusive */
1191 if (top.target_tid > 0 && top.cpu_list) { 1206 if (top.target_tid > 0 && top.cpu_list) {
1192 printf("WARNING: PID switch overriding CPU\n"); 1207 printf("WARNING: PID switch overriding CPU\n");
@@ -1198,7 +1213,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1198 top.target_tid = top.target_pid; 1213 top.target_tid = top.target_pid;
1199 1214
1200 if (perf_evlist__create_maps(top.evlist, top.target_pid, 1215 if (perf_evlist__create_maps(top.evlist, top.target_pid,
1201 top.target_tid, top.cpu_list) < 0) 1216 top.target_tid, top.uid, top.cpu_list) < 0)
1202 usage_with_options(top_usage, options); 1217 usage_with_options(top_usage, options);
1203 1218
1204 if (!top.evlist->nr_entries && 1219 if (!top.evlist->nr_entries &&
@@ -1262,6 +1277,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1262 1277
1263 status = __cmd_top(&top); 1278 status = __cmd_top(&top);
1264 1279
1280out_delete_evlist:
1265 perf_evlist__delete(top.evlist); 1281 perf_evlist__delete(top.evlist);
1266 1282
1267 return status; 1283 return status;
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 64f8bee31ced..92af1688bae4 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -188,6 +188,7 @@ void pthread__unblock_sigwinch(void);
188struct perf_record_opts { 188struct perf_record_opts {
189 pid_t target_pid; 189 pid_t target_pid;
190 pid_t target_tid; 190 pid_t target_tid;
191 uid_t uid;
191 bool call_graph; 192 bool call_graph;
192 bool group; 193 bool group;
193 bool inherit_stat; 194 bool inherit_stat;
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 6893eec693ab..adc72f09914d 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -166,6 +166,17 @@ out:
166 return cpus; 166 return cpus;
167} 167}
168 168
169size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
170{
171 int i;
172 size_t printed = fprintf(fp, "%d cpu%s: ",
173 map->nr, map->nr > 1 ? "s" : "");
174 for (i = 0; i < map->nr; ++i)
175 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
176
177 return printed + fprintf(fp, "\n");
178}
179
169struct cpu_map *cpu_map__dummy_new(void) 180struct cpu_map *cpu_map__dummy_new(void)
170{ 181{
171 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int)); 182 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 072c0a374794..c41518573c6a 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -1,6 +1,8 @@
1#ifndef __PERF_CPUMAP_H 1#ifndef __PERF_CPUMAP_H
2#define __PERF_CPUMAP_H 2#define __PERF_CPUMAP_H
3 3
4#include <stdio.h>
5
4struct cpu_map { 6struct cpu_map {
5 int nr; 7 int nr;
6 int map[]; 8 int map[];
@@ -10,4 +12,6 @@ struct cpu_map *cpu_map__new(const char *cpu_list);
10struct cpu_map *cpu_map__dummy_new(void); 12struct cpu_map *cpu_map__dummy_new(void);
11void cpu_map__delete(struct cpu_map *map); 13void cpu_map__delete(struct cpu_map *map);
12 14
15size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
16
13#endif /* __PERF_CPUMAP_H */ 17#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 3f16e08a5c8d..a6d50e376257 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -594,14 +594,14 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
594} 594}
595 595
596int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 596int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
597 pid_t target_tid, const char *cpu_list) 597 pid_t target_tid, uid_t uid, const char *cpu_list)
598{ 598{
599 evlist->threads = thread_map__new(target_pid, target_tid); 599 evlist->threads = thread_map__new(target_pid, target_tid, uid);
600 600
601 if (evlist->threads == NULL) 601 if (evlist->threads == NULL)
602 return -1; 602 return -1;
603 603
604 if (cpu_list == NULL && target_tid != -1) 604 if (uid != UINT_MAX || (cpu_list == NULL && target_tid != -1))
605 evlist->cpus = cpu_map__dummy_new(); 605 evlist->cpus = cpu_map__dummy_new();
606 else 606 else
607 evlist->cpus = cpu_map__new(cpu_list); 607 evlist->cpus = cpu_map__new(cpu_list);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 8922aeed0467..9c516607ce20 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -107,7 +107,7 @@ static inline void perf_evlist__set_maps(struct perf_evlist *evlist,
107} 107}
108 108
109int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, 109int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
110 pid_t target_tid, const char *cpu_list); 110 pid_t tid, uid_t uid, const char *cpu_list);
111void perf_evlist__delete_maps(struct perf_evlist *evlist); 111void perf_evlist__delete_maps(struct perf_evlist *evlist);
112int perf_evlist__set_filters(struct perf_evlist *evlist); 112int perf_evlist__set_filters(struct perf_evlist *evlist);
113 113
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 3e7e0b09c12c..ecd7f4dd7eea 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2105,7 +2105,7 @@ int perf_event__synthesize_event_type(struct perf_tool *tool,
2105 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1); 2105 strncpy(ev.event_type.event_type.name, name, MAX_EVENT_NAME - 1);
2106 2106
2107 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE; 2107 ev.event_type.header.type = PERF_RECORD_HEADER_EVENT_TYPE;
2108 size = strlen(name); 2108 size = strlen(ev.event_type.event_type.name);
2109 size = ALIGN(size, sizeof(u64)); 2109 size = ALIGN(size, sizeof(u64));
2110 ev.event_type.header.size = sizeof(ev.event_type) - 2110 ev.event_type.header.size = sizeof(ev.event_type) -
2111 (sizeof(ev.event_type.event_type.name) - size); 2111 (sizeof(ev.event_type.event_type.name) - size);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index f55f0a8d1f81..0d486135d10f 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -55,6 +55,7 @@ struct hists {
55 u64 nr_entries; 55 u64 nr_entries;
56 const struct thread *thread_filter; 56 const struct thread *thread_filter;
57 const struct dso *dso_filter; 57 const struct dso *dso_filter;
58 const char *uid_filter_str;
58 pthread_mutex_t lock; 59 pthread_mutex_t lock;
59 struct events_stats stats; 60 struct events_stats stats;
60 u64 event_stream; 61 u64 event_stream;
diff --git a/tools/perf/util/include/asm/dwarf2.h b/tools/perf/util/include/asm/dwarf2.h
index bb4198e7837a..afe38199e922 100644
--- a/tools/perf/util/include/asm/dwarf2.h
+++ b/tools/perf/util/include/asm/dwarf2.h
@@ -2,10 +2,12 @@
2#ifndef PERF_DWARF2_H 2#ifndef PERF_DWARF2_H
3#define PERF_DWARF2_H 3#define PERF_DWARF2_H
4 4
5/* dwarf2.h ... dummy header file for including arch/x86/lib/memcpy_64.S */ 5/* dwarf2.h ... dummy header file for including arch/x86/lib/mem{cpy,set}_64.S */
6 6
7#define CFI_STARTPROC 7#define CFI_STARTPROC
8#define CFI_ENDPROC 8#define CFI_ENDPROC
9#define CFI_REMEMBER_STATE
10#define CFI_RESTORE_STATE
9 11
10#endif /* PERF_DWARF2_H */ 12#endif /* PERF_DWARF2_H */
11 13
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eb25900e2211..b9bbdd236357 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -19,7 +19,6 @@
19 * 19 *
20 */ 20 */
21 21
22#define _GNU_SOURCE
23#include <sys/utsname.h> 22#include <sys/utsname.h>
24#include <sys/types.h> 23#include <sys/types.h>
25#include <sys/stat.h> 24#include <sys/stat.h>
@@ -33,7 +32,6 @@
33#include <limits.h> 32#include <limits.h>
34#include <elf.h> 33#include <elf.h>
35 34
36#undef _GNU_SOURCE
37#include "util.h" 35#include "util.h"
38#include "event.h" 36#include "event.h"
39#include "string.h" 37#include "string.h"
@@ -1731,7 +1729,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1731 } 1729 }
1732 1730
1733 ret = 0; 1731 ret = 0;
1734 printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 1732 printf("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
1735 for (i = 0; i < ntevs; i++) { 1733 for (i = 0; i < ntevs; i++) {
1736 tev = &tevs[i]; 1734 tev = &tevs[i];
1737 if (pev->event) 1735 if (pev->event)
@@ -1786,7 +1784,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
1786 1784
1787 if (ret >= 0) { 1785 if (ret >= 0) {
1788 /* Show how to use the event. */ 1786 /* Show how to use the event. */
1789 printf("\nYou can now use it on all perf tools, such as:\n\n"); 1787 printf("\nYou can now use it in all perf tools, such as:\n\n");
1790 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1788 printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
1791 tev->event); 1789 tev->event);
1792 } 1790 }
@@ -1961,7 +1959,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
1961 goto error; 1959 goto error;
1962 } 1960 }
1963 1961
1964 printf("Remove event: %s\n", ent->s); 1962 printf("Removed event: %s\n", ent->s);
1965 return 0; 1963 return 0;
1966error: 1964error:
1967 pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1965 pr_warning("Failed to delete event: %s\n", strerror(-ret));
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 9dd47a4f2596..e03b58a48424 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -425,14 +425,14 @@ struct pyrf_thread_map {
425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, 425static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
426 PyObject *args, PyObject *kwargs) 426 PyObject *args, PyObject *kwargs)
427{ 427{
428 static char *kwlist[] = { "pid", "tid", NULL }; 428 static char *kwlist[] = { "pid", "tid", "uid", NULL };
429 int pid = -1, tid = -1; 429 int pid = -1, tid = -1, uid = UINT_MAX;
430 430
431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", 431 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii",
432 kwlist, &pid, &tid)) 432 kwlist, &pid, &tid, &uid))
433 return -1; 433 return -1;
434 434
435 pthreads->threads = thread_map__new(pid, tid); 435 pthreads->threads = thread_map__new(pid, tid, uid);
436 if (pthreads->threads == NULL) 436 if (pthreads->threads == NULL)
437 return -1; 437 return -1;
438 return 0; 438 return 0;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 215d50f2042e..0975438c3e72 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,4 +1,3 @@
1#define _GNU_SOURCE
2#include <ctype.h> 1#include <ctype.h>
3#include <dirent.h> 2#include <dirent.h>
4#include <errno.h> 3#include <errno.h>
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index a5df131b77c3..3d4b6c5931b9 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -1,6 +1,11 @@
1#include <dirent.h> 1#include <dirent.h>
2#include <limits.h>
3#include <stdbool.h>
2#include <stdlib.h> 4#include <stdlib.h>
3#include <stdio.h> 5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
4#include "thread_map.h" 9#include "thread_map.h"
5 10
6/* Skip "." and ".." directories */ 11/* Skip "." and ".." directories */
@@ -23,7 +28,7 @@ struct thread_map *thread_map__new_by_pid(pid_t pid)
23 sprintf(name, "/proc/%d/task", pid); 28 sprintf(name, "/proc/%d/task", pid);
24 items = scandir(name, &namelist, filter, NULL); 29 items = scandir(name, &namelist, filter, NULL);
25 if (items <= 0) 30 if (items <= 0)
26 return NULL; 31 return NULL;
27 32
28 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 33 threads = malloc(sizeof(*threads) + sizeof(pid_t) * items);
29 if (threads != NULL) { 34 if (threads != NULL) {
@@ -51,10 +56,99 @@ struct thread_map *thread_map__new_by_tid(pid_t tid)
51 return threads; 56 return threads;
52} 57}
53 58
54struct thread_map *thread_map__new(pid_t pid, pid_t tid) 59struct thread_map *thread_map__new_by_uid(uid_t uid)
60{
61 DIR *proc;
62 int max_threads = 32, items, i;
63 char path[256];
64 struct dirent dirent, *next, **namelist = NULL;
65 struct thread_map *threads = malloc(sizeof(*threads) +
66 max_threads * sizeof(pid_t));
67 if (threads == NULL)
68 goto out;
69
70 proc = opendir("/proc");
71 if (proc == NULL)
72 goto out_free_threads;
73
74 threads->nr = 0;
75
76 while (!readdir_r(proc, &dirent, &next) && next) {
77 char *end;
78 bool grow = false;
79 struct stat st;
80 pid_t pid = strtol(dirent.d_name, &end, 10);
81
82 if (*end) /* only interested in proper numerical dirents */
83 continue;
84
85 snprintf(path, sizeof(path), "/proc/%s", dirent.d_name);
86
87 if (stat(path, &st) != 0)
88 continue;
89
90 if (st.st_uid != uid)
91 continue;
92
93 snprintf(path, sizeof(path), "/proc/%d/task", pid);
94 items = scandir(path, &namelist, filter, NULL);
95 if (items <= 0)
96 goto out_free_closedir;
97
98 while (threads->nr + items >= max_threads) {
99 max_threads *= 2;
100 grow = true;
101 }
102
103 if (grow) {
104 struct thread_map *tmp;
105
106 tmp = realloc(threads, (sizeof(*threads) +
107 max_threads * sizeof(pid_t)));
108 if (tmp == NULL)
109 goto out_free_namelist;
110
111 threads = tmp;
112 }
113
114 for (i = 0; i < items; i++)
115 threads->map[threads->nr + i] = atoi(namelist[i]->d_name);
116
117 for (i = 0; i < items; i++)
118 free(namelist[i]);
119 free(namelist);
120
121 threads->nr += items;
122 }
123
124out_closedir:
125 closedir(proc);
126out:
127 return threads;
128
129out_free_threads:
130 free(threads);
131 return NULL;
132
133out_free_namelist:
134 for (i = 0; i < items; i++)
135 free(namelist[i]);
136 free(namelist);
137
138out_free_closedir:
139 free(threads);
140 threads = NULL;
141 goto out_closedir;
142}
143
144struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
55{ 145{
56 if (pid != -1) 146 if (pid != -1)
57 return thread_map__new_by_pid(pid); 147 return thread_map__new_by_pid(pid);
148
149 if (tid == -1 && uid != UINT_MAX)
150 return thread_map__new_by_uid(uid);
151
58 return thread_map__new_by_tid(tid); 152 return thread_map__new_by_tid(tid);
59} 153}
60 154
@@ -62,3 +156,14 @@ void thread_map__delete(struct thread_map *threads)
62{ 156{
63 free(threads); 157 free(threads);
64} 158}
159
160size_t thread_map__fprintf(struct thread_map *threads, FILE *fp)
161{
162 int i;
163 size_t printed = fprintf(fp, "%d thread%s: ",
164 threads->nr, threads->nr > 1 ? "s" : "");
165 for (i = 0; i < threads->nr; ++i)
166 printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]);
167
168 return printed + fprintf(fp, "\n");
169}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 3cb907311409..c75ddbaba005 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -2,6 +2,7 @@
2#define __PERF_THREAD_MAP_H 2#define __PERF_THREAD_MAP_H
3 3
4#include <sys/types.h> 4#include <sys/types.h>
5#include <stdio.h>
5 6
6struct thread_map { 7struct thread_map {
7 int nr; 8 int nr;
@@ -10,6 +11,10 @@ struct thread_map {
10 11
11struct thread_map *thread_map__new_by_pid(pid_t pid); 12struct thread_map *thread_map__new_by_pid(pid_t pid);
12struct thread_map *thread_map__new_by_tid(pid_t tid); 13struct thread_map *thread_map__new_by_tid(pid_t tid);
13struct thread_map *thread_map__new(pid_t pid, pid_t tid); 14struct thread_map *thread_map__new_by_uid(uid_t uid);
15struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid);
14void thread_map__delete(struct thread_map *threads); 16void thread_map__delete(struct thread_map *threads);
17
18size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
19
15#endif /* __PERF_THREAD_MAP_H */ 20#endif /* __PERF_THREAD_MAP_H */
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 500471dffa4f..e4370ca27193 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -75,6 +75,9 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
75 else if (top->target_tid != -1) 75 else if (top->target_tid != -1)
76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d", 76 ret += SNPRINTF(bf + ret, size - ret, " (target_tid: %d",
77 top->target_tid); 77 top->target_tid);
78 else if (top->uid_str != NULL)
79 ret += SNPRINTF(bf + ret, size - ret, " (uid: %s",
80 top->uid_str);
78 else 81 else
79 ret += SNPRINTF(bf + ret, size - ret, " (all"); 82 ret += SNPRINTF(bf + ret, size - ret, " (all");
80 83
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index a248f3c2c60d..def3e53e0fe0 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -24,6 +24,7 @@ struct perf_top {
24 int print_entries, count_filter, delay_secs; 24 int print_entries, count_filter, delay_secs;
25 int freq; 25 int freq;
26 pid_t target_pid, target_tid; 26 pid_t target_pid, target_tid;
27 uid_t uid;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool system_wide; 29 bool system_wide;
29 bool use_tui, use_stdio; 30 bool use_tui, use_stdio;
@@ -45,6 +46,7 @@ struct perf_top {
45 int realtime_prio; 46 int realtime_prio;
46 int sym_pcnt_filter; 47 int sym_pcnt_filter;
47 const char *sym_filter; 48 const char *sym_filter;
49 const char *uid_str;
48}; 50};
49 51
50size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 52size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc9ee95..1a8d4dc4f386 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -21,14 +21,13 @@
21 * The parts for function graph printing was taken and modified from the 21 * The parts for function graph printing was taken and modified from the
22 * Linux Kernel that were written by Frederic Weisbecker. 22 * Linux Kernel that were written by Frederic Weisbecker.
23 */ 23 */
24#define _GNU_SOURCE 24
25#include <stdio.h> 25#include <stdio.h>
26#include <stdlib.h> 26#include <stdlib.h>
27#include <string.h> 27#include <string.h>
28#include <ctype.h> 28#include <ctype.h>
29#include <errno.h> 29#include <errno.h>
30 30
31#undef _GNU_SOURCE
32#include "../perf.h" 31#include "../perf.h"
33#include "util.h" 32#include "util.h"
34#include "trace-event.h" 33#include "trace-event.h"
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 1212a386a033..bfba0490c098 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -1,6 +1,4 @@
1#define _GNU_SOURCE
2#include <stdio.h> 1#include <stdio.h>
3#undef _GNU_SOURCE
4#include "../libslang.h" 2#include "../libslang.h"
5#include <stdlib.h> 3#include <stdlib.h>
6#include <string.h> 4#include <string.h>
@@ -841,6 +839,9 @@ static int hists__browser_title(struct hists *self, char *bf, size_t size,
841 nr_events = convert_unit(nr_events, &unit); 839 nr_events = convert_unit(nr_events, &unit);
842 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name); 840 printed = snprintf(bf, size, "Events: %lu%c %s", nr_events, unit, ev_name);
843 841
842 if (self->uid_filter_str)
843 printed += snprintf(bf + printed, size - printed,
844 ", UID: %s", self->uid_filter_str);
844 if (thread) 845 if (thread)
845 printed += snprintf(bf + printed, size - printed, 846 printed += snprintf(bf + printed, size - printed,
846 ", Thread: %s(%d)", 847 ", Thread: %s(%d)",
diff --git a/tools/perf/util/ui/helpline.c b/tools/perf/util/ui/helpline.c
index 6ef3c5691762..4f48f5901b30 100644
--- a/tools/perf/util/ui/helpline.c
+++ b/tools/perf/util/ui/helpline.c
@@ -1,4 +1,3 @@
1#define _GNU_SOURCE
2#include <stdio.h> 1#include <stdio.h>
3#include <stdlib.h> 2#include <stdlib.h>
4#include <string.h> 3#include <string.h>
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c
index d76d1c0ff98f..d0c013934f30 100644
--- a/tools/perf/util/usage.c
+++ b/tools/perf/util/usage.c
@@ -7,6 +7,7 @@
7 * Copyright (C) Linus Torvalds, 2005 7 * Copyright (C) Linus Torvalds, 2005
8 */ 8 */
9#include "util.h" 9#include "util.h"
10#include "debug.h"
10 11
11static void report(const char *prefix, const char *err, va_list params) 12static void report(const char *prefix, const char *err, va_list params)
12{ 13{
@@ -81,3 +82,41 @@ void warning(const char *warn, ...)
81 warn_routine(warn, params); 82 warn_routine(warn, params);
82 va_end(params); 83 va_end(params);
83} 84}
85
86uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid)
87{
88 struct passwd pwd, *result;
89 char buf[1024];
90
91 if (str == NULL)
92 return UINT_MAX;
93
94 /* CPU and PID are mutually exclusive */
95 if (tid > 0 || pid > 0) {
96 ui__warning("PID/TID switch overriding UID\n");
97 sleep(1);
98 return UINT_MAX;
99 }
100
101 getpwnam_r(str, &pwd, buf, sizeof(buf), &result);
102
103 if (result == NULL) {
104 char *endptr;
105 int uid = strtol(str, &endptr, 10);
106
107 if (*endptr != '\0') {
108 ui__error("Invalid user %s\n", str);
109 return UINT_MAX - 1;
110 }
111
112 getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
113
114 if (result == NULL) {
115 ui__error("Problems obtaining information for user %s\n",
116 str);
117 return UINT_MAX - 1;
118 }
119 }
120
121 return result->pw_uid;
122}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index b9c530cce79a..232d17ef3e60 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -40,7 +40,6 @@
40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1) 40#define decimal_length(x) ((int)(sizeof(x) * 2.56 + 0.5) + 1)
41 41
42#define _ALL_SOURCE 1 42#define _ALL_SOURCE 1
43#define _GNU_SOURCE 1
44#define _BSD_SOURCE 1 43#define _BSD_SOURCE 1
45#define HAS_BOOL 44#define HAS_BOOL
46 45
@@ -246,6 +245,8 @@ struct perf_event_attr;
246 245
247void event_attr_init(struct perf_event_attr *attr); 246void event_attr_init(struct perf_event_attr *attr);
248 247
248uid_t parse_target_uid(const char *str, pid_t tid, pid_t pid);
249
249#define _STR(x) #x 250#define _STR(x) #x
250#define STR(x) _STR(x) 251#define STR(x) _STR(x)
251 252