diff options
-rw-r--r-- | tools/perf/builtin-sched.c | 152 |
1 files changed, 134 insertions, 18 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index c66e6a321371..6ec4f51d536b 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -57,7 +57,7 @@ static u64 sample_type; | |||
57 | 57 | ||
58 | #define BUG_ON(x) assert(!(x)) | 58 | #define BUG_ON(x) assert(!(x)) |
59 | 59 | ||
60 | #define DEBUG 1 | 60 | #define DEBUG 0 |
61 | 61 | ||
62 | typedef unsigned long long nsec_t; | 62 | typedef unsigned long long nsec_t; |
63 | 63 | ||
@@ -238,15 +238,14 @@ static struct sched_event *last_event(struct task_desc *task) | |||
238 | } | 238 | } |
239 | 239 | ||
240 | static void | 240 | static void |
241 | add_sched_event_run(struct task_desc *task, nsec_t timestamp, | 241 | add_sched_event_run(struct task_desc *task, nsec_t timestamp, u64 duration) |
242 | unsigned long duration) | ||
243 | { | 242 | { |
244 | struct sched_event *event, *curr_event = last_event(task); | 243 | struct sched_event *event, *curr_event = last_event(task); |
245 | 244 | ||
246 | /* | 245 | /* |
247 | * optimize an existing RUN event by merging this one | 246 | * optimize an existing RUN event by merging this one |
248 | * to it: | 247 | * to it: |
249 | */ | 248 | */ |
250 | if (curr_event && curr_event->type == SCHED_EVENT_RUN) { | 249 | if (curr_event && curr_event->type == SCHED_EVENT_RUN) { |
251 | nr_run_events_optimized++; | 250 | nr_run_events_optimized++; |
252 | curr_event->duration += duration; | 251 | curr_event->duration += duration; |
@@ -376,7 +375,7 @@ void parse_line(char *line) | |||
376 | dprintk("parsed: %s - %ld %Ld: %s - <%s %ld> (%ld %ld)\n", | 375 | dprintk("parsed: %s - %ld %Ld: %s - <%s %ld> (%ld %ld)\n", |
377 | comm, | 376 | comm, |
378 | pid, | 377 | pid, |
379 | timestamp, | 378 | timestamp, |
380 | func_str, | 379 | func_str, |
381 | comm2, | 380 | comm2, |
382 | pid2, | 381 | pid2, |
@@ -429,7 +428,7 @@ static void add_cross_task_wakeups(void) | |||
429 | } | 428 | } |
430 | 429 | ||
431 | static void | 430 | static void |
432 | process_sched_event(struct task_desc *this_task, struct sched_event *event) | 431 | process_sched_event(struct task_desc *this_task __used, struct sched_event *event) |
433 | { | 432 | { |
434 | int ret = 0; | 433 | int ret = 0; |
435 | nsec_t now; | 434 | nsec_t now; |
@@ -744,9 +743,9 @@ static void run_one_test(void) | |||
744 | 743 | ||
745 | #if 0 | 744 | #if 0 |
746 | /* | 745 | /* |
747 | * rusage statistics done by the parent, these are less | 746 | * rusage statistics done by the parent, these are less |
748 | * accurate than the sum_exec_runtime based statistics: | 747 | * accurate than the sum_exec_runtime based statistics: |
749 | */ | 748 | */ |
750 | printk(" [%0.2f / %0.2f]", | 749 | printk(" [%0.2f / %0.2f]", |
751 | (double)parent_cpu_usage/1e6, | 750 | (double)parent_cpu_usage/1e6, |
752 | (double)runavg_parent_cpu_usage/1e6); | 751 | (double)runavg_parent_cpu_usage/1e6); |
@@ -798,16 +797,128 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head) | |||
798 | return 0; | 797 | return 0; |
799 | } | 798 | } |
800 | 799 | ||
801 | static void process_sched_wakeup_event(struct event *event, | 800 | struct trace_wakeup_event { |
801 | u32 size; | ||
802 | |||
803 | u16 common_type; | ||
804 | u8 common_flags; | ||
805 | u8 common_preempt_count; | ||
806 | u32 common_pid; | ||
807 | u32 common_tgid; | ||
808 | |||
809 | char comm[16]; | ||
810 | u32 pid; | ||
811 | |||
812 | u32 prio; | ||
813 | u32 success; | ||
814 | u32 cpu; | ||
815 | }; | ||
816 | |||
817 | static void | ||
818 | process_sched_wakeup_event(struct trace_wakeup_event *wakeup_event, struct event *event, | ||
802 | int cpu __used, u64 timestamp __used, struct thread *thread __used) | 819 | int cpu __used, u64 timestamp __used, struct thread *thread __used) |
803 | { | 820 | { |
821 | struct task_desc *waker, *wakee; | ||
822 | |||
804 | printf("sched_wakeup event %p\n", event); | 823 | printf("sched_wakeup event %p\n", event); |
824 | |||
825 | printf(" ... pid %d woke up %s/%d\n", | ||
826 | wakeup_event->common_pid, | ||
827 | wakeup_event->comm, | ||
828 | wakeup_event->pid); | ||
829 | |||
830 | waker = register_pid(wakeup_event->common_pid, "<unknown>"); | ||
831 | wakee = register_pid(wakeup_event->pid, wakeup_event->comm); | ||
832 | |||
833 | add_sched_event_wakeup(waker, timestamp, wakee); | ||
805 | } | 834 | } |
806 | 835 | ||
807 | static void process_sched_switch_event(struct event *event, | 836 | struct trace_switch_event { |
837 | u32 size; | ||
838 | |||
839 | u16 common_type; | ||
840 | u8 common_flags; | ||
841 | u8 common_preempt_count; | ||
842 | u32 common_pid; | ||
843 | u32 common_tgid; | ||
844 | |||
845 | char prev_comm[16]; | ||
846 | u32 prev_pid; | ||
847 | u32 prev_prio; | ||
848 | u64 prev_state; | ||
849 | char next_comm[16]; | ||
850 | u32 next_pid; | ||
851 | u32 next_prio; | ||
852 | }; | ||
853 | |||
854 | #define MAX_CPUS 4096 | ||
855 | |||
856 | unsigned long cpu_last_switched[MAX_CPUS]; | ||
857 | |||
858 | static void | ||
859 | process_sched_switch_event(struct trace_switch_event *switch_event, struct event *event, | ||
808 | int cpu __used, u64 timestamp __used, struct thread *thread __used) | 860 | int cpu __used, u64 timestamp __used, struct thread *thread __used) |
809 | { | 861 | { |
862 | struct task_desc *prev, *next; | ||
863 | u64 timestamp0; | ||
864 | s64 delta; | ||
865 | |||
810 | printf("sched_switch event %p\n", event); | 866 | printf("sched_switch event %p\n", event); |
867 | if (cpu >= MAX_CPUS || cpu < 0) | ||
868 | return; | ||
869 | |||
870 | timestamp0 = cpu_last_switched[cpu]; | ||
871 | if (timestamp0) | ||
872 | delta = timestamp - timestamp0; | ||
873 | else | ||
874 | delta = 0; | ||
875 | |||
876 | if (delta < 0) | ||
877 | die("hm, delta: %Ld < 0 ?\n", delta); | ||
878 | |||
879 | printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n", | ||
880 | switch_event->prev_comm, switch_event->prev_pid, | ||
881 | switch_event->next_comm, switch_event->next_pid, | ||
882 | delta); | ||
883 | |||
884 | prev = register_pid(switch_event->prev_pid, switch_event->prev_comm); | ||
885 | next = register_pid(switch_event->next_pid, switch_event->next_comm); | ||
886 | |||
887 | cpu_last_switched[cpu] = timestamp; | ||
888 | |||
889 | add_sched_event_run(prev, timestamp, delta); | ||
890 | } | ||
891 | |||
892 | struct trace_fork_event { | ||
893 | u32 size; | ||
894 | |||
895 | u16 common_type; | ||
896 | u8 common_flags; | ||
897 | u8 common_preempt_count; | ||
898 | u32 common_pid; | ||
899 | u32 common_tgid; | ||
900 | |||
901 | char parent_comm[16]; | ||
902 | u32 parent_pid; | ||
903 | char child_comm[16]; | ||
904 | u32 child_pid; | ||
905 | }; | ||
906 | |||
907 | static void | ||
908 | process_sched_fork_event(struct trace_fork_event *fork_event, struct event *event, | ||
909 | int cpu __used, u64 timestamp __used, struct thread *thread __used) | ||
910 | { | ||
911 | printf("sched_fork event %p\n", event); | ||
912 | printf("... parent: %s/%d\n", fork_event->parent_comm, fork_event->parent_pid); | ||
913 | printf("... child: %s/%d\n", fork_event->child_comm, fork_event->child_pid); | ||
914 | register_pid(fork_event->parent_pid, fork_event->parent_comm); | ||
915 | register_pid(fork_event->child_pid, fork_event->child_comm); | ||
916 | } | ||
917 | |||
918 | static void process_sched_exit_event(struct event *event, | ||
919 | int cpu __used, u64 timestamp __used, struct thread *thread __used) | ||
920 | { | ||
921 | printf("sched_exit event %p\n", event); | ||
811 | } | 922 | } |
812 | 923 | ||
813 | static void | 924 | static void |
@@ -833,9 +944,15 @@ process_raw_event(event_t *raw_event, void *more_data, | |||
833 | raw_event->header.type, type, event->name); | 944 | raw_event->header.type, type, event->name); |
834 | 945 | ||
835 | if (!strcmp(event->name, "sched_switch")) | 946 | if (!strcmp(event->name, "sched_switch")) |
836 | process_sched_switch_event(event, cpu, timestamp, thread); | 947 | process_sched_switch_event(more_data, event, cpu, timestamp, thread); |
837 | if (!strcmp(event->name, "sched_wakeup")) | 948 | if (!strcmp(event->name, "sched_wakeup")) |
838 | process_sched_wakeup_event(event, cpu, timestamp, thread); | 949 | process_sched_wakeup_event(more_data, event, cpu, timestamp, thread); |
950 | if (!strcmp(event->name, "sched_wakeup_new")) | ||
951 | process_sched_wakeup_event(more_data, event, cpu, timestamp, thread); | ||
952 | if (!strcmp(event->name, "sched_process_fork")) | ||
953 | process_sched_fork_event(more_data, event, cpu, timestamp, thread); | ||
954 | if (!strcmp(event->name, "sched_process_exit")) | ||
955 | process_sched_exit_event(event, cpu, timestamp, thread); | ||
839 | } | 956 | } |
840 | 957 | ||
841 | static int | 958 | static int |
@@ -1053,7 +1170,7 @@ static const struct option options[] = { | |||
1053 | 1170 | ||
1054 | int cmd_sched(int argc, const char **argv, const char *prefix __used) | 1171 | int cmd_sched(int argc, const char **argv, const char *prefix __used) |
1055 | { | 1172 | { |
1056 | long nr_iterations = LONG_MAX, i; | 1173 | long nr_iterations = 10, i; |
1057 | 1174 | ||
1058 | symbol__init(); | 1175 | symbol__init(); |
1059 | page_size = getpagesize(); | 1176 | page_size = getpagesize(); |
@@ -1068,8 +1185,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used) | |||
1068 | usage_with_options(annotate_usage, options); | 1185 | usage_with_options(annotate_usage, options); |
1069 | } | 1186 | } |
1070 | 1187 | ||
1071 | 1188 | // setup_pager(); | |
1072 | setup_pager(); | ||
1073 | 1189 | ||
1074 | calibrate_run_measurement_overhead(); | 1190 | calibrate_run_measurement_overhead(); |
1075 | calibrate_sleep_measurement_overhead(); | 1191 | calibrate_sleep_measurement_overhead(); |