diff options
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r-- | tools/perf/builtin-sched.c | 80 |
1 files changed, 39 insertions, 41 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index 9ac0a495c954..d7176830b9b2 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -66,7 +66,7 @@ struct sched_atom { | |||
66 | struct task_desc *wakee; | 66 | struct task_desc *wakee; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | #define TASK_STATE_TO_CHAR_STR "RSDTtZX" | 69 | #define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" |
70 | 70 | ||
71 | enum thread_state { | 71 | enum thread_state { |
72 | THREAD_SLEEPING = 0, | 72 | THREAD_SLEEPING = 0, |
@@ -149,7 +149,6 @@ struct perf_sched { | |||
149 | unsigned long nr_runs; | 149 | unsigned long nr_runs; |
150 | unsigned long nr_timestamps; | 150 | unsigned long nr_timestamps; |
151 | unsigned long nr_unordered_timestamps; | 151 | unsigned long nr_unordered_timestamps; |
152 | unsigned long nr_state_machine_bugs; | ||
153 | unsigned long nr_context_switch_bugs; | 152 | unsigned long nr_context_switch_bugs; |
154 | unsigned long nr_events; | 153 | unsigned long nr_events; |
155 | unsigned long nr_lost_chunks; | 154 | unsigned long nr_lost_chunks; |
@@ -1007,17 +1006,12 @@ static int latency_wakeup_event(struct perf_sched *sched, | |||
1007 | struct perf_sample *sample, | 1006 | struct perf_sample *sample, |
1008 | struct machine *machine) | 1007 | struct machine *machine) |
1009 | { | 1008 | { |
1010 | const u32 pid = perf_evsel__intval(evsel, sample, "pid"), | 1009 | const u32 pid = perf_evsel__intval(evsel, sample, "pid"); |
1011 | success = perf_evsel__intval(evsel, sample, "success"); | ||
1012 | struct work_atoms *atoms; | 1010 | struct work_atoms *atoms; |
1013 | struct work_atom *atom; | 1011 | struct work_atom *atom; |
1014 | struct thread *wakee; | 1012 | struct thread *wakee; |
1015 | u64 timestamp = sample->time; | 1013 | u64 timestamp = sample->time; |
1016 | 1014 | ||
1017 | /* Note for later, it may be interesting to observe the failing cases */ | ||
1018 | if (!success) | ||
1019 | return 0; | ||
1020 | |||
1021 | wakee = machine__findnew_thread(machine, 0, pid); | 1015 | wakee = machine__findnew_thread(machine, 0, pid); |
1022 | atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); | 1016 | atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); |
1023 | if (!atoms) { | 1017 | if (!atoms) { |
@@ -1037,12 +1031,18 @@ static int latency_wakeup_event(struct perf_sched *sched, | |||
1037 | atom = list_entry(atoms->work_list.prev, struct work_atom, list); | 1031 | atom = list_entry(atoms->work_list.prev, struct work_atom, list); |
1038 | 1032 | ||
1039 | /* | 1033 | /* |
1034 | * As we do not guarantee the wakeup event happens when | ||
1035 | * task is out of run queue, also may happen when task is | ||
1036 | * on run queue and wakeup only change ->state to TASK_RUNNING, | ||
1037 | * then we should not set the ->wake_up_time when wake up a | ||
1038 | * task which is on run queue. | ||
1039 | * | ||
1040 | * You WILL be missing events if you've recorded only | 1040 | * You WILL be missing events if you've recorded only |
1041 | * one CPU, or are only looking at only one, so don't | 1041 | * one CPU, or are only looking at only one, so don't |
1042 | * make useless noise. | 1042 | * skip in this case. |
1043 | */ | 1043 | */ |
1044 | if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) | 1044 | if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) |
1045 | sched->nr_state_machine_bugs++; | 1045 | return 0; |
1046 | 1046 | ||
1047 | sched->nr_timestamps++; | 1047 | sched->nr_timestamps++; |
1048 | if (atom->sched_out_time > timestamp) { | 1048 | if (atom->sched_out_time > timestamp) { |
@@ -1266,9 +1266,8 @@ static int process_sched_wakeup_event(struct perf_tool *tool, | |||
1266 | static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, | 1266 | static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, |
1267 | struct perf_sample *sample, struct machine *machine) | 1267 | struct perf_sample *sample, struct machine *machine) |
1268 | { | 1268 | { |
1269 | const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), | 1269 | const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid"); |
1270 | next_pid = perf_evsel__intval(evsel, sample, "next_pid"); | 1270 | struct thread *sched_in; |
1271 | struct thread *sched_out __maybe_unused, *sched_in; | ||
1272 | int new_shortname; | 1271 | int new_shortname; |
1273 | u64 timestamp0, timestamp = sample->time; | 1272 | u64 timestamp0, timestamp = sample->time; |
1274 | s64 delta; | 1273 | s64 delta; |
@@ -1291,7 +1290,6 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, | |||
1291 | return -1; | 1290 | return -1; |
1292 | } | 1291 | } |
1293 | 1292 | ||
1294 | sched_out = machine__findnew_thread(machine, 0, prev_pid); | ||
1295 | sched_in = machine__findnew_thread(machine, 0, next_pid); | 1293 | sched_in = machine__findnew_thread(machine, 0, next_pid); |
1296 | 1294 | ||
1297 | sched->curr_thread[this_cpu] = sched_in; | 1295 | sched->curr_thread[this_cpu] = sched_in; |
@@ -1300,17 +1298,25 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, | |||
1300 | 1298 | ||
1301 | new_shortname = 0; | 1299 | new_shortname = 0; |
1302 | if (!sched_in->shortname[0]) { | 1300 | if (!sched_in->shortname[0]) { |
1303 | sched_in->shortname[0] = sched->next_shortname1; | 1301 | if (!strcmp(thread__comm_str(sched_in), "swapper")) { |
1304 | sched_in->shortname[1] = sched->next_shortname2; | 1302 | /* |
1305 | 1303 | * Don't allocate a letter-number for swapper:0 | |
1306 | if (sched->next_shortname1 < 'Z') { | 1304 | * as a shortname. Instead, we use '.' for it. |
1307 | sched->next_shortname1++; | 1305 | */ |
1306 | sched_in->shortname[0] = '.'; | ||
1307 | sched_in->shortname[1] = ' '; | ||
1308 | } else { | 1308 | } else { |
1309 | sched->next_shortname1='A'; | 1309 | sched_in->shortname[0] = sched->next_shortname1; |
1310 | if (sched->next_shortname2 < '9') { | 1310 | sched_in->shortname[1] = sched->next_shortname2; |
1311 | sched->next_shortname2++; | 1311 | |
1312 | if (sched->next_shortname1 < 'Z') { | ||
1313 | sched->next_shortname1++; | ||
1312 | } else { | 1314 | } else { |
1313 | sched->next_shortname2='0'; | 1315 | sched->next_shortname1 = 'A'; |
1316 | if (sched->next_shortname2 < '9') | ||
1317 | sched->next_shortname2++; | ||
1318 | else | ||
1319 | sched->next_shortname2 = '0'; | ||
1314 | } | 1320 | } |
1315 | } | 1321 | } |
1316 | new_shortname = 1; | 1322 | new_shortname = 1; |
@@ -1322,12 +1328,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, | |||
1322 | else | 1328 | else |
1323 | printf("*"); | 1329 | printf("*"); |
1324 | 1330 | ||
1325 | if (sched->curr_thread[cpu]) { | 1331 | if (sched->curr_thread[cpu]) |
1326 | if (sched->curr_thread[cpu]->tid) | 1332 | printf("%2s ", sched->curr_thread[cpu]->shortname); |
1327 | printf("%2s ", sched->curr_thread[cpu]->shortname); | 1333 | else |
1328 | else | ||
1329 | printf(". "); | ||
1330 | } else | ||
1331 | printf(" "); | 1334 | printf(" "); |
1332 | } | 1335 | } |
1333 | 1336 | ||
@@ -1496,14 +1499,6 @@ static void print_bad_events(struct perf_sched *sched) | |||
1496 | (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, | 1499 | (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, |
1497 | sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); | 1500 | sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); |
1498 | } | 1501 | } |
1499 | if (sched->nr_state_machine_bugs && sched->nr_timestamps) { | ||
1500 | printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)", | ||
1501 | (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0, | ||
1502 | sched->nr_state_machine_bugs, sched->nr_timestamps); | ||
1503 | if (sched->nr_lost_events) | ||
1504 | printf(" (due to lost events?)"); | ||
1505 | printf("\n"); | ||
1506 | } | ||
1507 | if (sched->nr_context_switch_bugs && sched->nr_timestamps) { | 1502 | if (sched->nr_context_switch_bugs && sched->nr_timestamps) { |
1508 | printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", | 1503 | printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", |
1509 | (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, | 1504 | (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, |
@@ -1635,6 +1630,7 @@ static int __cmd_record(int argc, const char **argv) | |||
1635 | "-e", "sched:sched_stat_runtime", | 1630 | "-e", "sched:sched_stat_runtime", |
1636 | "-e", "sched:sched_process_fork", | 1631 | "-e", "sched:sched_process_fork", |
1637 | "-e", "sched:sched_wakeup", | 1632 | "-e", "sched:sched_wakeup", |
1633 | "-e", "sched:sched_wakeup_new", | ||
1638 | "-e", "sched:sched_migrate_task", | 1634 | "-e", "sched:sched_migrate_task", |
1639 | }; | 1635 | }; |
1640 | 1636 | ||
@@ -1713,8 +1709,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1713 | "perf sched replay [<options>]", | 1709 | "perf sched replay [<options>]", |
1714 | NULL | 1710 | NULL |
1715 | }; | 1711 | }; |
1716 | const char * const sched_usage[] = { | 1712 | const char *const sched_subcommands[] = { "record", "latency", "map", |
1717 | "perf sched [<options>] {record|latency|map|replay|script}", | 1713 | "replay", "script", NULL }; |
1714 | const char *sched_usage[] = { | ||
1715 | NULL, | ||
1718 | NULL | 1716 | NULL |
1719 | }; | 1717 | }; |
1720 | struct trace_sched_handler lat_ops = { | 1718 | struct trace_sched_handler lat_ops = { |
@@ -1736,8 +1734,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1736 | for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++) | 1734 | for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++) |
1737 | sched.curr_pid[i] = -1; | 1735 | sched.curr_pid[i] = -1; |
1738 | 1736 | ||
1739 | argc = parse_options(argc, argv, sched_options, sched_usage, | 1737 | argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands, |
1740 | PARSE_OPT_STOP_AT_NON_OPTION); | 1738 | sched_usage, PARSE_OPT_STOP_AT_NON_OPTION); |
1741 | if (!argc) | 1739 | if (!argc) |
1742 | usage_with_options(sched_usage, sched_options); | 1740 | usage_with_options(sched_usage, sched_options); |
1743 | 1741 | ||