diff options
author | David Ahern <dsahern@gmail.com> | 2016-11-16 01:06:31 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-11-23 08:44:08 -0500 |
commit | fc1469f1b20777929a47f6f8e55bca12c6f142ac (patch) | |
tree | 2f8cb8d8c1c348363288e384fb67119102ca12ce | |
parent | 52df138caaa8daaaf4e0dc64428ef06f303a8dbf (diff) |
perf sched timehist: Add -w/--wakeups option
The -w option is to show wakeup events with timehist.
$ perf sched timehist -w
time cpu task name b/n time sch delay run time
[tid/pid] (msec) (msec) (msec)
--------------- ------ -------------------- --------- --------- ---------
2412598.429689 [0002] perf[7219] awakened: perf[7220]
2412598.429696 [0009] <idle> 0.000 0.000 0.000
2412598.429767 [0002] perf[7219] 0.000 0.000 0.000
2412598.429780 [0009] perf[7220] awakened: migration/9[53]
...
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/20161116060634.28477-6-namhyung@kernel.org
[ Add documentation based on above commit message ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/Documentation/perf-sched.txt | 4 | ||||
-rw-r--r-- | tools/perf/builtin-sched.c | 58 |
2 files changed, 58 insertions, 4 deletions
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt index 72730da307b9..9a77bc73e8a3 100644 --- a/tools/perf/Documentation/perf-sched.txt +++ b/tools/perf/Documentation/perf-sched.txt | |||
@@ -112,6 +112,10 @@ OPTIONS for 'perf sched timehist' | |||
112 | --symfs=<directory>:: | 112 | --symfs=<directory>:: |
113 | Look for files with symbols relative to this directory. | 113 | Look for files with symbols relative to this directory. |
114 | 114 | ||
115 | -w:: | ||
116 | --wakeups:: | ||
117 | Show wakeup events. | ||
118 | |||
115 | SEE ALSO | 119 | SEE ALSO |
116 | -------- | 120 | -------- |
117 | linkperf:perf-record[1] | 121 | linkperf:perf-record[1] |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 1e7d81ad5ec6..8fb7bcc2cb76 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -198,6 +198,7 @@ struct perf_sched { | |||
198 | /* options for timehist command */ | 198 | /* options for timehist command */ |
199 | bool summary; | 199 | bool summary; |
200 | bool summary_only; | 200 | bool summary_only; |
201 | bool show_wakeups; | ||
201 | u64 skipped_samples; | 202 | u64 skipped_samples; |
202 | }; | 203 | }; |
203 | 204 | ||
@@ -1807,7 +1808,8 @@ static void timehist_header(void) | |||
1807 | printf("\n"); | 1808 | printf("\n"); |
1808 | } | 1809 | } |
1809 | 1810 | ||
1810 | static void timehist_print_sample(struct perf_sample *sample, | 1811 | static void timehist_print_sample(struct perf_sched *sched, |
1812 | struct perf_sample *sample, | ||
1811 | struct thread *thread) | 1813 | struct thread *thread) |
1812 | { | 1814 | { |
1813 | struct thread_runtime *tr = thread__priv(thread); | 1815 | struct thread_runtime *tr = thread__priv(thread); |
@@ -1821,6 +1823,10 @@ static void timehist_print_sample(struct perf_sample *sample, | |||
1821 | print_sched_time(tr->dt_wait, 6); | 1823 | print_sched_time(tr->dt_wait, 6); |
1822 | print_sched_time(tr->dt_delay, 6); | 1824 | print_sched_time(tr->dt_delay, 6); |
1823 | print_sched_time(tr->dt_run, 6); | 1825 | print_sched_time(tr->dt_run, 6); |
1826 | |||
1827 | if (sched->show_wakeups) | ||
1828 | printf(" %-*s", comm_width, ""); | ||
1829 | |||
1824 | printf("\n"); | 1830 | printf("\n"); |
1825 | } | 1831 | } |
1826 | 1832 | ||
@@ -2028,12 +2034,44 @@ static bool timehist_skip_sample(struct perf_sched *sched, | |||
2028 | return rc; | 2034 | return rc; |
2029 | } | 2035 | } |
2030 | 2036 | ||
2031 | static int timehist_sched_wakeup_event(struct perf_tool *tool __maybe_unused, | 2037 | static void timehist_print_wakeup_event(struct perf_sched *sched, |
2038 | struct perf_sample *sample, | ||
2039 | struct machine *machine, | ||
2040 | struct thread *awakened) | ||
2041 | { | ||
2042 | struct thread *thread; | ||
2043 | char tstr[64]; | ||
2044 | |||
2045 | thread = machine__findnew_thread(machine, sample->pid, sample->tid); | ||
2046 | if (thread == NULL) | ||
2047 | return; | ||
2048 | |||
2049 | /* show wakeup unless both awakee and awaker are filtered */ | ||
2050 | if (timehist_skip_sample(sched, thread) && | ||
2051 | timehist_skip_sample(sched, awakened)) { | ||
2052 | return; | ||
2053 | } | ||
2054 | |||
2055 | timestamp__scnprintf_usec(sample->time, tstr, sizeof(tstr)); | ||
2056 | printf("%15s [%04d] ", tstr, sample->cpu); | ||
2057 | |||
2058 | printf(" %-*s ", comm_width, timehist_get_commstr(thread)); | ||
2059 | |||
2060 | /* dt spacer */ | ||
2061 | printf(" %9s %9s %9s ", "", "", ""); | ||
2062 | |||
2063 | printf("awakened: %s", timehist_get_commstr(awakened)); | ||
2064 | |||
2065 | printf("\n"); | ||
2066 | } | ||
2067 | |||
2068 | static int timehist_sched_wakeup_event(struct perf_tool *tool, | ||
2032 | union perf_event *event __maybe_unused, | 2069 | union perf_event *event __maybe_unused, |
2033 | struct perf_evsel *evsel, | 2070 | struct perf_evsel *evsel, |
2034 | struct perf_sample *sample, | 2071 | struct perf_sample *sample, |
2035 | struct machine *machine) | 2072 | struct machine *machine) |
2036 | { | 2073 | { |
2074 | struct perf_sched *sched = container_of(tool, struct perf_sched, tool); | ||
2037 | struct thread *thread; | 2075 | struct thread *thread; |
2038 | struct thread_runtime *tr = NULL; | 2076 | struct thread_runtime *tr = NULL; |
2039 | /* want pid of awakened task not pid in sample */ | 2077 | /* want pid of awakened task not pid in sample */ |
@@ -2050,6 +2088,10 @@ static int timehist_sched_wakeup_event(struct perf_tool *tool __maybe_unused, | |||
2050 | if (tr->ready_to_run == 0) | 2088 | if (tr->ready_to_run == 0) |
2051 | tr->ready_to_run = sample->time; | 2089 | tr->ready_to_run = sample->time; |
2052 | 2090 | ||
2091 | /* show wakeups if requested */ | ||
2092 | if (sched->show_wakeups) | ||
2093 | timehist_print_wakeup_event(sched, sample, machine, thread); | ||
2094 | |||
2053 | return 0; | 2095 | return 0; |
2054 | } | 2096 | } |
2055 | 2097 | ||
@@ -2059,12 +2101,12 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2059 | struct perf_sample *sample, | 2101 | struct perf_sample *sample, |
2060 | struct machine *machine) | 2102 | struct machine *machine) |
2061 | { | 2103 | { |
2104 | struct perf_sched *sched = container_of(tool, struct perf_sched, tool); | ||
2062 | struct addr_location al; | 2105 | struct addr_location al; |
2063 | struct thread *thread; | 2106 | struct thread *thread; |
2064 | struct thread_runtime *tr = NULL; | 2107 | struct thread_runtime *tr = NULL; |
2065 | u64 tprev; | 2108 | u64 tprev; |
2066 | int rc = 0; | 2109 | int rc = 0; |
2067 | struct perf_sched *sched = container_of(tool, struct perf_sched, tool); | ||
2068 | 2110 | ||
2069 | if (machine__resolve(machine, &al, sample) < 0) { | 2111 | if (machine__resolve(machine, &al, sample) < 0) { |
2070 | pr_err("problem processing %d event. skipping it\n", | 2112 | pr_err("problem processing %d event. skipping it\n", |
@@ -2092,7 +2134,7 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2092 | 2134 | ||
2093 | timehist_update_runtime_stats(tr, sample->time, tprev); | 2135 | timehist_update_runtime_stats(tr, sample->time, tprev); |
2094 | if (!sched->summary_only) | 2136 | if (!sched->summary_only) |
2095 | timehist_print_sample(sample, thread); | 2137 | timehist_print_sample(sched, sample, thread); |
2096 | 2138 | ||
2097 | out: | 2139 | out: |
2098 | if (tr) { | 2140 | if (tr) { |
@@ -2723,6 +2765,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2723 | "Show only syscall summary with statistics"), | 2765 | "Show only syscall summary with statistics"), |
2724 | OPT_BOOLEAN('S', "with-summary", &sched.summary, | 2766 | OPT_BOOLEAN('S', "with-summary", &sched.summary, |
2725 | "Show all syscalls and summary with statistics"), | 2767 | "Show all syscalls and summary with statistics"), |
2768 | OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"), | ||
2726 | OPT_PARENT(sched_options) | 2769 | OPT_PARENT(sched_options) |
2727 | }; | 2770 | }; |
2728 | 2771 | ||
@@ -2814,6 +2857,13 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
2814 | if (argc) | 2857 | if (argc) |
2815 | usage_with_options(timehist_usage, timehist_options); | 2858 | usage_with_options(timehist_usage, timehist_options); |
2816 | } | 2859 | } |
2860 | if (sched.show_wakeups && sched.summary_only) { | ||
2861 | pr_err(" Error: -s and -w are mutually exclusive.\n"); | ||
2862 | parse_options_usage(timehist_usage, timehist_options, "s", true); | ||
2863 | parse_options_usage(NULL, timehist_options, "w", true); | ||
2864 | return -EINVAL; | ||
2865 | } | ||
2866 | |||
2817 | return perf_sched__timehist(&sched); | 2867 | return perf_sched__timehist(&sched); |
2818 | } else { | 2868 | } else { |
2819 | usage_with_options(sched_usage, sched_options); | 2869 | usage_with_options(sched_usage, sched_options); |