aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-04-13 14:27:58 -0400
committerIngo Molnar <mingo@kernel.org>2016-04-13 14:27:58 -0400
commitc5ab6ad7f627f031e2bbde575c7e6e27ea36da55 (patch)
tree75bbf85deaff38eaa562eefb45bdb38fbcd38849
parent31d50c551e30923b86a1b5b420920dd1927fa63b (diff)
parent59247e33ff494e3643cdff54b64bf72575052b76 (diff)
Merge tag 'perf-core-for-mingo-20160413' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: User visible changes: - Print callchains asked for events requested via 'perf trace --event' too: (Arnaldo Carvalho de Melo) # trace -e nanosleep --call dwarf --event sched:sched_switch/call-graph=fp/ usleep 1 0.346 (0.005 ms): usleep/24428 nanosleep(rqtp: 0x7fffa15a0540) ... 0.346 ( ): sched:sched_switch:usleep:24428 [120] S ==> swapper/3:0 [120]) __schedule+0xfe200402 ([kernel.kallsyms]) schedule+0xfe200035 ([kernel.kallsyms]) do_nanosleep+0xfe20006f ([kernel.kallsyms]) hrtimer_nanosleep+0xfe2000dc ([kernel.kallsyms]) sys_nanosleep+0xfe20007a ([kernel.kallsyms]) do_syscall_64+0xfe200062 ([kernel.kallsyms]) return_from_SYSCALL_64+0xfe200000 ([kernel.kallsyms]) __nanosleep+0xffff005b8d602010 (/usr/lib64/libc-2.22.so) 0.400 (0.059 ms): usleep/24428 ... [continued]: nanosleep()) = 0 __nanosleep+0x10 (/usr/lib64/libc-2.22.so) usleep+0x34 (/usr/lib64/libc-2.22.so) main+0x1eb (/usr/bin/usleep) __libc_start_main+0xf0 (/usr/lib64/libc-2.22.so) _start+0x29 (/usr/bin/usleep) - Allow requesting that some CPUs or PIDs be highlighted in 'perf sched map' (Jiri Olsa) - Compact 'perf sched map' to show just CPUs with activity, improving the output in high core count systems (Jiri Olsa) - Fix segfault with 'perf trace --no-syscalls -e syscall-names' by bailing out such request, doesn't make sense to ask for no syscalls and then specify which ones should be printed (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf-sched.txt16
-rw-r--r--tools/perf/builtin-sched.c198
-rw-r--r--tools/perf/builtin-script.c14
-rw-r--r--tools/perf/builtin-trace.c48
-rw-r--r--tools/perf/util/cpumap.c12
-rw-r--r--tools/perf/util/cpumap.h2
-rw-r--r--tools/perf/util/evsel.c131
-rw-r--r--tools/perf/util/evsel.h13
-rw-r--r--tools/perf/util/session.c130
-rw-r--r--tools/perf/util/session.h13
-rw-r--r--tools/perf/util/thread_map.c14
-rw-r--r--tools/perf/util/thread_map.h3
12 files changed, 416 insertions, 178 deletions
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8ff4df956951..1cc08cc47ac5 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -50,6 +50,22 @@ OPTIONS
50--dump-raw-trace=:: 50--dump-raw-trace=::
51 Display verbose dump of the sched data. 51 Display verbose dump of the sched data.
52 52
53OPTIONS for 'perf sched map'
54----------------------------
55
56--compact::
57 Show only CPUs with activity. Helps visualizing on high core
58 count systems.
59
60--cpus::
61 Show just entries with activities for the given CPUs.
62
63--color-cpus::
64 Highlight the given cpus.
65
66--color-pids::
67 Highlight the given pids.
68
53SEE ALSO 69SEE ALSO
54-------- 70--------
55linkperf:perf-record[1] 71linkperf:perf-record[1]
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 871b55ae22a4..afa057666c2a 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,8 @@
11#include "util/session.h" 11#include "util/session.h"
12#include "util/tool.h" 12#include "util/tool.h"
13#include "util/cloexec.h" 13#include "util/cloexec.h"
14#include "util/thread_map.h"
15#include "util/color.h"
14 16
15#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
16#include "util/trace-event.h" 18#include "util/trace-event.h"
@@ -122,6 +124,21 @@ struct trace_sched_handler {
122 struct machine *machine); 124 struct machine *machine);
123}; 125};
124 126
127#define COLOR_PIDS PERF_COLOR_BLUE
128#define COLOR_CPUS PERF_COLOR_BG_RED
129
130struct perf_sched_map {
131 DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS);
132 int *comp_cpus;
133 bool comp;
134 struct thread_map *color_pids;
135 const char *color_pids_str;
136 struct cpu_map *color_cpus;
137 const char *color_cpus_str;
138 struct cpu_map *cpus;
139 const char *cpus_str;
140};
141
125struct perf_sched { 142struct perf_sched {
126 struct perf_tool tool; 143 struct perf_tool tool;
127 const char *sort_order; 144 const char *sort_order;
@@ -173,6 +190,7 @@ struct perf_sched {
173 struct list_head sort_list, cmp_pid; 190 struct list_head sort_list, cmp_pid;
174 bool force; 191 bool force;
175 bool skip_merge; 192 bool skip_merge;
193 struct perf_sched_map map;
176}; 194};
177 195
178static u64 get_nsecs(void) 196static u64 get_nsecs(void)
@@ -1339,6 +1357,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool,
1339 return 0; 1357 return 0;
1340} 1358}
1341 1359
1360union map_priv {
1361 void *ptr;
1362 bool color;
1363};
1364
1365static bool thread__has_color(struct thread *thread)
1366{
1367 union map_priv priv = {
1368 .ptr = thread__priv(thread),
1369 };
1370
1371 return priv.color;
1372}
1373
1374static struct thread*
1375map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid)
1376{
1377 struct thread *thread = machine__findnew_thread(machine, pid, tid);
1378 union map_priv priv = {
1379 .color = false,
1380 };
1381
1382 if (!sched->map.color_pids || !thread || thread__priv(thread))
1383 return thread;
1384
1385 if (thread_map__has(sched->map.color_pids, tid))
1386 priv.color = true;
1387
1388 thread__set_priv(thread, priv.ptr);
1389 return thread;
1390}
1391
1342static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, 1392static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1343 struct perf_sample *sample, struct machine *machine) 1393 struct perf_sample *sample, struct machine *machine)
1344{ 1394{
@@ -1347,13 +1397,25 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1347 int new_shortname; 1397 int new_shortname;
1348 u64 timestamp0, timestamp = sample->time; 1398 u64 timestamp0, timestamp = sample->time;
1349 s64 delta; 1399 s64 delta;
1350 int cpu, this_cpu = sample->cpu; 1400 int i, this_cpu = sample->cpu;
1401 int cpus_nr;
1402 bool new_cpu = false;
1403 const char *color = PERF_COLOR_NORMAL;
1351 1404
1352 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); 1405 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);
1353 1406
1354 if (this_cpu > sched->max_cpu) 1407 if (this_cpu > sched->max_cpu)
1355 sched->max_cpu = this_cpu; 1408 sched->max_cpu = this_cpu;
1356 1409
1410 if (sched->map.comp) {
1411 cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS);
1412 if (!test_and_set_bit(this_cpu, sched->map.comp_cpus_mask)) {
1413 sched->map.comp_cpus[cpus_nr++] = this_cpu;
1414 new_cpu = true;
1415 }
1416 } else
1417 cpus_nr = sched->max_cpu;
1418
1357 timestamp0 = sched->cpu_last_switched[this_cpu]; 1419 timestamp0 = sched->cpu_last_switched[this_cpu];
1358 sched->cpu_last_switched[this_cpu] = timestamp; 1420 sched->cpu_last_switched[this_cpu] = timestamp;
1359 if (timestamp0) 1421 if (timestamp0)
@@ -1366,7 +1428,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1366 return -1; 1428 return -1;
1367 } 1429 }
1368 1430
1369 sched_in = machine__findnew_thread(machine, -1, next_pid); 1431 sched_in = map__findnew_thread(sched, machine, -1, next_pid);
1370 if (sched_in == NULL) 1432 if (sched_in == NULL)
1371 return -1; 1433 return -1;
1372 1434
@@ -1400,26 +1462,52 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1400 new_shortname = 1; 1462 new_shortname = 1;
1401 } 1463 }
1402 1464
1403 for (cpu = 0; cpu <= sched->max_cpu; cpu++) { 1465 for (i = 0; i < cpus_nr; i++) {
1466 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1467 struct thread *curr_thread = sched->curr_thread[cpu];
1468 const char *pid_color = color;
1469 const char *cpu_color = color;
1470
1471 if (curr_thread && thread__has_color(curr_thread))
1472 pid_color = COLOR_PIDS;
1473
1474 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, cpu))
1475 continue;
1476
1477 if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu))
1478 cpu_color = COLOR_CPUS;
1479
1404 if (cpu != this_cpu) 1480 if (cpu != this_cpu)
1405 printf(" "); 1481 color_fprintf(stdout, cpu_color, " ");
1406 else 1482 else
1407 printf("*"); 1483 color_fprintf(stdout, cpu_color, "*");
1408 1484
1409 if (sched->curr_thread[cpu]) 1485 if (sched->curr_thread[cpu])
1410 printf("%2s ", sched->curr_thread[cpu]->shortname); 1486 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname);
1411 else 1487 else
1412 printf(" "); 1488 color_fprintf(stdout, color, " ");
1413 } 1489 }
1414 1490
1415 printf(" %12.6f secs ", (double)timestamp/1e9); 1491 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
1492 goto out;
1493
1494 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9);
1416 if (new_shortname) { 1495 if (new_shortname) {
1417 printf("%s => %s:%d\n", 1496 const char *pid_color = color;
1497
1498 if (thread__has_color(sched_in))
1499 pid_color = COLOR_PIDS;
1500
1501 color_fprintf(stdout, pid_color, "%s => %s:%d",
1418 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid); 1502 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
1419 } else {
1420 printf("\n");
1421 } 1503 }
1422 1504
1505 if (sched->map.comp && new_cpu)
1506 color_fprintf(stdout, color, " (CPU %d)", this_cpu);
1507
1508out:
1509 color_fprintf(stdout, color, "\n");
1510
1423 thread__put(sched_in); 1511 thread__put(sched_in);
1424 1512
1425 return 0; 1513 return 0;
@@ -1675,9 +1763,75 @@ static int perf_sched__lat(struct perf_sched *sched)
1675 return 0; 1763 return 0;
1676} 1764}
1677 1765
1766static int setup_map_cpus(struct perf_sched *sched)
1767{
1768 struct cpu_map *map;
1769
1770 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1771
1772 if (sched->map.comp) {
1773 sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int));
1774 if (!sched->map.comp_cpus)
1775 return -1;
1776 }
1777
1778 if (!sched->map.cpus_str)
1779 return 0;
1780
1781 map = cpu_map__new(sched->map.cpus_str);
1782 if (!map) {
1783 pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
1784 return -1;
1785 }
1786
1787 sched->map.cpus = map;
1788 return 0;
1789}
1790
1791static int setup_color_pids(struct perf_sched *sched)
1792{
1793 struct thread_map *map;
1794
1795 if (!sched->map.color_pids_str)
1796 return 0;
1797
1798 map = thread_map__new_by_tid_str(sched->map.color_pids_str);
1799 if (!map) {
1800 pr_err("failed to get thread map from %s\n", sched->map.color_pids_str);
1801 return -1;
1802 }
1803
1804 sched->map.color_pids = map;
1805 return 0;
1806}
1807
1808static int setup_color_cpus(struct perf_sched *sched)
1809{
1810 struct cpu_map *map;
1811
1812 if (!sched->map.color_cpus_str)
1813 return 0;
1814
1815 map = cpu_map__new(sched->map.color_cpus_str);
1816 if (!map) {
1817 pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
1818 return -1;
1819 }
1820
1821 sched->map.color_cpus = map;
1822 return 0;
1823}
1824
1678static int perf_sched__map(struct perf_sched *sched) 1825static int perf_sched__map(struct perf_sched *sched)
1679{ 1826{
1680 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1827 if (setup_map_cpus(sched))
1828 return -1;
1829
1830 if (setup_color_pids(sched))
1831 return -1;
1832
1833 if (setup_color_cpus(sched))
1834 return -1;
1681 1835
1682 setup_pager(); 1836 setup_pager();
1683 if (perf_sched__read_events(sched)) 1837 if (perf_sched__read_events(sched))
@@ -1831,6 +1985,17 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1831 "dump raw trace in ASCII"), 1985 "dump raw trace in ASCII"),
1832 OPT_END() 1986 OPT_END()
1833 }; 1987 };
1988 const struct option map_options[] = {
1989 OPT_BOOLEAN(0, "compact", &sched.map.comp,
1990 "map output in compact mode"),
1991 OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids",
1992 "highlight given pids in map"),
1993 OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus",
1994 "highlight given CPUs in map"),
1995 OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus",
1996 "display given CPUs in map"),
1997 OPT_END()
1998 };
1834 const char * const latency_usage[] = { 1999 const char * const latency_usage[] = {
1835 "perf sched latency [<options>]", 2000 "perf sched latency [<options>]",
1836 NULL 2001 NULL
@@ -1839,6 +2004,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1839 "perf sched replay [<options>]", 2004 "perf sched replay [<options>]",
1840 NULL 2005 NULL
1841 }; 2006 };
2007 const char * const map_usage[] = {
2008 "perf sched map [<options>]",
2009 NULL
2010 };
1842 const char *const sched_subcommands[] = { "record", "latency", "map", 2011 const char *const sched_subcommands[] = { "record", "latency", "map",
1843 "replay", "script", NULL }; 2012 "replay", "script", NULL };
1844 const char *sched_usage[] = { 2013 const char *sched_usage[] = {
@@ -1887,6 +2056,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1887 setup_sorting(&sched, latency_options, latency_usage); 2056 setup_sorting(&sched, latency_options, latency_usage);
1888 return perf_sched__lat(&sched); 2057 return perf_sched__lat(&sched);
1889 } else if (!strcmp(argv[0], "map")) { 2058 } else if (!strcmp(argv[0], "map")) {
2059 if (argc) {
2060 argc = parse_options(argc, argv, map_options, map_usage, 0);
2061 if (argc)
2062 usage_with_options(map_usage, map_options);
2063 }
1890 sched.tp_handler = &map_ops; 2064 sched.tp_handler = &map_ops;
1891 setup_sorting(&sched, latency_options, latency_usage); 2065 setup_sorting(&sched, latency_options, latency_usage);
1892 return perf_sched__map(&sched); 2066 return perf_sched__map(&sched);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ddd5b79e94c2..838c0bc38105 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -317,19 +317,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
317 317
318 output[type].print_ip_opts = 0; 318 output[type].print_ip_opts = 0;
319 if (PRINT_FIELD(IP)) 319 if (PRINT_FIELD(IP))
320 output[type].print_ip_opts |= PRINT_IP_OPT_IP; 320 output[type].print_ip_opts |= EVSEL__PRINT_IP;
321 321
322 if (PRINT_FIELD(SYM)) 322 if (PRINT_FIELD(SYM))
323 output[type].print_ip_opts |= PRINT_IP_OPT_SYM; 323 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
324 324
325 if (PRINT_FIELD(DSO)) 325 if (PRINT_FIELD(DSO))
326 output[type].print_ip_opts |= PRINT_IP_OPT_DSO; 326 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
327 327
328 if (PRINT_FIELD(SYMOFFSET)) 328 if (PRINT_FIELD(SYMOFFSET))
329 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; 329 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
330 330
331 if (PRINT_FIELD(SRCLINE)) 331 if (PRINT_FIELD(SRCLINE))
332 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; 332 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
333} 333}
334 334
335/* 335/*
@@ -574,9 +574,9 @@ static void print_sample_bts(struct perf_sample *sample,
574 printf("\n"); 574 printf("\n");
575 } else { 575 } else {
576 printf(" "); 576 printf(" ");
577 if (print_opts & PRINT_IP_OPT_SRCLINE) { 577 if (print_opts & EVSEL__PRINT_SRCLINE) {
578 print_srcline_last = true; 578 print_srcline_last = true;
579 print_opts &= ~PRINT_IP_OPT_SRCLINE; 579 print_opts &= ~EVSEL__PRINT_SRCLINE;
580 } 580 }
581 } 581 }
582 perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts, 582 perf_evsel__fprintf_sym(evsel, sample, al, 0, print_opts,
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 2ec53edcf649..d49c131bb5de 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2114,6 +2114,28 @@ out_put:
2114 return err; 2114 return err;
2115} 2115}
2116 2116
2117static int trace__fprintf_callchain(struct trace *trace, struct perf_evsel *evsel,
2118 struct perf_sample *sample)
2119{
2120 struct addr_location al;
2121 /* TODO: user-configurable print_opts */
2122 const unsigned int print_opts = EVSEL__PRINT_SYM |
2123 EVSEL__PRINT_DSO |
2124 EVSEL__PRINT_UNKNOWN_AS_ADDR;
2125
2126 if (sample->callchain == NULL)
2127 return 0;
2128
2129 if (machine__resolve(trace->host, &al, sample) < 0) {
2130 pr_err("Problem processing %s callchain, skipping...\n",
2131 perf_evsel__name(evsel));
2132 return 0;
2133 }
2134
2135 return perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts,
2136 scripting_max_stack, trace->output);
2137}
2138
2117static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 2139static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2118 union perf_event *event __maybe_unused, 2140 union perf_event *event __maybe_unused,
2119 struct perf_sample *sample) 2141 struct perf_sample *sample)
@@ -2193,21 +2215,7 @@ signed_print:
2193 2215
2194 fputc('\n', trace->output); 2216 fputc('\n', trace->output);
2195 2217
2196 if (sample->callchain) { 2218 trace__fprintf_callchain(trace, evsel, sample);
2197 struct addr_location al;
2198 /* TODO: user-configurable print_opts */
2199 const unsigned int print_opts = PRINT_IP_OPT_SYM |
2200 PRINT_IP_OPT_DSO |
2201 PRINT_IP_OPT_UNKNOWN_AS_ADDR;
2202
2203 if (machine__resolve(trace->host, &al, sample) < 0) {
2204 pr_err("problem processing %d event, skipping it.\n",
2205 event->header.type);
2206 goto out_put;
2207 }
2208 perf_evsel__fprintf_callchain(evsel, sample, &al, 38, print_opts,
2209 scripting_max_stack, trace->output);
2210 }
2211out: 2219out:
2212 ttrace->entry_pending = false; 2220 ttrace->entry_pending = false;
2213 err = 0; 2221 err = 0;
@@ -2355,6 +2363,9 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2355 } 2363 }
2356 2364
2357 fprintf(trace->output, ")\n"); 2365 fprintf(trace->output, ")\n");
2366
2367 trace__fprintf_callchain(trace, evsel, sample);
2368
2358 return 0; 2369 return 0;
2359} 2370}
2360 2371
@@ -3333,6 +3344,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3333 goto out; 3344 goto out;
3334 } 3345 }
3335 3346
3347 err = -1;
3348
3336 if (trace.trace_pgfaults) { 3349 if (trace.trace_pgfaults) {
3337 trace.opts.sample_address = true; 3350 trace.opts.sample_address = true;
3338 trace.opts.sample_time = true; 3351 trace.opts.sample_time = true;
@@ -3357,6 +3370,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3357 return -1; 3370 return -1;
3358 } 3371 }
3359 3372
3373 if (!trace.trace_syscalls && ev_qualifier_str) {
3374 pr_err("The -e option can't be used with --no-syscalls.\n");
3375 goto out;
3376 }
3377
3360 if (output_name != NULL) { 3378 if (output_name != NULL) {
3361 err = trace__open_output(&trace, output_name); 3379 err = trace__open_output(&trace, output_name);
3362 if (err < 0) { 3380 if (err < 0) {
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 9bcf2bed3a6d..02d801670f30 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -587,3 +587,15 @@ int cpu__setup_cpunode_map(void)
587 closedir(dir1); 587 closedir(dir1);
588 return 0; 588 return 0;
589} 589}
590
591bool cpu_map__has(struct cpu_map *cpus, int cpu)
592{
593 int i;
594
595 for (i = 0; i < cpus->nr; ++i) {
596 if (cpus->map[i] == cpu)
597 return true;
598 }
599
600 return false;
601}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 81a2562aaa2b..1a0a35073ce1 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -66,4 +66,6 @@ int cpu__get_node(int cpu);
66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, 66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
67 int (*f)(struct cpu_map *map, int cpu, void *data), 67 int (*f)(struct cpu_map *map, int cpu, void *data),
68 void *data); 68 void *data);
69
70bool cpu_map__has(struct cpu_map *cpus, int cpu);
69#endif /* __PERF_CPUMAP_H */ 71#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d475a4ec8b57..6e86598682be 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2343,6 +2343,137 @@ out:
2343 return ++printed; 2343 return ++printed;
2344} 2344}
2345 2345
2346int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample,
2347 struct addr_location *al, int left_alignment,
2348 unsigned int print_opts, unsigned int stack_depth,
2349 FILE *fp)
2350{
2351 int printed = 0;
2352 struct callchain_cursor_node *node;
2353 int print_ip = print_opts & EVSEL__PRINT_IP;
2354 int print_sym = print_opts & EVSEL__PRINT_SYM;
2355 int print_dso = print_opts & EVSEL__PRINT_DSO;
2356 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
2357 int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
2358 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
2359 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
2360 char s = print_oneline ? ' ' : '\t';
2361
2362 if (sample->callchain) {
2363 struct addr_location node_al;
2364
2365 if (thread__resolve_callchain(al->thread, evsel,
2366 sample, NULL, NULL,
2367 stack_depth) != 0) {
2368 if (verbose)
2369 error("Failed to resolve callchain. Skipping\n");
2370 return printed;
2371 }
2372 callchain_cursor_commit(&callchain_cursor);
2373
2374 if (print_symoffset)
2375 node_al = *al;
2376
2377 while (stack_depth) {
2378 u64 addr = 0;
2379
2380 node = callchain_cursor_current(&callchain_cursor);
2381 if (!node)
2382 break;
2383
2384 if (node->sym && node->sym->ignore)
2385 goto next;
2386
2387 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
2388
2389 if (print_ip)
2390 printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
2391
2392 if (node->map)
2393 addr = node->map->map_ip(node->map, node->ip);
2394
2395 if (print_sym) {
2396 printed += fprintf(fp, " ");
2397 node_al.addr = addr;
2398 node_al.map = node->map;
2399
2400 if (print_symoffset) {
2401 printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
2402 print_unknown_as_addr, fp);
2403 } else {
2404 printed += __symbol__fprintf_symname(node->sym, &node_al,
2405 print_unknown_as_addr, fp);
2406 }
2407 }
2408
2409 if (print_dso) {
2410 printed += fprintf(fp, " (");
2411 printed += map__fprintf_dsoname(node->map, fp);
2412 printed += fprintf(fp, ")");
2413 }
2414
2415 if (print_srcline)
2416 printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
2417
2418 if (!print_oneline)
2419 printed += fprintf(fp, "\n");
2420
2421 stack_depth--;
2422next:
2423 callchain_cursor_advance(&callchain_cursor);
2424 }
2425 }
2426
2427 return printed;
2428}
2429
2430int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample,
2431 struct addr_location *al, int left_alignment,
2432 unsigned int print_opts, unsigned int stack_depth,
2433 FILE *fp)
2434{
2435 int printed = 0;
2436 int print_ip = print_opts & EVSEL__PRINT_IP;
2437 int print_sym = print_opts & EVSEL__PRINT_SYM;
2438 int print_dso = print_opts & EVSEL__PRINT_DSO;
2439 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
2440 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
2441 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
2442
2443 if (symbol_conf.use_callchain && sample->callchain) {
2444 printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment,
2445 print_opts, stack_depth, fp);
2446 } else if (!(al->sym && al->sym->ignore)) {
2447 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
2448
2449 if (print_ip)
2450 printed += fprintf(fp, "%16" PRIx64, sample->ip);
2451
2452 if (print_sym) {
2453 printed += fprintf(fp, " ");
2454 if (print_symoffset) {
2455 printed += __symbol__fprintf_symname_offs(al->sym, al,
2456 print_unknown_as_addr, fp);
2457 } else {
2458 printed += __symbol__fprintf_symname(al->sym, al,
2459 print_unknown_as_addr, fp);
2460 }
2461 }
2462
2463 if (print_dso) {
2464 printed += fprintf(fp, " (");
2465 printed += map__fprintf_dsoname(al->map, fp);
2466 printed += fprintf(fp, ")");
2467 }
2468
2469 if (print_srcline)
2470 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
2471 }
2472
2473 return printed;
2474}
2475
2476
2346bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 2477bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2347 char *msg, size_t msgsize) 2478 char *msg, size_t msgsize)
2348{ 2479{
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 1bd6c2e02dfa..36edd3c91d5c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -387,12 +387,25 @@ struct perf_attr_details {
387int perf_evsel__fprintf(struct perf_evsel *evsel, 387int perf_evsel__fprintf(struct perf_evsel *evsel,
388 struct perf_attr_details *details, FILE *fp); 388 struct perf_attr_details *details, FILE *fp);
389 389
390#define EVSEL__PRINT_IP (1<<0)
391#define EVSEL__PRINT_SYM (1<<1)
392#define EVSEL__PRINT_DSO (1<<2)
393#define EVSEL__PRINT_SYMOFFSET (1<<3)
394#define EVSEL__PRINT_ONELINE (1<<4)
395#define EVSEL__PRINT_SRCLINE (1<<5)
396#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
397
390int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, 398int perf_evsel__fprintf_callchain(struct perf_evsel *evsel,
391 struct perf_sample *sample, 399 struct perf_sample *sample,
392 struct addr_location *al, int left_alignment, 400 struct addr_location *al, int left_alignment,
393 unsigned int print_opts, 401 unsigned int print_opts,
394 unsigned int stack_depth, FILE *fp); 402 unsigned int stack_depth, FILE *fp);
395 403
404int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample,
405 struct addr_location *al, int left_alignment,
406 unsigned int print_opts, unsigned int stack_depth,
407 FILE *fp);
408
396bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 409bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
397 char *msg, size_t msgsize); 410 char *msg, size_t msgsize);
398int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 411int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 0516d06a2741..91d4528d71fa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1953,136 +1953,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1953 return NULL; 1953 return NULL;
1954} 1954}
1955 1955
1956int perf_evsel__fprintf_callchain(struct perf_evsel *evsel, struct perf_sample *sample,
1957 struct addr_location *al, int left_alignment,
1958 unsigned int print_opts, unsigned int stack_depth,
1959 FILE *fp)
1960{
1961 int printed = 0;
1962 struct callchain_cursor_node *node;
1963 int print_ip = print_opts & PRINT_IP_OPT_IP;
1964 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1965 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1966 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1967 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1968 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1969 int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR;
1970 char s = print_oneline ? ' ' : '\t';
1971
1972 if (sample->callchain) {
1973 struct addr_location node_al;
1974
1975 if (thread__resolve_callchain(al->thread, evsel,
1976 sample, NULL, NULL,
1977 stack_depth) != 0) {
1978 if (verbose)
1979 error("Failed to resolve callchain. Skipping\n");
1980 return printed;
1981 }
1982 callchain_cursor_commit(&callchain_cursor);
1983
1984 if (print_symoffset)
1985 node_al = *al;
1986
1987 while (stack_depth) {
1988 u64 addr = 0;
1989
1990 node = callchain_cursor_current(&callchain_cursor);
1991 if (!node)
1992 break;
1993
1994 if (node->sym && node->sym->ignore)
1995 goto next;
1996
1997 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
1998
1999 if (print_ip)
2000 printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
2001
2002 if (node->map)
2003 addr = node->map->map_ip(node->map, node->ip);
2004
2005 if (print_sym) {
2006 printed += fprintf(fp, " ");
2007 node_al.addr = addr;
2008 node_al.map = node->map;
2009
2010 if (print_symoffset) {
2011 printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
2012 print_unknown_as_addr, fp);
2013 } else {
2014 printed += __symbol__fprintf_symname(node->sym, &node_al,
2015 print_unknown_as_addr, fp);
2016 }
2017 }
2018
2019 if (print_dso) {
2020 printed += fprintf(fp, " (");
2021 printed += map__fprintf_dsoname(node->map, fp);
2022 printed += fprintf(fp, ")");
2023 }
2024
2025 if (print_srcline)
2026 printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
2027
2028 if (!print_oneline)
2029 printed += fprintf(fp, "\n");
2030
2031 stack_depth--;
2032next:
2033 callchain_cursor_advance(&callchain_cursor);
2034 }
2035 }
2036
2037 return printed;
2038}
2039
2040int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample,
2041 struct addr_location *al, int left_alignment,
2042 unsigned int print_opts, unsigned int stack_depth,
2043 FILE *fp)
2044{
2045 int printed = 0;
2046 int print_ip = print_opts & PRINT_IP_OPT_IP;
2047 int print_sym = print_opts & PRINT_IP_OPT_SYM;
2048 int print_dso = print_opts & PRINT_IP_OPT_DSO;
2049 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
2050 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
2051 int print_unknown_as_addr = print_opts & PRINT_IP_OPT_UNKNOWN_AS_ADDR;
2052
2053 if (symbol_conf.use_callchain && sample->callchain) {
2054 printed += perf_evsel__fprintf_callchain(evsel, sample, al, left_alignment,
2055 print_opts, stack_depth, fp);
2056 } else if (!(al->sym && al->sym->ignore)) {
2057 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
2058
2059 if (print_ip)
2060 printed += fprintf(fp, "%16" PRIx64, sample->ip);
2061
2062 if (print_sym) {
2063 printed += fprintf(fp, " ");
2064 if (print_symoffset) {
2065 printed += __symbol__fprintf_symname_offs(al->sym, al,
2066 print_unknown_as_addr, fp);
2067 } else {
2068 printed += __symbol__fprintf_symname(al->sym, al,
2069 print_unknown_as_addr, fp);
2070 }
2071 }
2072
2073 if (print_dso) {
2074 printed += fprintf(fp, " (");
2075 printed += map__fprintf_dsoname(al->map, fp);
2076 printed += fprintf(fp, ")");
2077 }
2078
2079 if (print_srcline)
2080 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
2081 }
2082
2083 return printed;
2084}
2085
2086int perf_session__cpu_bitmap(struct perf_session *session, 1956int perf_session__cpu_bitmap(struct perf_session *session,
2087 const char *cpu_list, unsigned long *cpu_bitmap) 1957 const char *cpu_list, unsigned long *cpu_bitmap)
2088{ 1958{
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 4257fac56618..4bd758553450 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -36,14 +36,6 @@ struct perf_session {
36 struct perf_tool *tool; 36 struct perf_tool *tool;
37}; 37};
38 38
39#define PRINT_IP_OPT_IP (1<<0)
40#define PRINT_IP_OPT_SYM (1<<1)
41#define PRINT_IP_OPT_DSO (1<<2)
42#define PRINT_IP_OPT_SYMOFFSET (1<<3)
43#define PRINT_IP_OPT_ONELINE (1<<4)
44#define PRINT_IP_OPT_SRCLINE (1<<5)
45#define PRINT_IP_OPT_UNKNOWN_AS_ADDR (1<<6)
46
47struct perf_tool; 39struct perf_tool;
48 40
49struct perf_session *perf_session__new(struct perf_data_file *file, 41struct perf_session *perf_session__new(struct perf_data_file *file,
@@ -105,11 +97,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
105struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 97struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
106 unsigned int type); 98 unsigned int type);
107 99
108int perf_evsel__fprintf_sym(struct perf_evsel *evsel, struct perf_sample *sample,
109 struct addr_location *al, int left_alignment,
110 unsigned int print_opts, unsigned int stack_depth,
111 FILE *fp);
112
113int perf_session__cpu_bitmap(struct perf_session *session, 100int perf_session__cpu_bitmap(struct perf_session *session,
114 const char *cpu_list, unsigned long *cpu_bitmap); 101 const char *cpu_list, unsigned long *cpu_bitmap);
115 102
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 267112b4e3db..5654fe15e036 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void)
260 return threads; 260 return threads;
261} 261}
262 262
263static struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 263struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
264{ 264{
265 struct thread_map *threads = NULL, *nt; 265 struct thread_map *threads = NULL, *nt;
266 int ntasks = 0; 266 int ntasks = 0;
@@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event)
436 436
437 return threads; 437 return threads;
438} 438}
439
440bool thread_map__has(struct thread_map *threads, pid_t pid)
441{
442 int i;
443
444 for (i = 0; i < threads->nr; ++i) {
445 if (threads->map[i].pid == pid)
446 return true;
447 }
448
449 return false;
450}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 85e4c7c4fbde..bd3b971588da 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map);
31struct thread_map *thread_map__new_str(const char *pid, 31struct thread_map *thread_map__new_str(const char *pid,
32 const char *tid, uid_t uid); 32 const char *tid, uid_t uid);
33 33
34struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
35
34size_t thread_map__fprintf(struct thread_map *threads, FILE *fp); 36size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
35 37
36static inline int thread_map__nr(struct thread_map *threads) 38static inline int thread_map__nr(struct thread_map *threads)
@@ -55,4 +57,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread)
55} 57}
56 58
57void thread_map__read_comms(struct thread_map *threads); 59void thread_map__read_comms(struct thread_map *threads);
60bool thread_map__has(struct thread_map *threads, pid_t pid);
58#endif /* __PERF_THREAD_MAP_H */ 61#endif /* __PERF_THREAD_MAP_H */