diff options
author | Ingo Molnar <mingo@elte.hu> | 2012-01-26 06:11:41 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-01-26 06:11:41 -0500 |
commit | 939ddcfa60dabfaed390987bf0103a6654c0fe30 (patch) | |
tree | baa9b89a2b268d99496805f761ab9a00c272c0dc /tools | |
parent | 96070c83b295b31912ad92d3ffb66baec2b86d50 (diff) | |
parent | f8f4b2872295dca88339ec0c403b2217b1197353 (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')
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 |
66 | endif | 66 | endif |
67 | 67 | ||
@@ -104,7 +104,7 @@ endif | |||
104 | 104 | ||
105 | CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) | 105 | CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) |
106 | EXTLIBS = -lpthread -lrt -lelf -lm | 106 | EXTLIBS = -lpthread -lrt -lelf -lm |
107 | ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 | 107 | ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE |
108 | ALL_LDFLAGS = $(LDFLAGS) | 108 | ALL_LDFLAGS = $(LDFLAGS) |
109 | STRIP ?= strip | 109 | STRIP ?= 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 | 171 | BASIC_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.) | ||
174 | BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include | ||
175 | BASIC_LDFLAGS = | 172 | BASIC_LDFLAGS = |
176 | 173 | ||
177 | # Guard against environment variables | 174 | # Guard against environment variables |
@@ -362,8 +359,10 @@ BUILTIN_OBJS += $(OUTPUT)bench/sched-messaging.o | |||
362 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o | 359 | BUILTIN_OBJS += $(OUTPUT)bench/sched-pipe.o |
363 | ifeq ($(RAW_ARCH),x86_64) | 360 | ifeq ($(RAW_ARCH),x86_64) |
364 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o | 361 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy-x86-64-asm.o |
362 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset-x86-64-asm.o | ||
365 | endif | 363 | endif |
366 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o | 364 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o |
365 | BUILTIN_OBJS += $(OUTPUT)bench/mem-memset.o | ||
367 | 366 | ||
368 | BUILTIN_OBJS += $(OUTPUT)builtin-diff.o | 367 | BUILTIN_OBJS += $(OUTPUT)builtin-diff.o |
369 | BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o | 368 | BUILTIN_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 @@ | |||
4 | extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); | 4 | extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); |
5 | extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); | 5 | extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); |
6 | extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); | 6 | extern int bench_mem_memcpy(int argc, const char **argv, const char *prefix __used); |
7 | extern 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 @@ | |||
2 | MEMCPY_FN(__memcpy, | 2 | MEMCPY_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 | |||
6 | MEMCPY_FN(memcpy_c, | ||
7 | "x86-64-movsq", | ||
8 | "movsq-based memcpy() in arch/x86/lib/memcpy_64.S") | ||
9 | |||
10 | MEMCPY_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 | ||
25 | static const char *length_str = "1MB"; | 25 | static const char *length_str = "1MB"; |
26 | static const char *routine = "default"; | 26 | static const char *routine = "default"; |
27 | static int iterations = 1; | ||
27 | static bool use_clock; | 28 | static bool use_clock; |
28 | static int clock_fd; | 29 | static int clock_fd; |
29 | static bool only_prefault; | 30 | static 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 | |||
2 | MEMSET_FN(__memset, | ||
3 | "x86-64-unrolled", | ||
4 | "unrolled memset() in arch/x86/lib/memset_64.S") | ||
5 | |||
6 | MEMSET_FN(memset_c, | ||
7 | "x86-64-stosq", | ||
8 | "movsq-based memset() in arch/x86/lib/memset_64.S") | ||
9 | |||
10 | MEMSET_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 | |||
25 | static const char *length_str = "1MB"; | ||
26 | static const char *routine = "default"; | ||
27 | static int iterations = 1; | ||
28 | static bool use_clock; | ||
29 | static int clock_fd; | ||
30 | static bool only_prefault; | ||
31 | static bool no_prefault; | ||
32 | |||
33 | static 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 | |||
50 | typedef void *(*memset_t)(void *, int, size_t); | ||
51 | |||
52 | struct routine { | ||
53 | const char *name; | ||
54 | const char *desc; | ||
55 | memset_t fn; | ||
56 | }; | ||
57 | |||
58 | static 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 | |||
75 | static const char * const bench_mem_memset_usage[] = { | ||
76 | "perf bench mem memset <options>", | ||
77 | NULL | ||
78 | }; | ||
79 | |||
80 | static struct perf_event_attr clock_attr = { | ||
81 | .type = PERF_TYPE_HARDWARE, | ||
82 | .config = PERF_COUNT_HW_CPU_CYCLES | ||
83 | }; | ||
84 | |||
85 | static 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 | |||
95 | static 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 | |||
106 | static double timeval2double(struct timeval *ts) | ||
107 | { | ||
108 | return (double)ts->tv_sec + | ||
109 | (double)ts->tv_usec / (double)1000000; | ||
110 | } | ||
111 | |||
112 | static 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 | |||
119 | static 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 | |||
139 | static 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 | |||
174 | int 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 | |||
68 | void get_term_dimensions(struct winsize *ws) | 67 | void 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 | ||
538 | static void *display_thread_tui(void *arg) | 537 | static 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 | ||
1280 | out_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); | |||
188 | struct perf_record_opts { | 188 | struct 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 | ||
169 | size_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 | |||
169 | struct cpu_map *cpu_map__dummy_new(void) | 180 | struct 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 | |||
4 | struct cpu_map { | 6 | struct 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); | |||
10 | struct cpu_map *cpu_map__dummy_new(void); | 12 | struct cpu_map *cpu_map__dummy_new(void); |
11 | void cpu_map__delete(struct cpu_map *map); | 13 | void cpu_map__delete(struct cpu_map *map); |
12 | 14 | ||
15 | size_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 | ||
596 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | 596 | int 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 | ||
109 | int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid, | 109 | int 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); |
111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); | 111 | void perf_evlist__delete_maps(struct perf_evlist *evlist); |
112 | int perf_evlist__set_filters(struct perf_evlist *evlist); | 112 | int 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; |
1966 | error: | 1964 | error: |
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 { | |||
425 | static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads, | 425 | static 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 | ||
54 | struct thread_map *thread_map__new(pid_t pid, pid_t tid) | 59 | struct 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 | |||
124 | out_closedir: | ||
125 | closedir(proc); | ||
126 | out: | ||
127 | return threads; | ||
128 | |||
129 | out_free_threads: | ||
130 | free(threads); | ||
131 | return NULL; | ||
132 | |||
133 | out_free_namelist: | ||
134 | for (i = 0; i < items; i++) | ||
135 | free(namelist[i]); | ||
136 | free(namelist); | ||
137 | |||
138 | out_free_closedir: | ||
139 | free(threads); | ||
140 | threads = NULL; | ||
141 | goto out_closedir; | ||
142 | } | ||
143 | |||
144 | struct 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 | |||
160 | size_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 | ||
6 | struct thread_map { | 7 | struct thread_map { |
7 | int nr; | 8 | int nr; |
@@ -10,6 +11,10 @@ struct thread_map { | |||
10 | 11 | ||
11 | struct thread_map *thread_map__new_by_pid(pid_t pid); | 12 | struct thread_map *thread_map__new_by_pid(pid_t pid); |
12 | struct thread_map *thread_map__new_by_tid(pid_t tid); | 13 | struct thread_map *thread_map__new_by_tid(pid_t tid); |
13 | struct thread_map *thread_map__new(pid_t pid, pid_t tid); | 14 | struct thread_map *thread_map__new_by_uid(uid_t uid); |
15 | struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid); | ||
14 | void thread_map__delete(struct thread_map *threads); | 16 | void thread_map__delete(struct thread_map *threads); |
17 | |||
18 | size_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 | ||
50 | size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); | 52 | size_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 | ||
11 | static void report(const char *prefix, const char *err, va_list params) | 12 | static 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 | |||
86 | uid_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 | ||
247 | void event_attr_init(struct perf_event_attr *attr); | 246 | void event_attr_init(struct perf_event_attr *attr); |
248 | 247 | ||
248 | uid_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 | ||