summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/perf/builtin-top.c143
1 files changed, 101 insertions, 42 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 4a9fe228be2..a02fc414601 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -318,7 +318,7 @@ static void show_details(struct sym_entry *syme)
}
/*
- * Symbols will be added here in record_ip and will get out
+ * Symbols will be added here in event__process_sample and will get out
* after decayed.
*/
static LIST_HEAD(active_symbols);
@@ -459,18 +459,18 @@ static void print_sym_table(void)
}
if (nr_counters == 1)
- printf(" samples pcnt");
+ printf(" samples pcnt");
else
- printf(" weight samples pcnt");
+ printf(" weight samples pcnt");
if (verbose)
printf(" RIP ");
- printf(" kernel function\n");
- printf(" %s _______ _____",
+ printf(" function DSO\n");
+ printf(" %s _______ _____",
nr_counters == 1 ? " " : "______");
if (verbose)
- printf(" ________________");
- printf(" _______________\n\n");
+ printf(" ________________");
+ printf(" ________________________________ ________________\n\n");
for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
struct symbol *sym;
@@ -486,16 +486,15 @@ static void print_sym_table(void)
sum_ksamples));
if (nr_counters == 1 || !display_weighted)
- printf("%20.2f - ", syme->weight);
+ printf("%20.2f ", syme->weight);
else
- printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
+ printf("%9.1f %10ld ", syme->weight, syme->snap_count);
percent_color_fprintf(stdout, "%4.1f%%", pcnt);
if (verbose)
- printf(" - %016llx", sym->start);
- printf(" : %s", sym->name);
- if (syme->map->dso->name[0] == '[')
- printf(" \t%s", syme->map->dso->name);
+ printf(" %016llx", sym->start);
+ printf(" %-32s", sym->name);
+ printf(" %s", syme->map->dso->short_name);
printf("\n");
}
}
@@ -818,41 +817,97 @@ static int parse_symbols(void)
return 0;
}
-/*
- * Binary search in the histogram table and record the hit:
- */
-static void record_ip(u64 ip, int counter)
+static void event__process_sample(const event_t *self, int counter)
{
+ u64 ip = self->ip.ip;
struct map *map;
- struct symbol *sym = kernel_maps__find_symbol(ip, &map);
-
- if (sym != NULL) {
- struct sym_entry *syme = dso__sym_priv(map->dso, sym);
-
- if (!syme->skip) {
- syme->count[counter]++;
- record_precise_ip(syme, counter, ip);
- pthread_mutex_lock(&active_symbols_lock);
- if (list_empty(&syme->node) || !syme->node.next)
- __list_insert_active_sym(syme);
- pthread_mutex_unlock(&active_symbols_lock);
+ struct sym_entry *syme;
+ struct symbol *sym;
+
+ switch (self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) {
+ case PERF_RECORD_MISC_USER: {
+ struct thread *thread = threads__findnew(self->ip.pid);
+
+ if (thread == NULL)
return;
+
+ map = thread__find_map(thread, ip);
+ if (map != NULL) {
+ ip = map->map_ip(map, ip);
+ sym = map->dso->find_symbol(map->dso, ip);
+ if (sym == NULL)
+ return;
+ userspace_samples++;
+ break;
}
}
+ /*
+ * If this is outside of all known maps,
+ * and is a negative address, try to look it
+ * up in the kernel dso, as it might be a
+ * vsyscall or vdso (which executes in user-mode).
+ */
+ if ((long long)ip >= 0)
+ return;
+ /* Fall thru */
+ case PERF_RECORD_MISC_KERNEL:
+ sym = kernel_maps__find_symbol(ip, &map);
+ if (sym == NULL)
+ return;
+ break;
+ default:
+ return;
+ }
+
+ syme = dso__sym_priv(map->dso, sym);
- samples--;
+ if (!syme->skip) {
+ syme->count[counter]++;
+ record_precise_ip(syme, counter, ip);
+ pthread_mutex_lock(&active_symbols_lock);
+ if (list_empty(&syme->node) || !syme->node.next)
+ __list_insert_active_sym(syme);
+ pthread_mutex_unlock(&active_symbols_lock);
+ ++samples;
+ return;
+ }
}
-static void process_event(u64 ip, int counter, int user)
+static void event__process_mmap(event_t *self)
{
- samples++;
+ struct thread *thread = threads__findnew(self->mmap.pid);
+
+ if (thread != NULL) {
+ struct map *map = map__new(&self->mmap, NULL, 0,
+ sizeof(struct sym_entry),
+ symbol_filter);
+ if (map != NULL)
+ thread__insert_map(thread, map);
+ }
+}
- if (user) {
- userspace_samples++;
- return;
+static void event__process_comm(event_t *self)
+{
+ struct thread *thread = threads__findnew(self->comm.pid);
+
+ if (thread != NULL)
+ thread__set_comm(thread, self->comm.comm);
+}
+
+static int event__process(event_t *event)
+{
+ switch (event->header.type) {
+ case PERF_RECORD_COMM:
+ event__process_comm(event);
+ break;
+ case PERF_RECORD_MMAP:
+ event__process_mmap(event);
+ break;
+ default:
+ break;
}
- record_ip(ip, counter);
+ return 0;
}
struct mmap_data {
@@ -925,13 +980,11 @@ static void mmap_read_counter(struct mmap_data *md)
event = &event_copy;
}
+ if (event->header.type == PERF_RECORD_SAMPLE)
+ event__process_sample(event, md->counter);
+ else
+ event__process(event);
old += size;
-
- if (event->header.type == PERF_RECORD_SAMPLE) {
- int user =
- (event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK) == PERF_RECORD_MISC_USER;
- process_event(event->ip.ip, md->counter, user);
- }
}
md->prev = old;
@@ -973,6 +1026,7 @@ static void start_counter(int i, int counter)
}
attr->inherit = (cpu < 0) && inherit;
+ attr->mmap = 1;
try_again:
fd[i][counter] = sys_perf_event_open(attr, target_pid, cpu, group_fd, 0);
@@ -1031,6 +1085,11 @@ static int __cmd_top(void)
int i, counter;
int ret;
+ 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;
for (counter = 0; counter < nr_counters; counter++)