aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-trace.c
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2014-04-13 21:23:14 -0400
committerJames Morris <james.l.morris@oracle.com>2014-04-13 21:23:14 -0400
commitecd740c6f2f092b90b95fa35f757973589eaaca2 (patch)
treece02b1e18c4fc5729699251460cd8be7604d8401 /tools/perf/builtin-trace.c
parentf64410ec665479d7b4b77b7519e814253ed0f686 (diff)
parent455c6fdbd219161bd09b1165f11699d6d73de11c (diff)
Merge commit 'v3.14' into next
Diffstat (limited to 'tools/perf/builtin-trace.c')
-rw-r--r--tools/perf/builtin-trace.c130
1 files changed, 85 insertions, 45 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 8be17fc462ba..f954c26de231 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -11,6 +11,8 @@
11#include "util/intlist.h" 11#include "util/intlist.h"
12#include "util/thread_map.h" 12#include "util/thread_map.h"
13#include "util/stat.h" 13#include "util/stat.h"
14#include "trace-event.h"
15#include "util/parse-events.h"
14 16
15#include <libaudit.h> 17#include <libaudit.h>
16#include <stdlib.h> 18#include <stdlib.h>
@@ -35,6 +37,10 @@
35# define MADV_UNMERGEABLE 13 37# define MADV_UNMERGEABLE 13
36#endif 38#endif
37 39
40#ifndef EFD_SEMAPHORE
41# define EFD_SEMAPHORE 1
42#endif
43
38struct tp_field { 44struct tp_field {
39 int offset; 45 int offset;
40 union { 46 union {
@@ -144,8 +150,7 @@ static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
144 150
145static void perf_evsel__delete_priv(struct perf_evsel *evsel) 151static void perf_evsel__delete_priv(struct perf_evsel *evsel)
146{ 152{
147 free(evsel->priv); 153 zfree(&evsel->priv);
148 evsel->priv = NULL;
149 perf_evsel__delete(evsel); 154 perf_evsel__delete(evsel);
150} 155}
151 156
@@ -163,8 +168,7 @@ static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
163 return -ENOMEM; 168 return -ENOMEM;
164 169
165out_delete: 170out_delete:
166 free(evsel->priv); 171 zfree(&evsel->priv);
167 evsel->priv = NULL;
168 return -ENOENT; 172 return -ENOENT;
169} 173}
170 174
@@ -172,6 +176,10 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
172{ 176{
173 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction); 177 struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
174 178
179 /* older kernel (e.g., RHEL6) use syscalls:{enter,exit} */
180 if (evsel == NULL)
181 evsel = perf_evsel__newtp("syscalls", direction);
182
175 if (evsel) { 183 if (evsel) {
176 if (perf_evsel__init_syscall_tp(evsel, handler)) 184 if (perf_evsel__init_syscall_tp(evsel, handler))
177 goto out_delete; 185 goto out_delete;
@@ -275,6 +283,11 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
275 283
276#define SCA_STRARRAY syscall_arg__scnprintf_strarray 284#define SCA_STRARRAY syscall_arg__scnprintf_strarray
277 285
286#if defined(__i386__) || defined(__x86_64__)
287/*
288 * FIXME: Make this available to all arches as soon as the ioctl beautifier
289 * gets rewritten to support all arches.
290 */
278static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size, 291static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
279 struct syscall_arg *arg) 292 struct syscall_arg *arg)
280{ 293{
@@ -282,6 +295,7 @@ static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
282} 295}
283 296
284#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray 297#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
298#endif /* defined(__i386__) || defined(__x86_64__) */
285 299
286static size_t syscall_arg__scnprintf_fd(char *bf, size_t size, 300static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
287 struct syscall_arg *arg); 301 struct syscall_arg *arg);
@@ -811,7 +825,6 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
811 P_SIGNUM(PIPE); 825 P_SIGNUM(PIPE);
812 P_SIGNUM(ALRM); 826 P_SIGNUM(ALRM);
813 P_SIGNUM(TERM); 827 P_SIGNUM(TERM);
814 P_SIGNUM(STKFLT);
815 P_SIGNUM(CHLD); 828 P_SIGNUM(CHLD);
816 P_SIGNUM(CONT); 829 P_SIGNUM(CONT);
817 P_SIGNUM(STOP); 830 P_SIGNUM(STOP);
@@ -827,6 +840,15 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
827 P_SIGNUM(IO); 840 P_SIGNUM(IO);
828 P_SIGNUM(PWR); 841 P_SIGNUM(PWR);
829 P_SIGNUM(SYS); 842 P_SIGNUM(SYS);
843#ifdef SIGEMT
844 P_SIGNUM(EMT);
845#endif
846#ifdef SIGSTKFLT
847 P_SIGNUM(STKFLT);
848#endif
849#ifdef SIGSWI
850 P_SIGNUM(SWI);
851#endif
830 default: break; 852 default: break;
831 } 853 }
832 854
@@ -835,6 +857,10 @@ static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscal
835 857
836#define SCA_SIGNUM syscall_arg__scnprintf_signum 858#define SCA_SIGNUM syscall_arg__scnprintf_signum
837 859
860#if defined(__i386__) || defined(__x86_64__)
861/*
862 * FIXME: Make this available to all arches.
863 */
838#define TCGETS 0x5401 864#define TCGETS 0x5401
839 865
840static const char *tioctls[] = { 866static const char *tioctls[] = {
@@ -856,6 +882,7 @@ static const char *tioctls[] = {
856}; 882};
857 883
858static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); 884static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
885#endif /* defined(__i386__) || defined(__x86_64__) */
859 886
860#define STRARRAY(arg, name, array) \ 887#define STRARRAY(arg, name, array) \
861 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ 888 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
@@ -937,9 +964,16 @@ static struct syscall_fmt {
937 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 964 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
938 { .name = "ioctl", .errmsg = true, 965 { .name = "ioctl", .errmsg = true,
939 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 966 .arg_scnprintf = { [0] = SCA_FD, /* fd */
967#if defined(__i386__) || defined(__x86_64__)
968/*
969 * FIXME: Make this available to all arches.
970 */
940 [1] = SCA_STRHEXARRAY, /* cmd */ 971 [1] = SCA_STRHEXARRAY, /* cmd */
941 [2] = SCA_HEX, /* arg */ }, 972 [2] = SCA_HEX, /* arg */ },
942 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, }, 973 .arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
974#else
975 [2] = SCA_HEX, /* arg */ }, },
976#endif
943 { .name = "kill", .errmsg = true, 977 { .name = "kill", .errmsg = true,
944 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 978 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
945 { .name = "linkat", .errmsg = true, 979 { .name = "linkat", .errmsg = true,
@@ -1153,29 +1187,30 @@ struct trace {
1153 int max; 1187 int max;
1154 struct syscall *table; 1188 struct syscall *table;
1155 } syscalls; 1189 } syscalls;
1156 struct perf_record_opts opts; 1190 struct record_opts opts;
1157 struct machine *host; 1191 struct machine *host;
1158 u64 base_time; 1192 u64 base_time;
1159 bool full_time;
1160 FILE *output; 1193 FILE *output;
1161 unsigned long nr_events; 1194 unsigned long nr_events;
1162 struct strlist *ev_qualifier; 1195 struct strlist *ev_qualifier;
1163 bool not_ev_qualifier;
1164 bool live;
1165 const char *last_vfs_getname; 1196 const char *last_vfs_getname;
1166 struct intlist *tid_list; 1197 struct intlist *tid_list;
1167 struct intlist *pid_list; 1198 struct intlist *pid_list;
1199 double duration_filter;
1200 double runtime_ms;
1201 struct {
1202 u64 vfs_getname,
1203 proc_getname;
1204 } stats;
1205 bool not_ev_qualifier;
1206 bool live;
1207 bool full_time;
1168 bool sched; 1208 bool sched;
1169 bool multiple_threads; 1209 bool multiple_threads;
1170 bool summary; 1210 bool summary;
1171 bool summary_only; 1211 bool summary_only;
1172 bool show_comm; 1212 bool show_comm;
1173 bool show_tool_stats; 1213 bool show_tool_stats;
1174 double duration_filter;
1175 double runtime_ms;
1176 struct {
1177 u64 vfs_getname, proc_getname;
1178 } stats;
1179}; 1214};
1180 1215
1181static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname) 1216static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
@@ -1272,10 +1307,8 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
1272 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg); 1307 size_t printed = syscall_arg__scnprintf_fd(bf, size, arg);
1273 struct thread_trace *ttrace = arg->thread->priv; 1308 struct thread_trace *ttrace = arg->thread->priv;
1274 1309
1275 if (ttrace && fd >= 0 && fd <= ttrace->paths.max) { 1310 if (ttrace && fd >= 0 && fd <= ttrace->paths.max)
1276 free(ttrace->paths.table[fd]); 1311 zfree(&ttrace->paths.table[fd]);
1277 ttrace->paths.table[fd] = NULL;
1278 }
1279 1312
1280 return printed; 1313 return printed;
1281} 1314}
@@ -1430,11 +1463,11 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1430 sc->fmt = syscall_fmt__find(sc->name); 1463 sc->fmt = syscall_fmt__find(sc->name);
1431 1464
1432 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name); 1465 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
1433 sc->tp_format = event_format__new("syscalls", tp_name); 1466 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1434 1467
1435 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) { 1468 if (sc->tp_format == NULL && sc->fmt && sc->fmt->alias) {
1436 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias); 1469 snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->fmt->alias);
1437 sc->tp_format = event_format__new("syscalls", tp_name); 1470 sc->tp_format = trace_event__tp_format("syscalls", tp_name);
1438 } 1471 }
1439 1472
1440 if (sc->tp_format == NULL) 1473 if (sc->tp_format == NULL)
@@ -1764,8 +1797,10 @@ static int trace__process_sample(struct perf_tool *tool,
1764 if (!trace->full_time && trace->base_time == 0) 1797 if (!trace->full_time && trace->base_time == 0)
1765 trace->base_time = sample->time; 1798 trace->base_time = sample->time;
1766 1799
1767 if (handler) 1800 if (handler) {
1801 ++trace->nr_events;
1768 handler(trace, evsel, sample); 1802 handler(trace, evsel, sample);
1803 }
1769 1804
1770 return err; 1805 return err;
1771} 1806}
@@ -1800,10 +1835,11 @@ static int trace__record(int argc, const char **argv)
1800 "-R", 1835 "-R",
1801 "-m", "1024", 1836 "-m", "1024",
1802 "-c", "1", 1837 "-c", "1",
1803 "-e", "raw_syscalls:sys_enter,raw_syscalls:sys_exit", 1838 "-e",
1804 }; 1839 };
1805 1840
1806 rec_argc = ARRAY_SIZE(record_args) + argc; 1841 /* +1 is for the event string below */
1842 rec_argc = ARRAY_SIZE(record_args) + 1 + argc;
1807 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1843 rec_argv = calloc(rec_argc + 1, sizeof(char *));
1808 1844
1809 if (rec_argv == NULL) 1845 if (rec_argv == NULL)
@@ -1812,6 +1848,17 @@ static int trace__record(int argc, const char **argv)
1812 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1848 for (i = 0; i < ARRAY_SIZE(record_args); i++)
1813 rec_argv[i] = record_args[i]; 1849 rec_argv[i] = record_args[i];
1814 1850
1851 /* event string may be different for older kernels - e.g., RHEL6 */
1852 if (is_valid_tracepoint("raw_syscalls:sys_enter"))
1853 rec_argv[i] = "raw_syscalls:sys_enter,raw_syscalls:sys_exit";
1854 else if (is_valid_tracepoint("syscalls:sys_enter"))
1855 rec_argv[i] = "syscalls:sys_enter,syscalls:sys_exit";
1856 else {
1857 pr_err("Neither raw_syscalls nor syscalls events exist.\n");
1858 return -1;
1859 }
1860 i++;
1861
1815 for (j = 0; j < (unsigned int)argc; j++, i++) 1862 for (j = 0; j < (unsigned int)argc; j++, i++)
1816 rec_argv[i] = argv[j]; 1863 rec_argv[i] = argv[j];
1817 1864
@@ -1869,7 +1916,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1869 err = trace__symbols_init(trace, evlist); 1916 err = trace__symbols_init(trace, evlist);
1870 if (err < 0) { 1917 if (err < 0) {
1871 fprintf(trace->output, "Problems initializing symbol libraries!\n"); 1918 fprintf(trace->output, "Problems initializing symbol libraries!\n");
1872 goto out_delete_maps; 1919 goto out_delete_evlist;
1873 } 1920 }
1874 1921
1875 perf_evlist__config(evlist, &trace->opts); 1922 perf_evlist__config(evlist, &trace->opts);
@@ -1879,10 +1926,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1879 1926
1880 if (forks) { 1927 if (forks) {
1881 err = perf_evlist__prepare_workload(evlist, &trace->opts.target, 1928 err = perf_evlist__prepare_workload(evlist, &trace->opts.target,
1882 argv, false, false); 1929 argv, false, NULL);
1883 if (err < 0) { 1930 if (err < 0) {
1884 fprintf(trace->output, "Couldn't run the workload!\n"); 1931 fprintf(trace->output, "Couldn't run the workload!\n");
1885 goto out_delete_maps; 1932 goto out_delete_evlist;
1886 } 1933 }
1887 } 1934 }
1888 1935
@@ -1890,10 +1937,10 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
1890 if (err < 0) 1937 if (err < 0)
1891 goto out_error_open; 1938 goto out_error_open;
1892 1939
1893 err = perf_evlist__mmap(evlist, UINT_MAX, false); 1940 err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
1894 if (err < 0) { 1941 if (err < 0) {
1895 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno)); 1942 fprintf(trace->output, "Couldn't mmap the events: %s\n", strerror(errno));
1896 goto out_close_evlist; 1943 goto out_delete_evlist;
1897 } 1944 }
1898 1945
1899 perf_evlist__enable(evlist); 1946 perf_evlist__enable(evlist);
@@ -1977,11 +2024,6 @@ out_disable:
1977 } 2024 }
1978 } 2025 }
1979 2026
1980 perf_evlist__munmap(evlist);
1981out_close_evlist:
1982 perf_evlist__close(evlist);
1983out_delete_maps:
1984 perf_evlist__delete_maps(evlist);
1985out_delete_evlist: 2027out_delete_evlist:
1986 perf_evlist__delete(evlist); 2028 perf_evlist__delete(evlist);
1987out: 2029out:
@@ -2047,6 +2089,10 @@ static int trace__replay(struct trace *trace)
2047 2089
2048 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2090 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2049 "raw_syscalls:sys_enter"); 2091 "raw_syscalls:sys_enter");
2092 /* older kernels have syscalls tp versus raw_syscalls */
2093 if (evsel == NULL)
2094 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2095 "syscalls:sys_enter");
2050 if (evsel == NULL) { 2096 if (evsel == NULL) {
2051 pr_err("Data file does not have raw_syscalls:sys_enter event\n"); 2097 pr_err("Data file does not have raw_syscalls:sys_enter event\n");
2052 goto out; 2098 goto out;
@@ -2060,6 +2106,9 @@ static int trace__replay(struct trace *trace)
2060 2106
2061 evsel = perf_evlist__find_tracepoint_by_name(session->evlist, 2107 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2062 "raw_syscalls:sys_exit"); 2108 "raw_syscalls:sys_exit");
2109 if (evsel == NULL)
2110 evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
2111 "syscalls:sys_exit");
2063 if (evsel == NULL) { 2112 if (evsel == NULL) {
2064 pr_err("Data file does not have raw_syscalls:sys_exit event\n"); 2113 pr_err("Data file does not have raw_syscalls:sys_exit event\n");
2065 goto out; 2114 goto out;
@@ -2158,7 +2207,6 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2158 size_t printed = data->printed; 2207 size_t printed = data->printed;
2159 struct trace *trace = data->trace; 2208 struct trace *trace = data->trace;
2160 struct thread_trace *ttrace = thread->priv; 2209 struct thread_trace *ttrace = thread->priv;
2161 const char *color;
2162 double ratio; 2210 double ratio;
2163 2211
2164 if (ttrace == NULL) 2212 if (ttrace == NULL)
@@ -2166,17 +2214,9 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2166 2214
2167 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0; 2215 ratio = (double)ttrace->nr_events / trace->nr_events * 100.0;
2168 2216
2169 color = PERF_COLOR_NORMAL; 2217 printed += fprintf(fp, " %s (%d), ", thread__comm_str(thread), thread->tid);
2170 if (ratio > 50.0)
2171 color = PERF_COLOR_RED;
2172 else if (ratio > 25.0)
2173 color = PERF_COLOR_GREEN;
2174 else if (ratio > 5.0)
2175 color = PERF_COLOR_YELLOW;
2176
2177 printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
2178 printed += fprintf(fp, "%lu events, ", ttrace->nr_events); 2218 printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
2179 printed += color_fprintf(fp, color, "%.1f%%", ratio); 2219 printed += fprintf(fp, "%.1f%%", ratio);
2180 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); 2220 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2181 printed += thread__dump_stats(ttrace, trace, fp); 2221 printed += thread__dump_stats(ttrace, trace, fp);
2182 2222
@@ -2248,7 +2288,7 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
2248 }, 2288 },
2249 .user_freq = UINT_MAX, 2289 .user_freq = UINT_MAX,
2250 .user_interval = ULLONG_MAX, 2290 .user_interval = ULLONG_MAX,
2251 .no_delay = true, 2291 .no_buffering = true,
2252 .mmap_pages = 1024, 2292 .mmap_pages = 1024,
2253 }, 2293 },
2254 .output = stdout, 2294 .output = stdout,