Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
[linux-2.6-block.git] / tools / perf / builtin-sched.c
index 9ac0a495c954e5793ddfe9e0e42ef4ee995bec56..d7176830b9b2fb789a61565acf113987ac59fd99 100644 (file)
@@ -66,7 +66,7 @@ struct sched_atom {
        struct task_desc        *wakee;
 };
 
-#define TASK_STATE_TO_CHAR_STR "RSDTtZX"
+#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP"
 
 enum thread_state {
        THREAD_SLEEPING = 0,
@@ -149,7 +149,6 @@ struct perf_sched {
        unsigned long    nr_runs;
        unsigned long    nr_timestamps;
        unsigned long    nr_unordered_timestamps;
-       unsigned long    nr_state_machine_bugs;
        unsigned long    nr_context_switch_bugs;
        unsigned long    nr_events;
        unsigned long    nr_lost_chunks;
@@ -1007,17 +1006,12 @@ static int latency_wakeup_event(struct perf_sched *sched,
                                struct perf_sample *sample,
                                struct machine *machine)
 {
-       const u32 pid     = perf_evsel__intval(evsel, sample, "pid"),
-                 success = perf_evsel__intval(evsel, sample, "success");
+       const u32 pid     = perf_evsel__intval(evsel, sample, "pid");
        struct work_atoms *atoms;
        struct work_atom *atom;
        struct thread *wakee;
        u64 timestamp = sample->time;
 
-       /* Note for later, it may be interesting to observe the failing cases */
-       if (!success)
-               return 0;
-
        wakee = machine__findnew_thread(machine, 0, pid);
        atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
        if (!atoms) {
@@ -1037,12 +1031,18 @@ static int latency_wakeup_event(struct perf_sched *sched,
        atom = list_entry(atoms->work_list.prev, struct work_atom, list);
 
        /*
+        * As we do not guarantee the wakeup event happens when
+        * task is out of run queue, also may happen when task is
+        * on run queue and wakeup only change ->state to TASK_RUNNING,
+        * then we should not set the ->wake_up_time when wake up a
+        * task which is on run queue.
+        *
         * You WILL be missing events if you've recorded only
         * one CPU, or are only looking at only one, so don't
-        * make useless noise.
+        * skip in this case.
         */
        if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING)
-               sched->nr_state_machine_bugs++;
+               return 0;
 
        sched->nr_timestamps++;
        if (atom->sched_out_time > timestamp) {
@@ -1266,9 +1266,8 @@ static int process_sched_wakeup_event(struct perf_tool *tool,
 static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
                            struct perf_sample *sample, struct machine *machine)
 {
-       const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"),
-                 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
-       struct thread *sched_out __maybe_unused, *sched_in;
+       const u32 next_pid = perf_evsel__intval(evsel, sample, "next_pid");
+       struct thread *sched_in;
        int new_shortname;
        u64 timestamp0, timestamp = sample->time;
        s64 delta;
@@ -1291,7 +1290,6 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
                return -1;
        }
 
-       sched_out = machine__findnew_thread(machine, 0, prev_pid);
        sched_in = machine__findnew_thread(machine, 0, next_pid);
 
        sched->curr_thread[this_cpu] = sched_in;
@@ -1300,17 +1298,25 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
 
        new_shortname = 0;
        if (!sched_in->shortname[0]) {
-               sched_in->shortname[0] = sched->next_shortname1;
-               sched_in->shortname[1] = sched->next_shortname2;
-
-               if (sched->next_shortname1 < 'Z') {
-                       sched->next_shortname1++;
+               if (!strcmp(thread__comm_str(sched_in), "swapper")) {
+                       /*
+                        * Don't allocate a letter-number for swapper:0
+                        * as a shortname. Instead, we use '.' for it.
+                        */
+                       sched_in->shortname[0] = '.';
+                       sched_in->shortname[1] = ' ';
                } else {
-                       sched->next_shortname1='A';
-                       if (sched->next_shortname2 < '9') {
-                               sched->next_shortname2++;
+                       sched_in->shortname[0] = sched->next_shortname1;
+                       sched_in->shortname[1] = sched->next_shortname2;
+
+                       if (sched->next_shortname1 < 'Z') {
+                               sched->next_shortname1++;
                        } else {
-                               sched->next_shortname2='0';
+                               sched->next_shortname1 = 'A';
+                               if (sched->next_shortname2 < '9')
+                                       sched->next_shortname2++;
+                               else
+                                       sched->next_shortname2 = '0';
                        }
                }
                new_shortname = 1;
@@ -1322,12 +1328,9 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
                else
                        printf("*");
 
-               if (sched->curr_thread[cpu]) {
-                       if (sched->curr_thread[cpu]->tid)
-                               printf("%2s ", sched->curr_thread[cpu]->shortname);
-                       else
-                               printf(".  ");
-               } else
+               if (sched->curr_thread[cpu])
+                       printf("%2s ", sched->curr_thread[cpu]->shortname);
+               else
                        printf("   ");
        }
 
@@ -1496,14 +1499,6 @@ static void print_bad_events(struct perf_sched *sched)
                        (double)sched->nr_lost_events/(double)sched->nr_events * 100.0,
                        sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks);
        }
-       if (sched->nr_state_machine_bugs && sched->nr_timestamps) {
-               printf("  INFO: %.3f%% state machine bugs (%ld out of %ld)",
-                       (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0,
-                       sched->nr_state_machine_bugs, sched->nr_timestamps);
-               if (sched->nr_lost_events)
-                       printf(" (due to lost events?)");
-               printf("\n");
-       }
        if (sched->nr_context_switch_bugs && sched->nr_timestamps) {
                printf("  INFO: %.3f%% context switch bugs (%ld out of %ld)",
                        (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)
                "-e", "sched:sched_stat_runtime",
                "-e", "sched:sched_process_fork",
                "-e", "sched:sched_wakeup",
+               "-e", "sched:sched_wakeup_new",
                "-e", "sched:sched_migrate_task",
        };
 
@@ -1713,8 +1709,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
                "perf sched replay [<options>]",
                NULL
        };
-       const char * const sched_usage[] = {
-               "perf sched [<options>] {record|latency|map|replay|script}",
+       const char *const sched_subcommands[] = { "record", "latency", "map",
+                                                 "replay", "script", NULL };
+       const char *sched_usage[] = {
+               NULL,
                NULL
        };
        struct trace_sched_handler lat_ops  = {
@@ -1736,8 +1734,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
        for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++)
                sched.curr_pid[i] = -1;
 
-       argc = parse_options(argc, argv, sched_options, sched_usage,
-                            PARSE_OPT_STOP_AT_NON_OPTION);
+       argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands,
+                                       sched_usage, PARSE_OPT_STOP_AT_NON_OPTION);
        if (!argc)
                usage_with_options(sched_usage, sched_options);