aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r--tools/perf/builtin-sched.c80
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
71enum thread_state { 71enum 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,
1266static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, 1266static 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