aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-sched.c243
1 files changed, 165 insertions, 78 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 0215936696ed..756fe62eb046 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -14,6 +14,9 @@
14#include "util/trace-event.h" 14#include "util/trace-event.h"
15#include <sys/types.h> 15#include <sys/types.h>
16 16
17
18#define MAX_CPUS 4096
19
17static char const *input_name = "perf.data"; 20static char const *input_name = "perf.data";
18static int input; 21static int input;
19static unsigned long page_size; 22static unsigned long page_size;
@@ -27,6 +30,8 @@ static struct thread *last_match;
27static struct perf_header *header; 30static struct perf_header *header;
28static u64 sample_type; 31static u64 sample_type;
29 32
33static int replay_mode;
34
30 35
31/* 36/*
32 * Scheduler benchmarks 37 * Scheduler benchmarks
@@ -677,6 +682,27 @@ do { \
677 FILL_FIELD(ptr, common_tgid, event, data); \ 682 FILL_FIELD(ptr, common_tgid, event, data); \
678} while (0) 683} while (0)
679 684
685
686
687struct trace_switch_event {
688 u32 size;
689
690 u16 common_type;
691 u8 common_flags;
692 u8 common_preempt_count;
693 u32 common_pid;
694 u32 common_tgid;
695
696 char prev_comm[16];
697 u32 prev_pid;
698 u32 prev_prio;
699 u64 prev_state;
700 char next_comm[16];
701 u32 next_pid;
702 u32 next_prio;
703};
704
705
680struct trace_wakeup_event { 706struct trace_wakeup_event {
681 u32 size; 707 u32 size;
682 708
@@ -694,78 +720,79 @@ struct trace_wakeup_event {
694 u32 cpu; 720 u32 cpu;
695}; 721};
696 722
697static void 723struct trace_fork_event {
698process_sched_wakeup_event(struct raw_event_sample *raw, struct event *event, 724 u32 size;
699 int cpu __used, u64 timestamp __used, struct thread *thread __used)
700{
701 struct task_desc *waker, *wakee;
702 struct trace_wakeup_event wakeup_event;
703 725
704 FILL_COMMON_FIELDS(wakeup_event, event, raw->data); 726 u16 common_type;
727 u8 common_flags;
728 u8 common_preempt_count;
729 u32 common_pid;
730 u32 common_tgid;
731
732 char parent_comm[16];
733 u32 parent_pid;
734 char child_comm[16];
735 u32 child_pid;
736};
737
738struct trace_sched_handler {
739 void (*switch_event)(struct trace_switch_event *,
740 struct event *,
741 int cpu,
742 u64 timestamp,
743 struct thread *thread);
744
745 void (*wakeup_event)(struct trace_wakeup_event *,
746 struct event *,
747 int cpu,
748 u64 timestamp,
749 struct thread *thread);
750
751 void (*fork_event)(struct trace_fork_event *,
752 struct event *,
753 int cpu,
754 u64 timestamp,
755 struct thread *thread);
756};
705 757
706 FILL_ARRAY(wakeup_event, comm, event, raw->data);
707 FILL_FIELD(wakeup_event, pid, event, raw->data);
708 FILL_FIELD(wakeup_event, prio, event, raw->data);
709 FILL_FIELD(wakeup_event, success, event, raw->data);
710 FILL_FIELD(wakeup_event, cpu, event, raw->data);
711 758
759static void
760replay_wakeup_event(struct trace_wakeup_event *wakeup_event,
761 struct event *event,
762 int cpu __used,
763 u64 timestamp __used,
764 struct thread *thread __used)
765{
766 struct task_desc *waker, *wakee;
712 767
713 if (verbose) { 768 if (verbose) {
714 printf("sched_wakeup event %p\n", event); 769 printf("sched_wakeup event %p\n", event);
715 770
716 printf(" ... pid %d woke up %s/%d\n", 771 printf(" ... pid %d woke up %s/%d\n",
717 wakeup_event.common_pid, 772 wakeup_event->common_pid,
718 wakeup_event.comm, 773 wakeup_event->comm,
719 wakeup_event.pid); 774 wakeup_event->pid);
720 } 775 }
721 776
722 waker = register_pid(wakeup_event.common_pid, "<unknown>"); 777 waker = register_pid(wakeup_event->common_pid, "<unknown>");
723 wakee = register_pid(wakeup_event.pid, wakeup_event.comm); 778 wakee = register_pid(wakeup_event->pid, wakeup_event->comm);
724 779
725 add_sched_event_wakeup(waker, timestamp, wakee); 780 add_sched_event_wakeup(waker, timestamp, wakee);
726} 781}
727 782
728struct trace_switch_event { 783static unsigned long cpu_last_switched[MAX_CPUS];
729 u32 size;
730
731 u16 common_type;
732 u8 common_flags;
733 u8 common_preempt_count;
734 u32 common_pid;
735 u32 common_tgid;
736
737 char prev_comm[16];
738 u32 prev_pid;
739 u32 prev_prio;
740 u64 prev_state;
741 char next_comm[16];
742 u32 next_pid;
743 u32 next_prio;
744};
745
746#define MAX_CPUS 4096
747
748unsigned long cpu_last_switched[MAX_CPUS];
749 784
750static void 785static void
751process_sched_switch_event(struct raw_event_sample *raw, struct event *event, 786replay_switch_event(struct trace_switch_event *switch_event,
752 int cpu __used, u64 timestamp __used, struct thread *thread __used) 787 struct event *event,
788 int cpu,
789 u64 timestamp,
790 struct thread *thread __used)
753{ 791{
754 struct trace_switch_event switch_event;
755 struct task_desc *prev, *next; 792 struct task_desc *prev, *next;
756 u64 timestamp0; 793 u64 timestamp0;
757 s64 delta; 794 s64 delta;
758 795
759 FILL_COMMON_FIELDS(switch_event, event, raw->data);
760
761 FILL_ARRAY(switch_event, prev_comm, event, raw->data);
762 FILL_FIELD(switch_event, prev_pid, event, raw->data);
763 FILL_FIELD(switch_event, prev_prio, event, raw->data);
764 FILL_FIELD(switch_event, prev_state, event, raw->data);
765 FILL_ARRAY(switch_event, next_comm, event, raw->data);
766 FILL_FIELD(switch_event, next_pid, event, raw->data);
767 FILL_FIELD(switch_event, next_prio, event, raw->data);
768
769 if (verbose) 796 if (verbose)
770 printf("sched_switch event %p\n", event); 797 printf("sched_switch event %p\n", event);
771 798
@@ -783,38 +810,94 @@ process_sched_switch_event(struct raw_event_sample *raw, struct event *event,
783 810
784 if (verbose) { 811 if (verbose) {
785 printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n", 812 printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n",
786 switch_event.prev_comm, switch_event.prev_pid, 813 switch_event->prev_comm, switch_event->prev_pid,
787 switch_event.next_comm, switch_event.next_pid, 814 switch_event->next_comm, switch_event->next_pid,
788 delta); 815 delta);
789 } 816 }
790 817
791 prev = register_pid(switch_event.prev_pid, switch_event.prev_comm); 818 prev = register_pid(switch_event->prev_pid, switch_event->prev_comm);
792 next = register_pid(switch_event.next_pid, switch_event.next_comm); 819 next = register_pid(switch_event->next_pid, switch_event->next_comm);
793 820
794 cpu_last_switched[cpu] = timestamp; 821 cpu_last_switched[cpu] = timestamp;
795 822
796 add_sched_event_run(prev, timestamp, delta); 823 add_sched_event_run(prev, timestamp, delta);
797 add_sched_event_sleep(prev, timestamp, switch_event.prev_state); 824 add_sched_event_sleep(prev, timestamp, switch_event->prev_state);
798} 825}
799 826
800struct trace_fork_event {
801 u32 size;
802 827
803 u16 common_type; 828static void
804 u8 common_flags; 829replay_fork_event(struct trace_fork_event *fork_event,
805 u8 common_preempt_count; 830 struct event *event,
806 u32 common_pid; 831 int cpu __used,
807 u32 common_tgid; 832 u64 timestamp __used,
833 struct thread *thread __used)
834{
835 if (verbose) {
836 printf("sched_fork event %p\n", event);
837 printf("... parent: %s/%d\n", fork_event->parent_comm, fork_event->parent_pid);
838 printf("... child: %s/%d\n", fork_event->child_comm, fork_event->child_pid);
839 }
840 register_pid(fork_event->parent_pid, fork_event->parent_comm);
841 register_pid(fork_event->child_pid, fork_event->child_comm);
842}
808 843
809 char parent_comm[16]; 844static struct trace_sched_handler replay_ops = {
810 u32 parent_pid; 845 .wakeup_event = replay_wakeup_event,
811 char child_comm[16]; 846 .switch_event = replay_switch_event,
812 u32 child_pid; 847 .fork_event = replay_fork_event,
813}; 848};
814 849
850
851static struct trace_sched_handler *trace_handler;
852
815static void 853static void
816process_sched_fork_event(struct raw_event_sample *raw, struct event *event, 854process_sched_wakeup_event(struct raw_event_sample *raw,
817 int cpu __used, u64 timestamp __used, struct thread *thread __used) 855 struct event *event,
856 int cpu __used,
857 u64 timestamp __used,
858 struct thread *thread __used)
859{
860 struct trace_wakeup_event wakeup_event;
861
862 FILL_COMMON_FIELDS(wakeup_event, event, raw->data);
863
864 FILL_ARRAY(wakeup_event, comm, event, raw->data);
865 FILL_FIELD(wakeup_event, pid, event, raw->data);
866 FILL_FIELD(wakeup_event, prio, event, raw->data);
867 FILL_FIELD(wakeup_event, success, event, raw->data);
868 FILL_FIELD(wakeup_event, cpu, event, raw->data);
869
870 trace_handler->wakeup_event(&wakeup_event, event, cpu, timestamp, thread);
871}
872
873static void
874process_sched_switch_event(struct raw_event_sample *raw,
875 struct event *event,
876 int cpu __used,
877 u64 timestamp __used,
878 struct thread *thread __used)
879{
880 struct trace_switch_event switch_event;
881
882 FILL_COMMON_FIELDS(switch_event, event, raw->data);
883
884 FILL_ARRAY(switch_event, prev_comm, event, raw->data);
885 FILL_FIELD(switch_event, prev_pid, event, raw->data);
886 FILL_FIELD(switch_event, prev_prio, event, raw->data);
887 FILL_FIELD(switch_event, prev_state, event, raw->data);
888 FILL_ARRAY(switch_event, next_comm, event, raw->data);
889 FILL_FIELD(switch_event, next_pid, event, raw->data);
890 FILL_FIELD(switch_event, next_prio, event, raw->data);
891
892 trace_handler->switch_event(&switch_event, event, cpu, timestamp, thread);
893}
894
895static void
896process_sched_fork_event(struct raw_event_sample *raw,
897 struct event *event,
898 int cpu __used,
899 u64 timestamp __used,
900 struct thread *thread __used)
818{ 901{
819 struct trace_fork_event fork_event; 902 struct trace_fork_event fork_event;
820 903
@@ -825,17 +908,14 @@ process_sched_fork_event(struct raw_event_sample *raw, struct event *event,
825 FILL_ARRAY(fork_event, child_comm, event, raw->data); 908 FILL_ARRAY(fork_event, child_comm, event, raw->data);
826 FILL_FIELD(fork_event, child_pid, event, raw->data); 909 FILL_FIELD(fork_event, child_pid, event, raw->data);
827 910
828 if (verbose) { 911 trace_handler->fork_event(&fork_event, event, cpu, timestamp, thread);
829 printf("sched_fork event %p\n", event);
830 printf("... parent: %s/%d\n", fork_event.parent_comm, fork_event.parent_pid);
831 printf("... child: %s/%d\n", fork_event.child_comm, fork_event.child_pid);
832 }
833 register_pid(fork_event.parent_pid, fork_event.parent_comm);
834 register_pid(fork_event.child_pid, fork_event.child_comm);
835} 912}
836 913
837static void process_sched_exit_event(struct event *event, 914static void
838 int cpu __used, u64 timestamp __used, struct thread *thread __used) 915process_sched_exit_event(struct event *event,
916 int cpu __used,
917 u64 timestamp __used,
918 struct thread *thread __used)
839{ 919{
840 if (verbose) 920 if (verbose)
841 printf("sched_exit event %p\n", event); 921 printf("sched_exit event %p\n", event);
@@ -1072,6 +1152,8 @@ static const char * const annotate_usage[] = {
1072static const struct option options[] = { 1152static const struct option options[] = {
1073 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1153 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
1074 "dump raw trace in ASCII"), 1154 "dump raw trace in ASCII"),
1155 OPT_BOOLEAN('r', "replay", &replay_mode,
1156 "replay sched behaviour from traces"),
1075 OPT_BOOLEAN('v', "verbose", &verbose, 1157 OPT_BOOLEAN('v', "verbose", &verbose,
1076 "be more verbose (show symbol address, etc)"), 1158 "be more verbose (show symbol address, etc)"),
1077 OPT_END() 1159 OPT_END()
@@ -1096,6 +1178,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used)
1096 1178
1097// setup_pager(); 1179// setup_pager();
1098 1180
1181 if (replay_mode)
1182 trace_handler = &replay_ops;
1183 else /* We may need a default subcommand */
1184 die("Please select a sub command (-r)\n");
1185
1099 calibrate_run_measurement_overhead(); 1186 calibrate_run_measurement_overhead();
1100 calibrate_sleep_measurement_overhead(); 1187 calibrate_sleep_measurement_overhead();
1101 1188