aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN21
-rw-r--r--tools/perf/util/dso.c10
-rw-r--r--tools/perf/util/dso.h3
-rw-r--r--tools/perf/util/evlist.c12
-rw-r--r--tools/perf/util/evsel.c6
-rw-r--r--tools/perf/util/header.c17
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/hist.c96
-rw-r--r--tools/perf/util/hist.h16
-rw-r--r--tools/perf/util/map.c1
-rw-r--r--tools/perf/util/parse-events.c4
-rw-r--r--tools/perf/util/session.h1
-rw-r--r--tools/perf/util/setup.py5
-rw-r--r--tools/perf/util/sort.c128
-rw-r--r--tools/perf/util/sort.h36
-rw-r--r--tools/perf/util/stat.c2
-rw-r--r--tools/perf/util/symbol.c1
-rw-r--r--tools/perf/util/thread.c4
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/top.c23
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/util.h6
-rw-r--r--tools/perf/util/vdso.c2
23 files changed, 240 insertions, 158 deletions
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 055fef34b6f6..15a77b7c0e36 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -13,13 +13,22 @@ LF='
13# First check if there is a .git to get the version from git describe 13# First check if there is a .git to get the version from git describe
14# otherwise try to get the version from the kernel Makefile 14# otherwise try to get the version from the kernel Makefile
15# 15#
16if test -d ../../.git -o -f ../../.git && 16CID=
17 VN=$(git tag 2>/dev/null | tail -1 | grep -E "v[0-9].[0-9]*") 17TAG=
18if test -d ../../.git -o -f ../../.git
18then 19then
19 VN=$(echo $VN"-g"$(git log -1 --abbrev=4 --pretty=format:"%h" HEAD)) 20 TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
20 VN=$(echo "$VN" | sed -e 's/-/./g'); 21 CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
21else 22fi
22 VN=$(MAKEFLAGS= make -sC ../.. kernelversion) 23if test -z "$TAG"
24then
25 TAG=$(MAKEFLAGS= make -sC ../.. kernelversion)
26fi
27VN="$TAG$CID"
28if test -n "$CID"
29then
30 # format version string, strip trailing zero of sublevel:
31 VN=$(echo "$VN" | sed -e 's/-/./g;s/\([0-9]*[.][0-9]*\)[.]0/\1/')
23fi 32fi
24 33
25VN=$(expr "$VN" : v*'\(.*\)') 34VN=$(expr "$VN" : v*'\(.*\)')
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 6f7d5a9d6b05..c4374f07603c 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -513,10 +513,16 @@ void dsos__add(struct list_head *head, struct dso *dso)
513 list_add_tail(&dso->node, head); 513 list_add_tail(&dso->node, head);
514} 514}
515 515
516struct dso *dsos__find(struct list_head *head, const char *name) 516struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short)
517{ 517{
518 struct dso *pos; 518 struct dso *pos;
519 519
520 if (cmp_short) {
521 list_for_each_entry(pos, head, node)
522 if (strcmp(pos->short_name, name) == 0)
523 return pos;
524 return NULL;
525 }
520 list_for_each_entry(pos, head, node) 526 list_for_each_entry(pos, head, node)
521 if (strcmp(pos->long_name, name) == 0) 527 if (strcmp(pos->long_name, name) == 0)
522 return pos; 528 return pos;
@@ -525,7 +531,7 @@ struct dso *dsos__find(struct list_head *head, const char *name)
525 531
526struct dso *__dsos__findnew(struct list_head *head, const char *name) 532struct dso *__dsos__findnew(struct list_head *head, const char *name)
527{ 533{
528 struct dso *dso = dsos__find(head, name); 534 struct dso *dso = dsos__find(head, name, false);
529 535
530 if (!dso) { 536 if (!dso) {
531 dso = dso__new(name); 537 dso = dso__new(name);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 450199ab51b5..d51aaf272c68 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -133,7 +133,8 @@ struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
133 const char *short_name, int dso_type); 133 const char *short_name, int dso_type);
134 134
135void dsos__add(struct list_head *head, struct dso *dso); 135void dsos__add(struct list_head *head, struct dso *dso);
136struct dso *dsos__find(struct list_head *head, const char *name); 136struct dso *dsos__find(struct list_head *head, const char *name,
137 bool cmp_short);
137struct dso *__dsos__findnew(struct list_head *head, const char *name); 138struct dso *__dsos__findnew(struct list_head *head, const char *name);
138bool __dsos__read_build_ids(struct list_head *head, bool with_hits); 139bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
139 140
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f7c727801aab..8065ce8fa9a5 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -776,6 +776,8 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
776 if (pipe_output) 776 if (pipe_output)
777 dup2(2, 1); 777 dup2(2, 1);
778 778
779 signal(SIGTERM, SIG_DFL);
780
779 close(child_ready_pipe[0]); 781 close(child_ready_pipe[0]);
780 close(go_pipe[1]); 782 close(go_pipe[1]);
781 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 783 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
@@ -819,6 +821,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
819 goto out_close_pipes; 821 goto out_close_pipes;
820 } 822 }
821 823
824 fcntl(go_pipe[1], F_SETFD, FD_CLOEXEC);
822 evlist->workload.cork_fd = go_pipe[1]; 825 evlist->workload.cork_fd = go_pipe[1];
823 close(child_ready_pipe[0]); 826 close(child_ready_pipe[0]);
824 return 0; 827 return 0;
@@ -835,10 +838,17 @@ out_close_ready_pipe:
835int perf_evlist__start_workload(struct perf_evlist *evlist) 838int perf_evlist__start_workload(struct perf_evlist *evlist)
836{ 839{
837 if (evlist->workload.cork_fd > 0) { 840 if (evlist->workload.cork_fd > 0) {
841 char bf;
842 int ret;
838 /* 843 /*
839 * Remove the cork, let it rip! 844 * Remove the cork, let it rip!
840 */ 845 */
841 return close(evlist->workload.cork_fd); 846 ret = write(evlist->workload.cork_fd, &bf, 1);
847 if (ret < 0)
848 perror("enable to write to pipe");
849
850 close(evlist->workload.cork_fd);
851 return ret;
842 } 852 }
843 853
844 return 0; 854 return 0;
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 07b1a3ad3e24..c9c7494506a1 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -124,7 +124,7 @@ struct event_format *event_format__new(const char *sys, const char *name)
124 bf = nbf; 124 bf = nbf;
125 } 125 }
126 126
127 n = read(fd, bf + size, BUFSIZ); 127 n = read(fd, bf + size, alloc_size - size);
128 if (n < 0) 128 if (n < 0)
129 goto out_free_bf; 129 goto out_free_bf;
130 size += n; 130 size += n;
@@ -1170,7 +1170,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1170 } else { 1170 } else {
1171 data->user_stack.data = (char *)array; 1171 data->user_stack.data = (char *)array;
1172 array += size / sizeof(*array); 1172 array += size / sizeof(*array);
1173 data->user_stack.size = *array; 1173 data->user_stack.size = *array++;
1174 } 1174 }
1175 } 1175 }
1176 1176
@@ -1514,7 +1514,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel,
1514 switch (err) { 1514 switch (err) {
1515 case EPERM: 1515 case EPERM:
1516 case EACCES: 1516 case EACCES:
1517 return scnprintf(msg, size, "%s", 1517 return scnprintf(msg, size,
1518 "You may not have permission to collect %sstats.\n" 1518 "You may not have permission to collect %sstats.\n"
1519 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" 1519 "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n"
1520 " -1 - Not paranoid at all\n" 1520 " -1 - Not paranoid at all\n"
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 326068a593a5..a4dafbee2511 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2303,29 +2303,18 @@ int perf_session__write_header(struct perf_session *session,
2303 struct perf_file_header f_header; 2303 struct perf_file_header f_header;
2304 struct perf_file_attr f_attr; 2304 struct perf_file_attr f_attr;
2305 struct perf_header *header = &session->header; 2305 struct perf_header *header = &session->header;
2306 struct perf_evsel *evsel, *pair = NULL; 2306 struct perf_evsel *evsel;
2307 int err; 2307 int err;
2308 2308
2309 lseek(fd, sizeof(f_header), SEEK_SET); 2309 lseek(fd, sizeof(f_header), SEEK_SET);
2310 2310
2311 if (session->evlist != evlist)
2312 pair = perf_evlist__first(session->evlist);
2313
2314 list_for_each_entry(evsel, &evlist->entries, node) { 2311 list_for_each_entry(evsel, &evlist->entries, node) {
2315 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2312 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2316 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2313 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
2317 if (err < 0) { 2314 if (err < 0) {
2318out_err_write:
2319 pr_debug("failed to write perf header\n"); 2315 pr_debug("failed to write perf header\n");
2320 return err; 2316 return err;
2321 } 2317 }
2322 if (session->evlist != evlist) {
2323 err = do_write(fd, pair->id, pair->ids * sizeof(u64));
2324 if (err < 0)
2325 goto out_err_write;
2326 evsel->ids += pair->ids;
2327 pair = perf_evsel__next(pair);
2328 }
2329 } 2318 }
2330 2319
2331 header->attr_offset = lseek(fd, 0, SEEK_CUR); 2320 header->attr_offset = lseek(fd, 0, SEEK_CUR);
@@ -2391,7 +2380,6 @@ out_err_write:
2391 } 2380 }
2392 lseek(fd, header->data_offset + header->data_size, SEEK_SET); 2381 lseek(fd, header->data_offset + header->data_size, SEEK_SET);
2393 2382
2394 header->frozen = 1;
2395 return 0; 2383 return 0;
2396} 2384}
2397 2385
@@ -2871,7 +2859,6 @@ int perf_session__read_header(struct perf_session *session, int fd)
2871 session->pevent)) 2859 session->pevent))
2872 goto out_delete_evlist; 2860 goto out_delete_evlist;
2873 2861
2874 header->frozen = 1;
2875 return 0; 2862 return 0;
2876out_errno: 2863out_errno:
2877 return -errno; 2864 return -errno;
@@ -2969,6 +2956,8 @@ int perf_event__process_attr(union perf_event *event,
2969 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]); 2956 perf_evlist__id_add(evlist, evsel, 0, i, event->attr.id[i]);
2970 } 2957 }
2971 2958
2959 symbol_conf.nr_events = evlist->nr_entries;
2960
2972 return 0; 2961 return 0;
2973} 2962}
2974 2963
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index c9fc55cada6d..16a3e83c584e 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -84,7 +84,6 @@ struct perf_session_env {
84}; 84};
85 85
86struct perf_header { 86struct perf_header {
87 int frozen;
88 bool needs_swap; 87 bool needs_swap;
89 s64 attr_offset; 88 s64 attr_offset;
90 u64 data_offset; 89 u64 data_offset;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 6b32721f829a..b11a6cfdb414 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -70,9 +70,17 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
70 int symlen; 70 int symlen;
71 u16 len; 71 u16 len;
72 72
73 if (h->ms.sym) 73 /*
74 hists__new_col_len(hists, HISTC_SYMBOL, h->ms.sym->namelen + 4); 74 * +4 accounts for '[x] ' priv level info
75 else { 75 * +2 accounts for 0x prefix on raw addresses
76 * +3 accounts for ' y ' symtab origin info
77 */
78 if (h->ms.sym) {
79 symlen = h->ms.sym->namelen + 4;
80 if (verbose)
81 symlen += BITS_PER_LONG / 4 + 2 + 3;
82 hists__new_col_len(hists, HISTC_SYMBOL, symlen);
83 } else {
76 symlen = unresolved_col_width + 4 + 2; 84 symlen = unresolved_col_width + 4 + 2;
77 hists__new_col_len(hists, HISTC_SYMBOL, symlen); 85 hists__new_col_len(hists, HISTC_SYMBOL, symlen);
78 hists__set_unres_dso_col_len(hists, HISTC_DSO); 86 hists__set_unres_dso_col_len(hists, HISTC_DSO);
@@ -91,12 +99,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
91 hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen); 99 hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);
92 100
93 if (h->branch_info) { 101 if (h->branch_info) {
94 /*
95 * +4 accounts for '[x] ' priv level info
96 * +2 account of 0x prefix on raw addresses
97 */
98 if (h->branch_info->from.sym) { 102 if (h->branch_info->from.sym) {
99 symlen = (int)h->branch_info->from.sym->namelen + 4; 103 symlen = (int)h->branch_info->from.sym->namelen + 4;
104 if (verbose)
105 symlen += BITS_PER_LONG / 4 + 2 + 3;
100 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen); 106 hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
101 107
102 symlen = dso__name_len(h->branch_info->from.map->dso); 108 symlen = dso__name_len(h->branch_info->from.map->dso);
@@ -109,6 +115,8 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
109 115
110 if (h->branch_info->to.sym) { 116 if (h->branch_info->to.sym) {
111 symlen = (int)h->branch_info->to.sym->namelen + 4; 117 symlen = (int)h->branch_info->to.sym->namelen + 4;
118 if (verbose)
119 symlen += BITS_PER_LONG / 4 + 2 + 3;
112 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 120 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
113 121
114 symlen = dso__name_len(h->branch_info->to.map->dso); 122 symlen = dso__name_len(h->branch_info->to.map->dso);
@@ -121,10 +129,6 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
121 } 129 }
122 130
123 if (h->mem_info) { 131 if (h->mem_info) {
124 /*
125 * +4 accounts for '[x] ' priv level info
126 * +2 account of 0x prefix on raw addresses
127 */
128 if (h->mem_info->daddr.sym) { 132 if (h->mem_info->daddr.sym) {
129 symlen = (int)h->mem_info->daddr.sym->namelen + 4 133 symlen = (int)h->mem_info->daddr.sym->namelen + 4
130 + unresolved_col_width + 2; 134 + unresolved_col_width + 2;
@@ -236,8 +240,7 @@ static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
236 return he->stat.period == 0; 240 return he->stat.period == 0;
237} 241}
238 242
239static void __hists__decay_entries(struct hists *hists, bool zap_user, 243void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
240 bool zap_kernel, bool threaded)
241{ 244{
242 struct rb_node *next = rb_first(&hists->entries); 245 struct rb_node *next = rb_first(&hists->entries);
243 struct hist_entry *n; 246 struct hist_entry *n;
@@ -256,7 +259,7 @@ static void __hists__decay_entries(struct hists *hists, bool zap_user,
256 !n->used) { 259 !n->used) {
257 rb_erase(&n->rb_node, &hists->entries); 260 rb_erase(&n->rb_node, &hists->entries);
258 261
259 if (sort__need_collapse || threaded) 262 if (sort__need_collapse)
260 rb_erase(&n->rb_node_in, &hists->entries_collapsed); 263 rb_erase(&n->rb_node_in, &hists->entries_collapsed);
261 264
262 hist_entry__free(n); 265 hist_entry__free(n);
@@ -265,17 +268,6 @@ static void __hists__decay_entries(struct hists *hists, bool zap_user,
265 } 268 }
266} 269}
267 270
268void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
269{
270 return __hists__decay_entries(hists, zap_user, zap_kernel, false);
271}
272
273void hists__decay_entries_threaded(struct hists *hists,
274 bool zap_user, bool zap_kernel)
275{
276 return __hists__decay_entries(hists, zap_user, zap_kernel, true);
277}
278
279/* 271/*
280 * histogram, sorted on item, collects periods 272 * histogram, sorted on item, collects periods
281 */ 273 */
@@ -292,6 +284,20 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template)
292 he->ms.map->referenced = true; 284 he->ms.map->referenced = true;
293 285
294 if (he->branch_info) { 286 if (he->branch_info) {
287 /*
288 * This branch info is (a part of) allocated from
289 * machine__resolve_bstack() and will be freed after
290 * adding new entries. So we need to save a copy.
291 */
292 he->branch_info = malloc(sizeof(*he->branch_info));
293 if (he->branch_info == NULL) {
294 free(he);
295 return NULL;
296 }
297
298 memcpy(he->branch_info, template->branch_info,
299 sizeof(*he->branch_info));
300
295 if (he->branch_info->from.map) 301 if (he->branch_info->from.map)
296 he->branch_info->from.map->referenced = true; 302 he->branch_info->from.map->referenced = true;
297 if (he->branch_info->to.map) 303 if (he->branch_info->to.map)
@@ -341,8 +347,6 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
341 struct hist_entry *he; 347 struct hist_entry *he;
342 int cmp; 348 int cmp;
343 349
344 pthread_mutex_lock(&hists->lock);
345
346 p = &hists->entries_in->rb_node; 350 p = &hists->entries_in->rb_node;
347 351
348 while (*p != NULL) { 352 while (*p != NULL) {
@@ -360,6 +364,12 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
360 if (!cmp) { 364 if (!cmp) {
361 he_stat__add_period(&he->stat, period, weight); 365 he_stat__add_period(&he->stat, period, weight);
362 366
367 /*
368 * This mem info was allocated from machine__resolve_mem
369 * and will not be used anymore.
370 */
371 free(entry->mem_info);
372
363 /* If the map of an existing hist_entry has 373 /* If the map of an existing hist_entry has
364 * become out-of-date due to an exec() or 374 * become out-of-date due to an exec() or
365 * similar, update it. Otherwise we will 375 * similar, update it. Otherwise we will
@@ -382,14 +392,12 @@ static struct hist_entry *add_hist_entry(struct hists *hists,
382 392
383 he = hist_entry__new(entry); 393 he = hist_entry__new(entry);
384 if (!he) 394 if (!he)
385 goto out_unlock; 395 return NULL;
386 396
387 rb_link_node(&he->rb_node_in, parent, p); 397 rb_link_node(&he->rb_node_in, parent, p);
388 rb_insert_color(&he->rb_node_in, hists->entries_in); 398 rb_insert_color(&he->rb_node_in, hists->entries_in);
389out: 399out:
390 hist_entry__add_cpumode_period(he, al->cpumode, period); 400 hist_entry__add_cpumode_period(he, al->cpumode, period);
391out_unlock:
392 pthread_mutex_unlock(&hists->lock);
393 return he; 401 return he;
394} 402}
395 403
@@ -589,13 +597,13 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
589 hists__filter_entry_by_symbol(hists, he); 597 hists__filter_entry_by_symbol(hists, he);
590} 598}
591 599
592static void __hists__collapse_resort(struct hists *hists, bool threaded) 600void hists__collapse_resort(struct hists *hists)
593{ 601{
594 struct rb_root *root; 602 struct rb_root *root;
595 struct rb_node *next; 603 struct rb_node *next;
596 struct hist_entry *n; 604 struct hist_entry *n;
597 605
598 if (!sort__need_collapse && !threaded) 606 if (!sort__need_collapse)
599 return; 607 return;
600 608
601 root = hists__get_rotate_entries_in(hists); 609 root = hists__get_rotate_entries_in(hists);
@@ -617,16 +625,6 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded)
617 } 625 }
618} 626}
619 627
620void hists__collapse_resort(struct hists *hists)
621{
622 return __hists__collapse_resort(hists, false);
623}
624
625void hists__collapse_resort_threaded(struct hists *hists)
626{
627 return __hists__collapse_resort(hists, true);
628}
629
630/* 628/*
631 * reverse the map, sort on period. 629 * reverse the map, sort on period.
632 */ 630 */
@@ -713,7 +711,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
713 rb_insert_color(&he->rb_node, entries); 711 rb_insert_color(&he->rb_node, entries);
714} 712}
715 713
716static void __hists__output_resort(struct hists *hists, bool threaded) 714void hists__output_resort(struct hists *hists)
717{ 715{
718 struct rb_root *root; 716 struct rb_root *root;
719 struct rb_node *next; 717 struct rb_node *next;
@@ -722,7 +720,7 @@ static void __hists__output_resort(struct hists *hists, bool threaded)
722 720
723 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100); 721 min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
724 722
725 if (sort__need_collapse || threaded) 723 if (sort__need_collapse)
726 root = &hists->entries_collapsed; 724 root = &hists->entries_collapsed;
727 else 725 else
728 root = hists->entries_in; 726 root = hists->entries_in;
@@ -743,16 +741,6 @@ static void __hists__output_resort(struct hists *hists, bool threaded)
743 } 741 }
744} 742}
745 743
746void hists__output_resort(struct hists *hists)
747{
748 return __hists__output_resort(hists, false);
749}
750
751void hists__output_resort_threaded(struct hists *hists)
752{
753 return __hists__output_resort(hists, true);
754}
755
756static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h, 744static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
757 enum hist_filter filter) 745 enum hist_filter filter)
758{ 746{
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 14c2fe20aa62..2d3790fd99bb 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -43,12 +43,12 @@ enum hist_column {
43 HISTC_COMM, 43 HISTC_COMM,
44 HISTC_PARENT, 44 HISTC_PARENT,
45 HISTC_CPU, 45 HISTC_CPU,
46 HISTC_SRCLINE,
46 HISTC_MISPREDICT, 47 HISTC_MISPREDICT,
47 HISTC_SYMBOL_FROM, 48 HISTC_SYMBOL_FROM,
48 HISTC_SYMBOL_TO, 49 HISTC_SYMBOL_TO,
49 HISTC_DSO_FROM, 50 HISTC_DSO_FROM,
50 HISTC_DSO_TO, 51 HISTC_DSO_TO,
51 HISTC_SRCLINE,
52 HISTC_LOCAL_WEIGHT, 52 HISTC_LOCAL_WEIGHT,
53 HISTC_GLOBAL_WEIGHT, 53 HISTC_GLOBAL_WEIGHT,
54 HISTC_MEM_DADDR_SYMBOL, 54 HISTC_MEM_DADDR_SYMBOL,
@@ -104,13 +104,9 @@ struct hist_entry *__hists__add_mem_entry(struct hists *self,
104 u64 weight); 104 u64 weight);
105 105
106void hists__output_resort(struct hists *self); 106void hists__output_resort(struct hists *self);
107void hists__output_resort_threaded(struct hists *hists);
108void hists__collapse_resort(struct hists *self); 107void hists__collapse_resort(struct hists *self);
109void hists__collapse_resort_threaded(struct hists *hists);
110 108
111void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 109void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
112void hists__decay_entries_threaded(struct hists *hists, bool zap_user,
113 bool zap_kernel);
114void hists__output_recalc_col_len(struct hists *hists, int max_rows); 110void hists__output_recalc_col_len(struct hists *hists, int max_rows);
115 111
116void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h); 112void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
@@ -119,7 +115,7 @@ void events_stats__inc(struct events_stats *stats, u32 type);
119size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 115size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
120 116
121size_t hists__fprintf(struct hists *self, bool show_header, int max_rows, 117size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
122 int max_cols, FILE *fp); 118 int max_cols, float min_pcnt, FILE *fp);
123 119
124int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr); 120int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
125int hist_entry__annotate(struct hist_entry *self, size_t privsize); 121int hist_entry__annotate(struct hist_entry *self, size_t privsize);
@@ -199,6 +195,7 @@ int hist_entry__tui_annotate(struct hist_entry *he, struct perf_evsel *evsel,
199 195
200int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, 196int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
201 struct hist_browser_timer *hbt, 197 struct hist_browser_timer *hbt,
198 float min_pcnt,
202 struct perf_session_env *env); 199 struct perf_session_env *env);
203int script_browse(const char *script_opt); 200int script_browse(const char *script_opt);
204#else 201#else
@@ -206,6 +203,7 @@ static inline
206int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused, 203int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
207 const char *help __maybe_unused, 204 const char *help __maybe_unused,
208 struct hist_browser_timer *hbt __maybe_unused, 205 struct hist_browser_timer *hbt __maybe_unused,
206 float min_pcnt __maybe_unused,
209 struct perf_session_env *env __maybe_unused) 207 struct perf_session_env *env __maybe_unused)
210{ 208{
211 return 0; 209 return 0;
@@ -233,12 +231,14 @@ static inline int script_browse(const char *script_opt __maybe_unused)
233 231
234#ifdef GTK2_SUPPORT 232#ifdef GTK2_SUPPORT
235int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help, 233int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *help,
236 struct hist_browser_timer *hbt __maybe_unused); 234 struct hist_browser_timer *hbt __maybe_unused,
235 float min_pcnt);
237#else 236#else
238static inline 237static inline
239int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused, 238int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,
240 const char *help __maybe_unused, 239 const char *help __maybe_unused,
241 struct hist_browser_timer *hbt __maybe_unused) 240 struct hist_browser_timer *hbt __maybe_unused,
241 float min_pcnt __maybe_unused)
242{ 242{
243 return 0; 243 return 0;
244} 244}
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 6fcb9de62340..8bcdf9e54089 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -21,6 +21,7 @@ const char *map_type__name[MAP__NR_TYPES] = {
21static inline int is_anon_memory(const char *filename) 21static inline int is_anon_memory(const char *filename)
22{ 22{
23 return !strcmp(filename, "//anon") || 23 return !strcmp(filename, "//anon") ||
24 !strcmp(filename, "/dev/zero (deleted)") ||
24 !strcmp(filename, "/anon_hugepage (deleted)"); 25 !strcmp(filename, "/anon_hugepage (deleted)");
25} 26}
26 27
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6c8bb0fb189b..995fc25db8c6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -860,7 +860,8 @@ int parse_events_terms(struct list_head *terms, const char *str)
860 return 0; 860 return 0;
861 } 861 }
862 862
863 parse_events__free_terms(data.terms); 863 if (data.terms)
864 parse_events__free_terms(data.terms);
864 return ret; 865 return ret;
865} 866}
866 867
@@ -1183,6 +1184,7 @@ static int new_term(struct parse_events_term **_term, int type_val,
1183 term->val.str = str; 1184 term->val.str = str;
1184 break; 1185 break;
1185 default: 1186 default:
1187 free(term);
1186 return -EINVAL; 1188 return -EINVAL;
1187 } 1189 }
1188 1190
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 6b51d47acdba..f3b235ec7bf4 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -37,7 +37,6 @@ struct perf_session {
37 int fd; 37 int fd;
38 bool fd_pipe; 38 bool fd_pipe;
39 bool repipe; 39 bool repipe;
40 int cwdlen;
41 char *cwd; 40 char *cwd;
42 struct ordered_samples ordered_samples; 41 struct ordered_samples ordered_samples;
43 char filename[1]; 42 char filename[1];
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 6b0ed322907e..58ea5ca6c255 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -18,8 +18,9 @@ class install_lib(_install_lib):
18 self.build_dir = build_lib 18 self.build_dir = build_lib
19 19
20 20
21cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] 21cflags = getenv('CFLAGS', '').split()
22cflags += getenv('CFLAGS', '').split() 22# switch off several checks (need to be at the end of cflags list)
23cflags += ['-fno-strict-aliasing', '-Wno-write-strings', '-Wno-unused-parameter' ]
23 24
24build_lib = getenv('PYTHON_EXTBUILD_LIB') 25build_lib = getenv('PYTHON_EXTBUILD_LIB')
25build_tmp = getenv('PYTHON_EXTBUILD_TMP') 26build_tmp = getenv('PYTHON_EXTBUILD_TMP')
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 5f52d492590c..313a5a730112 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -1,5 +1,6 @@
1#include "sort.h" 1#include "sort.h"
2#include "hist.h" 2#include "hist.h"
3#include "symbol.h"
3 4
4regex_t parent_regex; 5regex_t parent_regex;
5const char default_parent_pattern[] = "^sys_|^do_page_fault"; 6const char default_parent_pattern[] = "^sys_|^do_page_fault";
@@ -9,7 +10,7 @@ const char *sort_order = default_sort_order;
9int sort__need_collapse = 0; 10int sort__need_collapse = 0;
10int sort__has_parent = 0; 11int sort__has_parent = 0;
11int sort__has_sym = 0; 12int sort__has_sym = 0;
12int sort__branch_mode = -1; /* -1 = means not set */ 13enum sort_mode sort__mode = SORT_MODE__NORMAL;
13 14
14enum sort_type sort__first_dimension; 15enum sort_type sort__first_dimension;
15 16
@@ -194,7 +195,7 @@ static int _hist_entry__sym_snprintf(struct map *map, struct symbol *sym,
194 if (verbose) { 195 if (verbose) {
195 char o = map ? dso__symtab_origin(map->dso) : '!'; 196 char o = map ? dso__symtab_origin(map->dso) : '!';
196 ret += repsep_snprintf(bf, size, "%-#*llx %c ", 197 ret += repsep_snprintf(bf, size, "%-#*llx %c ",
197 BITS_PER_LONG / 4, ip, o); 198 BITS_PER_LONG / 4 + 2, ip, o);
198 } 199 }
199 200
200 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level); 201 ret += repsep_snprintf(bf + ret, size - ret, "[%c] ", level);
@@ -871,14 +872,6 @@ static struct sort_dimension common_sort_dimensions[] = {
871 DIM(SORT_PARENT, "parent", sort_parent), 872 DIM(SORT_PARENT, "parent", sort_parent),
872 DIM(SORT_CPU, "cpu", sort_cpu), 873 DIM(SORT_CPU, "cpu", sort_cpu),
873 DIM(SORT_SRCLINE, "srcline", sort_srcline), 874 DIM(SORT_SRCLINE, "srcline", sort_srcline),
874 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
875 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
876 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
877 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
878 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
879 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
880 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
881 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
882}; 875};
883 876
884#undef DIM 877#undef DIM
@@ -895,6 +888,36 @@ static struct sort_dimension bstack_sort_dimensions[] = {
895 888
896#undef DIM 889#undef DIM
897 890
891#define DIM(d, n, func) [d - __SORT_MEMORY_MODE] = { .name = n, .entry = &(func) }
892
893static struct sort_dimension memory_sort_dimensions[] = {
894 DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight),
895 DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight),
896 DIM(SORT_MEM_DADDR_SYMBOL, "symbol_daddr", sort_mem_daddr_sym),
897 DIM(SORT_MEM_DADDR_DSO, "dso_daddr", sort_mem_daddr_dso),
898 DIM(SORT_MEM_LOCKED, "locked", sort_mem_locked),
899 DIM(SORT_MEM_TLB, "tlb", sort_mem_tlb),
900 DIM(SORT_MEM_LVL, "mem", sort_mem_lvl),
901 DIM(SORT_MEM_SNOOP, "snoop", sort_mem_snoop),
902};
903
904#undef DIM
905
906static void __sort_dimension__add(struct sort_dimension *sd, enum sort_type idx)
907{
908 if (sd->taken)
909 return;
910
911 if (sd->entry->se_collapse)
912 sort__need_collapse = 1;
913
914 if (list_empty(&hist_entry__sort_list))
915 sort__first_dimension = idx;
916
917 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
918 sd->taken = 1;
919}
920
898int sort_dimension__add(const char *tok) 921int sort_dimension__add(const char *tok)
899{ 922{
900 unsigned int i; 923 unsigned int i;
@@ -915,25 +938,11 @@ int sort_dimension__add(const char *tok)
915 return -EINVAL; 938 return -EINVAL;
916 } 939 }
917 sort__has_parent = 1; 940 sort__has_parent = 1;
918 } else if (sd->entry == &sort_sym || 941 } else if (sd->entry == &sort_sym) {
919 sd->entry == &sort_sym_from ||
920 sd->entry == &sort_sym_to ||
921 sd->entry == &sort_mem_daddr_sym) {
922 sort__has_sym = 1; 942 sort__has_sym = 1;
923 } 943 }
924 944
925 if (sd->taken) 945 __sort_dimension__add(sd, i);
926 return 0;
927
928 if (sd->entry->se_collapse)
929 sort__need_collapse = 1;
930
931 if (list_empty(&hist_entry__sort_list))
932 sort__first_dimension = i;
933
934 list_add_tail(&sd->entry->list, &hist_entry__sort_list);
935 sd->taken = 1;
936
937 return 0; 946 return 0;
938 } 947 }
939 948
@@ -943,24 +952,29 @@ int sort_dimension__add(const char *tok)
943 if (strncasecmp(tok, sd->name, strlen(tok))) 952 if (strncasecmp(tok, sd->name, strlen(tok)))
944 continue; 953 continue;
945 954
946 if (sort__branch_mode != 1) 955 if (sort__mode != SORT_MODE__BRANCH)
947 return -EINVAL; 956 return -EINVAL;
948 957
949 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) 958 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
950 sort__has_sym = 1; 959 sort__has_sym = 1;
951 960
952 if (sd->taken) 961 __sort_dimension__add(sd, i + __SORT_BRANCH_STACK);
953 return 0; 962 return 0;
963 }
954 964
955 if (sd->entry->se_collapse) 965 for (i = 0; i < ARRAY_SIZE(memory_sort_dimensions); i++) {
956 sort__need_collapse = 1; 966 struct sort_dimension *sd = &memory_sort_dimensions[i];
957 967
958 if (list_empty(&hist_entry__sort_list)) 968 if (strncasecmp(tok, sd->name, strlen(tok)))
959 sort__first_dimension = i + __SORT_BRANCH_STACK; 969 continue;
960 970
961 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 971 if (sort__mode != SORT_MODE__MEMORY)
962 sd->taken = 1; 972 return -EINVAL;
973
974 if (sd->entry == &sort_mem_daddr_sym)
975 sort__has_sym = 1;
963 976
977 __sort_dimension__add(sd, i + __SORT_MEMORY_MODE);
964 return 0; 978 return 0;
965 } 979 }
966 980
@@ -993,8 +1007,9 @@ int setup_sorting(void)
993 return ret; 1007 return ret;
994} 1008}
995 1009
996void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, 1010static void sort_entry__setup_elide(struct sort_entry *self,
997 const char *list_name, FILE *fp) 1011 struct strlist *list,
1012 const char *list_name, FILE *fp)
998{ 1013{
999 if (list && strlist__nr_entries(list) == 1) { 1014 if (list && strlist__nr_entries(list) == 1) {
1000 if (fp != NULL) 1015 if (fp != NULL)
@@ -1003,3 +1018,42 @@ void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list,
1003 self->elide = true; 1018 self->elide = true;
1004 } 1019 }
1005} 1020}
1021
1022void sort__setup_elide(FILE *output)
1023{
1024 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1025 "dso", output);
1026 sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list,
1027 "comm", output);
1028 sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list,
1029 "symbol", output);
1030
1031 if (sort__mode == SORT_MODE__BRANCH) {
1032 sort_entry__setup_elide(&sort_dso_from,
1033 symbol_conf.dso_from_list,
1034 "dso_from", output);
1035 sort_entry__setup_elide(&sort_dso_to,
1036 symbol_conf.dso_to_list,
1037 "dso_to", output);
1038 sort_entry__setup_elide(&sort_sym_from,
1039 symbol_conf.sym_from_list,
1040 "sym_from", output);
1041 sort_entry__setup_elide(&sort_sym_to,
1042 symbol_conf.sym_to_list,
1043 "sym_to", output);
1044 } else if (sort__mode == SORT_MODE__MEMORY) {
1045 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1046 "symbol_daddr", output);
1047 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1048 "dso_daddr", output);
1049 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1050 "mem", output);
1051 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1052 "local_weight", output);
1053 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1054 "tlb", output);
1055 sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list,
1056 "snoop", output);
1057 }
1058
1059}
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index f24bdf64238c..45ac84c1e037 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -32,7 +32,7 @@ extern const char default_sort_order[];
32extern int sort__need_collapse; 32extern int sort__need_collapse;
33extern int sort__has_parent; 33extern int sort__has_parent;
34extern int sort__has_sym; 34extern int sort__has_sym;
35extern int sort__branch_mode; 35extern enum sort_mode sort__mode;
36extern struct sort_entry sort_comm; 36extern struct sort_entry sort_comm;
37extern struct sort_entry sort_dso; 37extern struct sort_entry sort_dso;
38extern struct sort_entry sort_sym; 38extern struct sort_entry sort_sym;
@@ -117,12 +117,18 @@ static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he)
117 return NULL; 117 return NULL;
118} 118}
119 119
120static inline void hist_entry__add_pair(struct hist_entry *he, 120static inline void hist_entry__add_pair(struct hist_entry *pair,
121 struct hist_entry *pair) 121 struct hist_entry *he)
122{ 122{
123 list_add_tail(&he->pairs.head, &pair->pairs.node); 123 list_add_tail(&pair->pairs.node, &he->pairs.head);
124} 124}
125 125
126enum sort_mode {
127 SORT_MODE__NORMAL,
128 SORT_MODE__BRANCH,
129 SORT_MODE__MEMORY,
130};
131
126enum sort_type { 132enum sort_type {
127 /* common sort keys */ 133 /* common sort keys */
128 SORT_PID, 134 SORT_PID,
@@ -132,14 +138,6 @@ enum sort_type {
132 SORT_PARENT, 138 SORT_PARENT,
133 SORT_CPU, 139 SORT_CPU,
134 SORT_SRCLINE, 140 SORT_SRCLINE,
135 SORT_LOCAL_WEIGHT,
136 SORT_GLOBAL_WEIGHT,
137 SORT_MEM_DADDR_SYMBOL,
138 SORT_MEM_DADDR_DSO,
139 SORT_MEM_LOCKED,
140 SORT_MEM_TLB,
141 SORT_MEM_LVL,
142 SORT_MEM_SNOOP,
143 141
144 /* branch stack specific sort keys */ 142 /* branch stack specific sort keys */
145 __SORT_BRANCH_STACK, 143 __SORT_BRANCH_STACK,
@@ -148,6 +146,17 @@ enum sort_type {
148 SORT_SYM_FROM, 146 SORT_SYM_FROM,
149 SORT_SYM_TO, 147 SORT_SYM_TO,
150 SORT_MISPREDICT, 148 SORT_MISPREDICT,
149
150 /* memory mode specific sort keys */
151 __SORT_MEMORY_MODE,
152 SORT_LOCAL_WEIGHT = __SORT_MEMORY_MODE,
153 SORT_GLOBAL_WEIGHT,
154 SORT_MEM_DADDR_SYMBOL,
155 SORT_MEM_DADDR_DSO,
156 SORT_MEM_LOCKED,
157 SORT_MEM_TLB,
158 SORT_MEM_LVL,
159 SORT_MEM_SNOOP,
151}; 160};
152 161
153/* 162/*
@@ -172,7 +181,6 @@ extern struct list_head hist_entry__sort_list;
172 181
173int setup_sorting(void); 182int setup_sorting(void);
174extern int sort_dimension__add(const char *); 183extern int sort_dimension__add(const char *);
175void sort_entry__setup_elide(struct sort_entry *self, struct strlist *list, 184void sort__setup_elide(FILE *fp);
176 const char *list_name, FILE *fp);
177 185
178#endif /* __PERF_SORT_H */ 186#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 23742126f47c..7c59c28afcc5 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -37,7 +37,7 @@ double stddev_stats(struct stats *stats)
37{ 37{
38 double variance, variance_mean; 38 double variance, variance_mean;
39 39
40 if (!stats->n) 40 if (stats->n < 2)
41 return 0.0; 41 return 0.0;
42 42
43 variance = stats->M2 / (stats->n - 1); 43 variance = stats->M2 / (stats->n - 1);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8cf3b5426a9a..d5528e1cc03a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -32,7 +32,6 @@ int vmlinux_path__nr_entries;
32char **vmlinux_path; 32char **vmlinux_path;
33 33
34struct symbol_conf symbol_conf = { 34struct symbol_conf symbol_conf = {
35 .exclude_other = true,
36 .use_modules = true, 35 .use_modules = true,
37 .try_vmlinux_path = true, 36 .try_vmlinux_path = true,
38 .annotate_src = true, 37 .annotate_src = true,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 632e40e5ceca..40399cbcca77 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -14,6 +14,7 @@ struct thread *thread__new(pid_t pid)
14 if (self != NULL) { 14 if (self != NULL) {
15 map_groups__init(&self->mg); 15 map_groups__init(&self->mg);
16 self->pid = pid; 16 self->pid = pid;
17 self->ppid = -1;
17 self->comm = malloc(32); 18 self->comm = malloc(32);
18 if (self->comm) 19 if (self->comm)
19 snprintf(self->comm, 32, ":%d", self->pid); 20 snprintf(self->comm, 32, ":%d", self->pid);
@@ -82,5 +83,8 @@ int thread__fork(struct thread *self, struct thread *parent)
82 for (i = 0; i < MAP__NR_TYPES; ++i) 83 for (i = 0; i < MAP__NR_TYPES; ++i)
83 if (map_groups__clone(&self->mg, &parent->mg, i) < 0) 84 if (map_groups__clone(&self->mg, &parent->mg, i) < 0)
84 return -ENOMEM; 85 return -ENOMEM;
86
87 self->ppid = parent->pid;
88
85 return 0; 89 return 0;
86} 90}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 5ad266403098..eeb7ac62b9e3 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -13,6 +13,7 @@ struct thread {
13 }; 13 };
14 struct map_groups mg; 14 struct map_groups mg;
15 pid_t pid; 15 pid_t pid;
16 pid_t ppid;
16 char shortname[3]; 17 char shortname[3];
17 bool comm_set; 18 bool comm_set;
18 char *comm; 19 char *comm;
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 54d37a4753c5..f857b51b6bde 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -23,20 +23,31 @@
23 23
24size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size) 24size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
25{ 25{
26 float samples_per_sec = top->samples / top->delay_secs; 26 float samples_per_sec;
27 float ksamples_per_sec = top->kernel_samples / top->delay_secs; 27 float ksamples_per_sec;
28 float esamples_percent = (100.0 * top->exact_samples) / top->samples; 28 float esamples_percent;
29 struct perf_record_opts *opts = &top->record_opts; 29 struct perf_record_opts *opts = &top->record_opts;
30 struct perf_target *target = &opts->target; 30 struct perf_target *target = &opts->target;
31 size_t ret = 0; 31 size_t ret = 0;
32 32
33 if (top->samples) {
34 samples_per_sec = top->samples / top->delay_secs;
35 ksamples_per_sec = top->kernel_samples / top->delay_secs;
36 esamples_percent = (100.0 * top->exact_samples) / top->samples;
37 } else {
38 samples_per_sec = ksamples_per_sec = esamples_percent = 0.0;
39 }
40
33 if (!perf_guest) { 41 if (!perf_guest) {
42 float ksamples_percent = 0.0;
43
44 if (samples_per_sec)
45 ksamples_percent = (100.0 * ksamples_per_sec) /
46 samples_per_sec;
34 ret = SNPRINTF(bf, size, 47 ret = SNPRINTF(bf, size,
35 " PerfTop:%8.0f irqs/sec kernel:%4.1f%%" 48 " PerfTop:%8.0f irqs/sec kernel:%4.1f%%"
36 " exact: %4.1f%% [", samples_per_sec, 49 " exact: %4.1f%% [", samples_per_sec,
37 100.0 - (100.0 * ((samples_per_sec - ksamples_per_sec) / 50 ksamples_percent, esamples_percent);
38 samples_per_sec)),
39 esamples_percent);
40 } else { 51 } else {
41 float us_samples_per_sec = top->us_samples / top->delay_secs; 52 float us_samples_per_sec = top->us_samples / top->delay_secs;
42 float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs; 53 float guest_kernel_samples_per_sec = top->guest_kernel_samples / top->delay_secs;
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 7ebf357dc9e1..df46be93d902 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -26,7 +26,6 @@ struct perf_top {
26 int print_entries, count_filter, delay_secs; 26 int print_entries, count_filter, delay_secs;
27 bool hide_kernel_symbols, hide_user_symbols, zero; 27 bool hide_kernel_symbols, hide_user_symbols, zero;
28 bool use_tui, use_stdio; 28 bool use_tui, use_stdio;
29 bool sort_has_symbols;
30 bool kptr_restrict_warned; 29 bool kptr_restrict_warned;
31 bool vmlinux_warned; 30 bool vmlinux_warned;
32 bool dump_symtab; 31 bool dump_symtab;
@@ -37,6 +36,7 @@ struct perf_top {
37 int realtime_prio; 36 int realtime_prio;
38 int sym_pcnt_filter; 37 int sym_pcnt_filter;
39 const char *sym_filter; 38 const char *sym_filter;
39 float min_percent;
40}; 40};
41 41
42size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 42size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index a45710b70a55..2732fad03908 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -72,6 +72,7 @@
72#include "types.h" 72#include "types.h"
73#include <sys/ttydefaults.h> 73#include <sys/ttydefaults.h>
74#include <lk/debugfs.h> 74#include <lk/debugfs.h>
75#include <termios.h>
75 76
76extern const char *graph_line; 77extern const char *graph_line;
77extern const char *graph_dotted_line; 78extern const char *graph_dotted_line;
@@ -221,8 +222,8 @@ extern unsigned char sane_ctype[256];
221#define isalpha(x) sane_istest(x,GIT_ALPHA) 222#define isalpha(x) sane_istest(x,GIT_ALPHA)
222#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 223#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
223#define isprint(x) sane_istest(x,GIT_PRINT) 224#define isprint(x) sane_istest(x,GIT_PRINT)
224#define islower(x) (sane_istest(x,GIT_ALPHA) && sane_istest(x,0x20)) 225#define islower(x) (sane_istest(x,GIT_ALPHA) && (x & 0x20))
225#define isupper(x) (sane_istest(x,GIT_ALPHA) && !sane_istest(x,0x20)) 226#define isupper(x) (sane_istest(x,GIT_ALPHA) && !(x & 0x20))
226#define tolower(x) sane_case((unsigned char)(x), 0x20) 227#define tolower(x) sane_case((unsigned char)(x), 0x20)
227#define toupper(x) sane_case((unsigned char)(x), 0) 228#define toupper(x) sane_case((unsigned char)(x), 0)
228 229
@@ -274,6 +275,5 @@ void dump_stack(void);
274 275
275extern unsigned int page_size; 276extern unsigned int page_size;
276 277
277struct winsize;
278void get_term_dimensions(struct winsize *ws); 278void get_term_dimensions(struct winsize *ws);
279#endif /* GIT_COMPAT_UTIL_H */ 279#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index e60951fcdb12..39159822d58f 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -91,7 +91,7 @@ void vdso__exit(void)
91 91
92struct dso *vdso__dso_findnew(struct list_head *head) 92struct dso *vdso__dso_findnew(struct list_head *head)
93{ 93{
94 struct dso *dso = dsos__find(head, VDSO__MAP_NAME); 94 struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true);
95 95
96 if (!dso) { 96 if (!dso) {
97 char *file; 97 char *file;