diff options
author | Liming Wang <liming.wang@windriver.com> | 2009-12-31 03:05:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-01-13 04:09:08 -0500 |
commit | 60666c630bdb33983a894b050b588b663f38f368 (patch) | |
tree | ec9eef2f18fe94f7ec6d86ad4fcb046081a47283 /tools | |
parent | 0fb8ee48d9dfff6a0913ceb0be2068d8be203763 (diff) |
perf tools: Fix --pid option for stat
current pid option doesn't work for perf stat. Change it to what
perf record --pid acts as.
Signed-off-by: Liming Wang <liming.wang@windriver.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
LKML-Reference: <1262246750-2191-1-git-send-email-liming.wang@windriver.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-stat.c | 106 |
1 files changed, 61 insertions, 45 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c70d72003557..e8c85d5aec41 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "util/parse-events.h" | 44 | #include "util/parse-events.h" |
45 | #include "util/event.h" | 45 | #include "util/event.h" |
46 | #include "util/debug.h" | 46 | #include "util/debug.h" |
47 | #include "util/header.h" | ||
47 | 48 | ||
48 | #include <sys/prctl.h> | 49 | #include <sys/prctl.h> |
49 | #include <math.h> | 50 | #include <math.h> |
@@ -79,6 +80,8 @@ static int fd[MAX_NR_CPUS][MAX_COUNTERS]; | |||
79 | 80 | ||
80 | static int event_scaled[MAX_COUNTERS]; | 81 | static int event_scaled[MAX_COUNTERS]; |
81 | 82 | ||
83 | static volatile int done = 0; | ||
84 | |||
82 | struct stats | 85 | struct stats |
83 | { | 86 | { |
84 | double n, mean, M2; | 87 | double n, mean, M2; |
@@ -247,61 +250,64 @@ static int run_perf_stat(int argc __used, const char **argv) | |||
247 | unsigned long long t0, t1; | 250 | unsigned long long t0, t1; |
248 | int status = 0; | 251 | int status = 0; |
249 | int counter; | 252 | int counter; |
250 | int pid; | 253 | int pid = target_pid; |
251 | int child_ready_pipe[2], go_pipe[2]; | 254 | int child_ready_pipe[2], go_pipe[2]; |
255 | const bool forks = (target_pid == -1 && argc > 0); | ||
252 | char buf; | 256 | char buf; |
253 | 257 | ||
254 | if (!system_wide) | 258 | if (!system_wide) |
255 | nr_cpus = 1; | 259 | nr_cpus = 1; |
256 | 260 | ||
257 | if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) { | 261 | if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { |
258 | perror("failed to create pipes"); | 262 | perror("failed to create pipes"); |
259 | exit(1); | 263 | exit(1); |
260 | } | 264 | } |
261 | 265 | ||
262 | if ((pid = fork()) < 0) | 266 | if (forks) { |
263 | perror("failed to fork"); | 267 | if ((pid = fork()) < 0) |
268 | perror("failed to fork"); | ||
269 | |||
270 | if (!pid) { | ||
271 | close(child_ready_pipe[0]); | ||
272 | close(go_pipe[1]); | ||
273 | fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); | ||
274 | |||
275 | /* | ||
276 | * Do a dummy execvp to get the PLT entry resolved, | ||
277 | * so we avoid the resolver overhead on the real | ||
278 | * execvp call. | ||
279 | */ | ||
280 | execvp("", (char **)argv); | ||
281 | |||
282 | /* | ||
283 | * Tell the parent we're ready to go | ||
284 | */ | ||
285 | close(child_ready_pipe[1]); | ||
286 | |||
287 | /* | ||
288 | * Wait until the parent tells us to go. | ||
289 | */ | ||
290 | if (read(go_pipe[0], &buf, 1) == -1) | ||
291 | perror("unable to read pipe"); | ||
292 | |||
293 | execvp(argv[0], (char **)argv); | ||
294 | |||
295 | perror(argv[0]); | ||
296 | exit(-1); | ||
297 | } | ||
264 | 298 | ||
265 | if (!pid) { | 299 | child_pid = pid; |
266 | close(child_ready_pipe[0]); | ||
267 | close(go_pipe[1]); | ||
268 | fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); | ||
269 | 300 | ||
270 | /* | 301 | /* |
271 | * Do a dummy execvp to get the PLT entry resolved, | 302 | * Wait for the child to be ready to exec. |
272 | * so we avoid the resolver overhead on the real | ||
273 | * execvp call. | ||
274 | */ | ||
275 | execvp("", (char **)argv); | ||
276 | |||
277 | /* | ||
278 | * Tell the parent we're ready to go | ||
279 | */ | 303 | */ |
280 | close(child_ready_pipe[1]); | 304 | close(child_ready_pipe[1]); |
281 | 305 | close(go_pipe[0]); | |
282 | /* | 306 | if (read(child_ready_pipe[0], &buf, 1) == -1) |
283 | * Wait until the parent tells us to go. | ||
284 | */ | ||
285 | if (read(go_pipe[0], &buf, 1) == -1) | ||
286 | perror("unable to read pipe"); | 307 | perror("unable to read pipe"); |
287 | 308 | close(child_ready_pipe[0]); | |
288 | execvp(argv[0], (char **)argv); | ||
289 | |||
290 | perror(argv[0]); | ||
291 | exit(-1); | ||
292 | } | 309 | } |
293 | 310 | ||
294 | child_pid = pid; | ||
295 | |||
296 | /* | ||
297 | * Wait for the child to be ready to exec. | ||
298 | */ | ||
299 | close(child_ready_pipe[1]); | ||
300 | close(go_pipe[0]); | ||
301 | if (read(child_ready_pipe[0], &buf, 1) == -1) | ||
302 | perror("unable to read pipe"); | ||
303 | close(child_ready_pipe[0]); | ||
304 | |||
305 | for (counter = 0; counter < nr_counters; counter++) | 311 | for (counter = 0; counter < nr_counters; counter++) |
306 | create_perf_stat_counter(counter, pid); | 312 | create_perf_stat_counter(counter, pid); |
307 | 313 | ||
@@ -310,8 +316,12 @@ static int run_perf_stat(int argc __used, const char **argv) | |||
310 | */ | 316 | */ |
311 | t0 = rdclock(); | 317 | t0 = rdclock(); |
312 | 318 | ||
313 | close(go_pipe[1]); | 319 | if (forks) { |
314 | wait(&status); | 320 | close(go_pipe[1]); |
321 | wait(&status); | ||
322 | } else { | ||
323 | while(!done); | ||
324 | } | ||
315 | 325 | ||
316 | t1 = rdclock(); | 326 | t1 = rdclock(); |
317 | 327 | ||
@@ -417,10 +427,13 @@ static void print_stat(int argc, const char **argv) | |||
417 | fflush(stdout); | 427 | fflush(stdout); |
418 | 428 | ||
419 | fprintf(stderr, "\n"); | 429 | fprintf(stderr, "\n"); |
420 | fprintf(stderr, " Performance counter stats for \'%s", argv[0]); | 430 | fprintf(stderr, " Performance counter stats for "); |
421 | 431 | if(target_pid == -1) { | |
422 | for (i = 1; i < argc; i++) | 432 | fprintf(stderr, "\'%s", argv[0]); |
423 | fprintf(stderr, " %s", argv[i]); | 433 | for (i = 1; i < argc; i++) |
434 | fprintf(stderr, " %s", argv[i]); | ||
435 | }else | ||
436 | fprintf(stderr, "task pid \'%d", target_pid); | ||
424 | 437 | ||
425 | fprintf(stderr, "\'"); | 438 | fprintf(stderr, "\'"); |
426 | if (run_count > 1) | 439 | if (run_count > 1) |
@@ -445,6 +458,9 @@ static volatile int signr = -1; | |||
445 | 458 | ||
446 | static void skip_signal(int signo) | 459 | static void skip_signal(int signo) |
447 | { | 460 | { |
461 | if(target_pid != -1) | ||
462 | done = 1; | ||
463 | |||
448 | signr = signo; | 464 | signr = signo; |
449 | } | 465 | } |
450 | 466 | ||
@@ -461,7 +477,7 @@ static void sig_atexit(void) | |||
461 | } | 477 | } |
462 | 478 | ||
463 | static const char * const stat_usage[] = { | 479 | static const char * const stat_usage[] = { |
464 | "perf stat [<options>] <command>", | 480 | "perf stat [<options>] [<command>]", |
465 | NULL | 481 | NULL |
466 | }; | 482 | }; |
467 | 483 | ||
@@ -492,7 +508,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) | |||
492 | 508 | ||
493 | argc = parse_options(argc, argv, options, stat_usage, | 509 | argc = parse_options(argc, argv, options, stat_usage, |
494 | PARSE_OPT_STOP_AT_NON_OPTION); | 510 | PARSE_OPT_STOP_AT_NON_OPTION); |
495 | if (!argc) | 511 | if (!argc && target_pid == -1) |
496 | usage_with_options(stat_usage, options); | 512 | usage_with_options(stat_usage, options); |
497 | if (run_count <= 0) | 513 | if (run_count <= 0) |
498 | usage_with_options(stat_usage, options); | 514 | usage_with_options(stat_usage, options); |