diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-10-14 15:43:42 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-15 04:42:39 -0400 |
commit | cda48461c7fb8431a99b7960480f5f42cc1a5324 (patch) | |
tree | 89afa42fb7136ac1086d1736529f59cfe4ac1ce3 | |
parent | 0d1da915c76838c9ee7af7cdefbcb2bae9424161 (diff) |
perf tools: Add latency format to trace output
Add the irqs disabled, preemption count, need resched, and other
info that is shown in the latency format of ftrace.
# perf trace -l
perf-16457 2..s2. 53636.260344: kmem_cache_free: call_site=ffffffff811198f
perf-16457 2..s2. 53636.264330: kmem_cache_free: call_site=ffffffff811198f
perf-16457 2d.s4. 53636.300006: kmem_cache_free: call_site=ffffffff810d889
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <20091014194400.076588953@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | tools/perf/builtin-trace.c | 2 | ||||
-rw-r--r-- | tools/perf/util/trace-event-parse.c | 120 | ||||
-rw-r--r-- | tools/perf/util/trace-event.h | 11 |
3 files changed, 114 insertions, 19 deletions
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index ccf867dbab5c..ce8459ac2845 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -144,6 +144,8 @@ static const struct option options[] = { | |||
144 | "dump raw trace in ASCII"), | 144 | "dump raw trace in ASCII"), |
145 | OPT_BOOLEAN('v', "verbose", &verbose, | 145 | OPT_BOOLEAN('v', "verbose", &verbose, |
146 | "be more verbose (show symbol address, etc)"), | 146 | "be more verbose (show symbol address, etc)"), |
147 | OPT_BOOLEAN('l', "latency", &latency_format, | ||
148 | "show latency attributes (irqs/preemption disabled, etc)"), | ||
147 | OPT_END() | 149 | OPT_END() |
148 | }; | 150 | }; |
149 | 151 | ||
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index c174765d4056..fde1a434d630 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -40,6 +40,8 @@ int header_page_size_size; | |||
40 | int header_page_data_offset; | 40 | int header_page_data_offset; |
41 | int header_page_data_size; | 41 | int header_page_data_size; |
42 | 42 | ||
43 | int latency_format; | ||
44 | |||
43 | static char *input_buf; | 45 | static char *input_buf; |
44 | static unsigned long long input_buf_ptr; | 46 | static unsigned long long input_buf_ptr; |
45 | static unsigned long long input_buf_siz; | 47 | static unsigned long long input_buf_siz; |
@@ -1928,37 +1930,67 @@ static int get_common_info(const char *type, int *offset, int *size) | |||
1928 | return 0; | 1930 | return 0; |
1929 | } | 1931 | } |
1930 | 1932 | ||
1931 | int trace_parse_common_type(void *data) | 1933 | static int __parse_common(void *data, int *size, int *offset, |
1934 | char *name) | ||
1932 | { | 1935 | { |
1933 | static int type_offset; | ||
1934 | static int type_size; | ||
1935 | int ret; | 1936 | int ret; |
1936 | 1937 | ||
1937 | if (!type_size) { | 1938 | if (!*size) { |
1938 | ret = get_common_info("common_type", | 1939 | ret = get_common_info(name, offset, size); |
1939 | &type_offset, | ||
1940 | &type_size); | ||
1941 | if (ret < 0) | 1940 | if (ret < 0) |
1942 | return ret; | 1941 | return ret; |
1943 | } | 1942 | } |
1944 | return read_size(data + type_offset, type_size); | 1943 | return read_size(data + *offset, *size); |
1944 | } | ||
1945 | |||
1946 | int trace_parse_common_type(void *data) | ||
1947 | { | ||
1948 | static int type_offset; | ||
1949 | static int type_size; | ||
1950 | |||
1951 | return __parse_common(data, &type_size, &type_offset, | ||
1952 | (char *)"common_type"); | ||
1945 | } | 1953 | } |
1946 | 1954 | ||
1947 | static int parse_common_pid(void *data) | 1955 | static int parse_common_pid(void *data) |
1948 | { | 1956 | { |
1949 | static int pid_offset; | 1957 | static int pid_offset; |
1950 | static int pid_size; | 1958 | static int pid_size; |
1959 | |||
1960 | return __parse_common(data, &pid_size, &pid_offset, | ||
1961 | (char *)"common_pid"); | ||
1962 | } | ||
1963 | |||
1964 | static int parse_common_pc(void *data) | ||
1965 | { | ||
1966 | static int pc_offset; | ||
1967 | static int pc_size; | ||
1968 | |||
1969 | return __parse_common(data, &pc_size, &pc_offset, | ||
1970 | (char *)"common_preempt_count"); | ||
1971 | } | ||
1972 | |||
1973 | static int parse_common_flags(void *data) | ||
1974 | { | ||
1975 | static int flags_offset; | ||
1976 | static int flags_size; | ||
1977 | |||
1978 | return __parse_common(data, &flags_size, &flags_offset, | ||
1979 | (char *)"common_flags"); | ||
1980 | } | ||
1981 | |||
1982 | static int parse_common_lock_depth(void *data) | ||
1983 | { | ||
1984 | static int ld_offset; | ||
1985 | static int ld_size; | ||
1951 | int ret; | 1986 | int ret; |
1952 | 1987 | ||
1953 | if (!pid_size) { | 1988 | ret = __parse_common(data, &ld_size, &ld_offset, |
1954 | ret = get_common_info("common_pid", | 1989 | (char *)"common_lock_depth"); |
1955 | &pid_offset, | 1990 | if (ret < 0) |
1956 | &pid_size); | 1991 | return -1; |
1957 | if (ret < 0) | ||
1958 | return ret; | ||
1959 | } | ||
1960 | 1992 | ||
1961 | return read_size(data + pid_offset, pid_size); | 1993 | return ret; |
1962 | } | 1994 | } |
1963 | 1995 | ||
1964 | struct event *trace_find_event(int id) | 1996 | struct event *trace_find_event(int id) |
@@ -2525,6 +2557,41 @@ static inline int log10_cpu(int nb) | |||
2525 | return 1; | 2557 | return 1; |
2526 | } | 2558 | } |
2527 | 2559 | ||
2560 | static void print_lat_fmt(void *data, int size __unused) | ||
2561 | { | ||
2562 | unsigned int lat_flags; | ||
2563 | unsigned int pc; | ||
2564 | int lock_depth; | ||
2565 | int hardirq; | ||
2566 | int softirq; | ||
2567 | |||
2568 | lat_flags = parse_common_flags(data); | ||
2569 | pc = parse_common_pc(data); | ||
2570 | lock_depth = parse_common_lock_depth(data); | ||
2571 | |||
2572 | hardirq = lat_flags & TRACE_FLAG_HARDIRQ; | ||
2573 | softirq = lat_flags & TRACE_FLAG_SOFTIRQ; | ||
2574 | |||
2575 | printf("%c%c%c", | ||
2576 | (lat_flags & TRACE_FLAG_IRQS_OFF) ? 'd' : | ||
2577 | (lat_flags & TRACE_FLAG_IRQS_NOSUPPORT) ? | ||
2578 | 'X' : '.', | ||
2579 | (lat_flags & TRACE_FLAG_NEED_RESCHED) ? | ||
2580 | 'N' : '.', | ||
2581 | (hardirq && softirq) ? 'H' : | ||
2582 | hardirq ? 'h' : softirq ? 's' : '.'); | ||
2583 | |||
2584 | if (pc) | ||
2585 | printf("%x", pc); | ||
2586 | else | ||
2587 | printf("."); | ||
2588 | |||
2589 | if (lock_depth < 0) | ||
2590 | printf("."); | ||
2591 | else | ||
2592 | printf("%d", lock_depth); | ||
2593 | } | ||
2594 | |||
2528 | /* taken from Linux, written by Frederic Weisbecker */ | 2595 | /* taken from Linux, written by Frederic Weisbecker */ |
2529 | static void print_graph_cpu(int cpu) | 2596 | static void print_graph_cpu(int cpu) |
2530 | { | 2597 | { |
@@ -2768,6 +2835,11 @@ pretty_print_func_ent(void *data, int size, struct event *event, | |||
2768 | 2835 | ||
2769 | printf(" | "); | 2836 | printf(" | "); |
2770 | 2837 | ||
2838 | if (latency_format) { | ||
2839 | print_lat_fmt(data, size); | ||
2840 | printf(" | "); | ||
2841 | } | ||
2842 | |||
2771 | field = find_field(event, "func"); | 2843 | field = find_field(event, "func"); |
2772 | if (!field) | 2844 | if (!field) |
2773 | die("function entry does not have func field"); | 2845 | die("function entry does not have func field"); |
@@ -2811,6 +2883,11 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event, | |||
2811 | 2883 | ||
2812 | printf(" | "); | 2884 | printf(" | "); |
2813 | 2885 | ||
2886 | if (latency_format) { | ||
2887 | print_lat_fmt(data, size); | ||
2888 | printf(" | "); | ||
2889 | } | ||
2890 | |||
2814 | field = find_field(event, "rettime"); | 2891 | field = find_field(event, "rettime"); |
2815 | if (!field) | 2892 | if (!field) |
2816 | die("can't find rettime in return graph"); | 2893 | die("can't find rettime in return graph"); |
@@ -2882,9 +2959,14 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs, | |||
2882 | return pretty_print_func_graph(data, size, event, cpu, | 2959 | return pretty_print_func_graph(data, size, event, cpu, |
2883 | pid, comm, secs, usecs); | 2960 | pid, comm, secs, usecs); |
2884 | 2961 | ||
2885 | printf("%16s-%-5d [%03d] %5lu.%09Lu: %s: ", | 2962 | if (latency_format) { |
2886 | comm, pid, cpu, | 2963 | printf("%8.8s-%-5d %3d", |
2887 | secs, nsecs, event->name); | 2964 | comm, pid, cpu); |
2965 | print_lat_fmt(data, size); | ||
2966 | } else | ||
2967 | printf("%16s-%-5d [%03d]", comm, pid, cpu); | ||
2968 | |||
2969 | printf(" %5lu.%06lu: %s: ", secs, usecs, event->name); | ||
2888 | 2970 | ||
2889 | if (event->flags & EVENT_FL_FAILED) { | 2971 | if (event->flags & EVENT_FL_FAILED) { |
2890 | printf("EVENT '%s' FAILED TO PARSE\n", | 2972 | printf("EVENT '%s' FAILED TO PARSE\n", |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index 29821acc8db6..f6637c2fa1fe 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
@@ -239,6 +239,8 @@ extern int header_page_size_size; | |||
239 | extern int header_page_data_offset; | 239 | extern int header_page_data_offset; |
240 | extern int header_page_data_size; | 240 | extern int header_page_data_size; |
241 | 241 | ||
242 | extern int latency_format; | ||
243 | |||
242 | int parse_header_page(char *buf, unsigned long size); | 244 | int parse_header_page(char *buf, unsigned long size); |
243 | int trace_parse_common_type(void *data); | 245 | int trace_parse_common_type(void *data); |
244 | struct event *trace_find_event(int id); | 246 | struct event *trace_find_event(int id); |
@@ -248,4 +250,13 @@ void *raw_field_ptr(struct event *event, const char *name, void *data); | |||
248 | 250 | ||
249 | void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); | 251 | void read_tracing_data(int fd, struct perf_event_attr *pattrs, int nb_events); |
250 | 252 | ||
253 | /* taken from kernel/trace/trace.h */ | ||
254 | enum trace_flag_type { | ||
255 | TRACE_FLAG_IRQS_OFF = 0x01, | ||
256 | TRACE_FLAG_IRQS_NOSUPPORT = 0x02, | ||
257 | TRACE_FLAG_NEED_RESCHED = 0x04, | ||
258 | TRACE_FLAG_HARDIRQ = 0x08, | ||
259 | TRACE_FLAG_SOFTIRQ = 0x10, | ||
260 | }; | ||
261 | |||
251 | #endif /* __PERF_TRACE_EVENTS_H */ | 262 | #endif /* __PERF_TRACE_EVENTS_H */ |