mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-09 06:43:09 +00:00
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>
This commit is contained in:
parent
0fb8ee48d9
commit
60666c630b
@ -44,6 +44,7 @@
|
|||||||
#include "util/parse-events.h"
|
#include "util/parse-events.h"
|
||||||
#include "util/event.h"
|
#include "util/event.h"
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
|
#include "util/header.h"
|
||||||
|
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@ -79,6 +80,8 @@ static int fd[MAX_NR_CPUS][MAX_COUNTERS];
|
|||||||
|
|
||||||
static int event_scaled[MAX_COUNTERS];
|
static int event_scaled[MAX_COUNTERS];
|
||||||
|
|
||||||
|
static volatile int done = 0;
|
||||||
|
|
||||||
struct stats
|
struct stats
|
||||||
{
|
{
|
||||||
double n, mean, M2;
|
double n, mean, M2;
|
||||||
@ -247,61 +250,64 @@ static int run_perf_stat(int argc __used, const char **argv)
|
|||||||
unsigned long long t0, t1;
|
unsigned long long t0, t1;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
int counter;
|
int counter;
|
||||||
int pid;
|
int pid = target_pid;
|
||||||
int child_ready_pipe[2], go_pipe[2];
|
int child_ready_pipe[2], go_pipe[2];
|
||||||
|
const bool forks = (target_pid == -1 && argc > 0);
|
||||||
char buf;
|
char buf;
|
||||||
|
|
||||||
if (!system_wide)
|
if (!system_wide)
|
||||||
nr_cpus = 1;
|
nr_cpus = 1;
|
||||||
|
|
||||||
if (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0) {
|
if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
|
||||||
perror("failed to create pipes");
|
perror("failed to create pipes");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pid = fork()) < 0)
|
if (forks) {
|
||||||
perror("failed to fork");
|
if ((pid = fork()) < 0)
|
||||||
|
perror("failed to fork");
|
||||||
|
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
close(child_ready_pipe[0]);
|
close(child_ready_pipe[0]);
|
||||||
close(go_pipe[1]);
|
close(go_pipe[1]);
|
||||||
fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
|
fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do a dummy execvp to get the PLT entry resolved,
|
||||||
|
* so we avoid the resolver overhead on the real
|
||||||
|
* execvp call.
|
||||||
|
*/
|
||||||
|
execvp("", (char **)argv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell the parent we're ready to go
|
||||||
|
*/
|
||||||
|
close(child_ready_pipe[1]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait until the parent tells us to go.
|
||||||
|
*/
|
||||||
|
if (read(go_pipe[0], &buf, 1) == -1)
|
||||||
|
perror("unable to read pipe");
|
||||||
|
|
||||||
|
execvp(argv[0], (char **)argv);
|
||||||
|
|
||||||
|
perror(argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
child_pid = pid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do a dummy execvp to get the PLT entry resolved,
|
* Wait for the child to be ready to exec.
|
||||||
* so we avoid the resolver overhead on the real
|
|
||||||
* execvp call.
|
|
||||||
*/
|
|
||||||
execvp("", (char **)argv);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tell the parent we're ready to go
|
|
||||||
*/
|
*/
|
||||||
close(child_ready_pipe[1]);
|
close(child_ready_pipe[1]);
|
||||||
|
close(go_pipe[0]);
|
||||||
/*
|
if (read(child_ready_pipe[0], &buf, 1) == -1)
|
||||||
* Wait until the parent tells us to go.
|
|
||||||
*/
|
|
||||||
if (read(go_pipe[0], &buf, 1) == -1)
|
|
||||||
perror("unable to read pipe");
|
perror("unable to read pipe");
|
||||||
|
close(child_ready_pipe[0]);
|
||||||
execvp(argv[0], (char **)argv);
|
|
||||||
|
|
||||||
perror(argv[0]);
|
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child_pid = pid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait for the child to be ready to exec.
|
|
||||||
*/
|
|
||||||
close(child_ready_pipe[1]);
|
|
||||||
close(go_pipe[0]);
|
|
||||||
if (read(child_ready_pipe[0], &buf, 1) == -1)
|
|
||||||
perror("unable to read pipe");
|
|
||||||
close(child_ready_pipe[0]);
|
|
||||||
|
|
||||||
for (counter = 0; counter < nr_counters; counter++)
|
for (counter = 0; counter < nr_counters; counter++)
|
||||||
create_perf_stat_counter(counter, pid);
|
create_perf_stat_counter(counter, pid);
|
||||||
|
|
||||||
@ -310,8 +316,12 @@ static int run_perf_stat(int argc __used, const char **argv)
|
|||||||
*/
|
*/
|
||||||
t0 = rdclock();
|
t0 = rdclock();
|
||||||
|
|
||||||
close(go_pipe[1]);
|
if (forks) {
|
||||||
wait(&status);
|
close(go_pipe[1]);
|
||||||
|
wait(&status);
|
||||||
|
} else {
|
||||||
|
while(!done);
|
||||||
|
}
|
||||||
|
|
||||||
t1 = rdclock();
|
t1 = rdclock();
|
||||||
|
|
||||||
@ -417,10 +427,13 @@ static void print_stat(int argc, const char **argv)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, " Performance counter stats for \'%s", argv[0]);
|
fprintf(stderr, " Performance counter stats for ");
|
||||||
|
if(target_pid == -1) {
|
||||||
for (i = 1; i < argc; i++)
|
fprintf(stderr, "\'%s", argv[0]);
|
||||||
fprintf(stderr, " %s", argv[i]);
|
for (i = 1; i < argc; i++)
|
||||||
|
fprintf(stderr, " %s", argv[i]);
|
||||||
|
}else
|
||||||
|
fprintf(stderr, "task pid \'%d", target_pid);
|
||||||
|
|
||||||
fprintf(stderr, "\'");
|
fprintf(stderr, "\'");
|
||||||
if (run_count > 1)
|
if (run_count > 1)
|
||||||
@ -445,6 +458,9 @@ static volatile int signr = -1;
|
|||||||
|
|
||||||
static void skip_signal(int signo)
|
static void skip_signal(int signo)
|
||||||
{
|
{
|
||||||
|
if(target_pid != -1)
|
||||||
|
done = 1;
|
||||||
|
|
||||||
signr = signo;
|
signr = signo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +477,7 @@ static void sig_atexit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char * const stat_usage[] = {
|
static const char * const stat_usage[] = {
|
||||||
"perf stat [<options>] <command>",
|
"perf stat [<options>] [<command>]",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -492,7 +508,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
|||||||
|
|
||||||
argc = parse_options(argc, argv, options, stat_usage,
|
argc = parse_options(argc, argv, options, stat_usage,
|
||||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
if (!argc)
|
if (!argc && target_pid == -1)
|
||||||
usage_with_options(stat_usage, options);
|
usage_with_options(stat_usage, options);
|
||||||
if (run_count <= 0)
|
if (run_count <= 0)
|
||||||
usage_with_options(stat_usage, options);
|
usage_with_options(stat_usage, options);
|
||||||
|
Loading…
Reference in New Issue
Block a user