|
@@ -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++)
|