Newer
Older

Frederic Weisbecker
committed
}

Ingo Molnar
committed
int nr_poll;
int group_fd;
static void start_counter(int i, int counter)
struct perf_event_attr *attr;

Ingo Molnar
committed
cpu = profile_cpu;
if (target_pid == -1 && profile_cpu == -1)
cpu = i;
attr = attrs + counter;
attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
if (freq) {
attr->sample_type |= PERF_SAMPLE_PERIOD;
attr->freq = 1;
attr->sample_freq = freq;
}
attr->inherit = (cpu < 0) && inherit;

Ingo Molnar
committed
try_again:
fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0);

Ingo Molnar
committed
if (fd[i][counter] < 0) {
int err = errno;
die("No permission - are you root?\n");

Ingo Molnar
committed
/*
* If it's cycles then fall back to hrtimer
* based cpu-clock-tick sw counter, which
* is always available even if no PMU support:
*/
if (attr->type == PERF_TYPE_HARDWARE
&& attr->config == PERF_COUNT_HW_CPU_CYCLES) {

Ingo Molnar
committed
if (verbose)
warning(" ... trying to fall back to cpu-clock-ticks\n");

Ingo Molnar
committed
attr->type = PERF_TYPE_SOFTWARE;
attr->config = PERF_COUNT_SW_CPU_CLOCK;

Ingo Molnar
committed
goto try_again;
}
printf("\n");
error("perfcounter syscall returned with %d (%s)\n",
fd[i][counter], strerror(err));
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");

Ingo Molnar
committed
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
exit(-1);
}
assert(fd[i][counter] >= 0);
fcntl(fd[i][counter], F_SETFL, O_NONBLOCK);
/*
* First counter acts as the group leader:
*/
if (group && group_fd == -1)
group_fd = fd[i][counter];
event_array[nr_poll].fd = fd[i][counter];
event_array[nr_poll].events = POLLIN;
nr_poll++;
mmap_array[i][counter].counter = counter;
mmap_array[i][counter].prev = 0;
mmap_array[i][counter].mask = mmap_pages*page_size - 1;
mmap_array[i][counter].base = mmap(NULL, (mmap_pages+1)*page_size,
PROT_READ, MAP_SHARED, fd[i][counter], 0);
if (mmap_array[i][counter].base == MAP_FAILED)
die("failed to mmap with %d (%s)\n", errno, strerror(errno));
}
static int __cmd_top(void)
{
pthread_t thread;
int i, counter;
if (target_pid != -1)
event__synthesize_thread(target_pid, event__process);
else
event__synthesize_threads(event__process);
for (i = 0; i < nr_cpus; i++) {
group_fd = -1;

Ingo Molnar
committed
for (counter = 0; counter < nr_counters; counter++)
start_counter(i, counter);

Frederic Weisbecker
committed
/* Wait for a minimal set of events before starting the snapshot */
poll(event_array, nr_poll, 100);
mmap_read();
if (pthread_create(&thread, NULL, display_thread, NULL)) {
printf("Could not create display thread.\n");
exit(-1);
}
if (realtime_prio) {
struct sched_param param;
param.sched_priority = realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
printf("Could not set realtime priority.\n");
exit(-1);
}
}
while (1) {

Frederic Weisbecker
committed
mmap_read();
ret = poll(event_array, nr_poll, 100);
}
return 0;
}
static const char * const top_usage[] = {
"perf top [<options>]",
NULL
};
static const struct option options[] = {
OPT_CALLBACK('e', "event", NULL, "event",
"event selector. use 'perf list' to list available events",
parse_events),
OPT_INTEGER('c', "count", &default_interval,
"event period to sample"),
OPT_INTEGER('p', "pid", &target_pid,
"profile events on existing pid"),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
OPT_INTEGER('C', "CPU", &profile_cpu,
"CPU to profile on"),
OPT_STRING('k', "vmlinux", &vmlinux_name, "file", "vmlinux pathname"),
OPT_INTEGER('m', "mmap-pages", &mmap_pages,
"number of mmap data pages"),
OPT_INTEGER('r', "realtime", &realtime_prio,
"collect data with this RT SCHED_FIFO priority"),
OPT_INTEGER('d', "delay", &delay_secs,
"number of seconds to delay between refreshes"),
OPT_BOOLEAN('D', "dump-symtab", &dump_symtab,
"dump the symbol table used for profiling"),
OPT_INTEGER('f', "count-filter", &count_filter,
"only display functions with more events than this"),
OPT_BOOLEAN('g', "group", &group,
"put the counters into a counter group"),
OPT_BOOLEAN('i', "inherit", &inherit,
"child tasks inherit counters"),

Mike Galbraith
committed
OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
"symbol to annotate - requires -k option"),
OPT_INTEGER('F', "freq", &freq,
OPT_INTEGER('E', "entries", &print_entries,
"display this many functions"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show counter open errors, etc)"),
int cmd_top(int argc, const char **argv, const char *prefix __used)
symbol__init(sizeof(struct sym_entry));
page_size = sysconf(_SC_PAGE_SIZE);
argc = parse_options(argc, argv, options, top_usage, 0);
if (argc)
usage_with_options(top_usage, options);
/* CPU and PID are mutually exclusive */
if (target_pid != -1 && profile_cpu != -1) {
printf("WARNING: PID switch overriding CPU\n");
sleep(1);
profile_cpu = -1;
}
if (!nr_counters)
if (delay_secs < 1)
delay_secs = 1;

Mike Galbraith
committed
parse_source(sym_filter_entry);
/*
* User specified count overrides default frequency.
*/
if (default_interval)
freq = 0;
else if (freq) {
default_interval = freq;
} else {
fprintf(stderr, "frequency and count are zero, aborting\n");
exit(EXIT_FAILURE);
}
/*
* Fill in the ones not specifically initialized via -c:
*/
for (counter = 0; counter < nr_counters; counter++) {
if (attrs[counter].sample_period)
attrs[counter].sample_period = default_interval;