diff options
-rw-r--r-- | tools/perf/builtin-sched.c | 88 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 8 |
2 files changed, 51 insertions, 45 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index cc2dbd5b50eb..b72544f2b964 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -144,7 +144,7 @@ struct task_atoms { | |||
144 | u64 total_runtime; | 144 | u64 total_runtime; |
145 | }; | 145 | }; |
146 | 146 | ||
147 | typedef int (*sort_thread_lat)(struct task_atoms *, struct task_atoms *); | 147 | typedef int (*sort_fn_t)(struct task_atoms *, struct task_atoms *); |
148 | 148 | ||
149 | static struct rb_root atom_root, sorted_atom_root; | 149 | static struct rb_root atom_root, sorted_atom_root; |
150 | 150 | ||
@@ -869,41 +869,22 @@ static struct trace_sched_handler replay_ops = { | |||
869 | .fork_event = replay_fork_event, | 869 | .fork_event = replay_fork_event, |
870 | }; | 870 | }; |
871 | 871 | ||
872 | static struct task_atoms * | ||
873 | thread_atoms_search(struct rb_root *root, struct thread *thread) | ||
874 | { | ||
875 | struct rb_node *node = root->rb_node; | ||
876 | |||
877 | while (node) { | ||
878 | struct task_atoms *atoms; | ||
879 | |||
880 | atoms = container_of(node, struct task_atoms, node); | ||
881 | if (thread->pid > atoms->thread->pid) | ||
882 | node = node->rb_left; | ||
883 | else if (thread->pid < atoms->thread->pid) | ||
884 | node = node->rb_right; | ||
885 | else { | ||
886 | return atoms; | ||
887 | } | ||
888 | } | ||
889 | return NULL; | ||
890 | } | ||
891 | |||
892 | struct sort_dimension { | 872 | struct sort_dimension { |
893 | const char *name; | 873 | const char *name; |
894 | sort_thread_lat cmp; | 874 | sort_fn_t cmp; |
895 | struct list_head list; | 875 | struct list_head list; |
896 | }; | 876 | }; |
897 | 877 | ||
898 | static LIST_HEAD(cmp_pid); | 878 | static LIST_HEAD(cmp_pid); |
899 | 879 | ||
900 | static int | 880 | static int |
901 | thread_lat_cmp(struct list_head *list, struct task_atoms *l, | 881 | thread_lat_cmp(struct list_head *list, struct task_atoms *l, struct task_atoms *r) |
902 | struct task_atoms *r) | ||
903 | { | 882 | { |
904 | struct sort_dimension *sort; | 883 | struct sort_dimension *sort; |
905 | int ret = 0; | 884 | int ret = 0; |
906 | 885 | ||
886 | BUG_ON(list_empty(list)); | ||
887 | |||
907 | list_for_each_entry(sort, list, list) { | 888 | list_for_each_entry(sort, list, list) { |
908 | ret = sort->cmp(l, r); | 889 | ret = sort->cmp(l, r); |
909 | if (ret) | 890 | if (ret) |
@@ -913,6 +894,32 @@ thread_lat_cmp(struct list_head *list, struct task_atoms *l, | |||
913 | return ret; | 894 | return ret; |
914 | } | 895 | } |
915 | 896 | ||
897 | static struct task_atoms * | ||
898 | thread_atoms_search(struct rb_root *root, struct thread *thread, | ||
899 | struct list_head *sort_list) | ||
900 | { | ||
901 | struct rb_node *node = root->rb_node; | ||
902 | struct task_atoms key = { .thread = thread }; | ||
903 | |||
904 | while (node) { | ||
905 | struct task_atoms *atoms; | ||
906 | int cmp; | ||
907 | |||
908 | atoms = container_of(node, struct task_atoms, node); | ||
909 | |||
910 | cmp = thread_lat_cmp(sort_list, &key, atoms); | ||
911 | if (cmp > 0) | ||
912 | node = node->rb_left; | ||
913 | else if (cmp < 0) | ||
914 | node = node->rb_right; | ||
915 | else { | ||
916 | BUG_ON(thread != atoms->thread); | ||
917 | return atoms; | ||
918 | } | ||
919 | } | ||
920 | return NULL; | ||
921 | } | ||
922 | |||
916 | static void | 923 | static void |
917 | __thread_latency_insert(struct rb_root *root, struct task_atoms *data, | 924 | __thread_latency_insert(struct rb_root *root, struct task_atoms *data, |
918 | struct list_head *sort_list) | 925 | struct list_head *sort_list) |
@@ -1049,18 +1056,18 @@ latency_switch_event(struct trace_switch_event *switch_event, | |||
1049 | sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); | 1056 | sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); |
1050 | sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); | 1057 | sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); |
1051 | 1058 | ||
1052 | in_atoms = thread_atoms_search(&atom_root, sched_in); | 1059 | in_atoms = thread_atoms_search(&atom_root, sched_in, &cmp_pid); |
1053 | if (!in_atoms) { | 1060 | if (!in_atoms) { |
1054 | thread_atoms_insert(sched_in); | 1061 | thread_atoms_insert(sched_in); |
1055 | in_atoms = thread_atoms_search(&atom_root, sched_in); | 1062 | in_atoms = thread_atoms_search(&atom_root, sched_in, &cmp_pid); |
1056 | if (!in_atoms) | 1063 | if (!in_atoms) |
1057 | die("in-atom: Internal tree error"); | 1064 | die("in-atom: Internal tree error"); |
1058 | } | 1065 | } |
1059 | 1066 | ||
1060 | out_atoms = thread_atoms_search(&atom_root, sched_out); | 1067 | out_atoms = thread_atoms_search(&atom_root, sched_out, &cmp_pid); |
1061 | if (!out_atoms) { | 1068 | if (!out_atoms) { |
1062 | thread_atoms_insert(sched_out); | 1069 | thread_atoms_insert(sched_out); |
1063 | out_atoms = thread_atoms_search(&atom_root, sched_out); | 1070 | out_atoms = thread_atoms_search(&atom_root, sched_out, &cmp_pid); |
1064 | if (!out_atoms) | 1071 | if (!out_atoms) |
1065 | die("out-atom: Internal tree error"); | 1072 | die("out-atom: Internal tree error"); |
1066 | } | 1073 | } |
@@ -1085,7 +1092,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event, | |||
1085 | return; | 1092 | return; |
1086 | 1093 | ||
1087 | wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); | 1094 | wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); |
1088 | atoms = thread_atoms_search(&atom_root, wakee); | 1095 | atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); |
1089 | if (!atoms) { | 1096 | if (!atoms) { |
1090 | thread_atoms_insert(wakee); | 1097 | thread_atoms_insert(wakee); |
1091 | return; | 1098 | return; |
@@ -1136,7 +1143,6 @@ static void output_lat_thread(struct task_atoms *atom_list) | |||
1136 | 1143 | ||
1137 | static int pid_cmp(struct task_atoms *l, struct task_atoms *r) | 1144 | static int pid_cmp(struct task_atoms *l, struct task_atoms *r) |
1138 | { | 1145 | { |
1139 | |||
1140 | if (l->thread->pid < r->thread->pid) | 1146 | if (l->thread->pid < r->thread->pid) |
1141 | return -1; | 1147 | return -1; |
1142 | if (l->thread->pid > r->thread->pid) | 1148 | if (l->thread->pid > r->thread->pid) |
@@ -1146,8 +1152,8 @@ static int pid_cmp(struct task_atoms *l, struct task_atoms *r) | |||
1146 | } | 1152 | } |
1147 | 1153 | ||
1148 | static struct sort_dimension pid_sort_dimension = { | 1154 | static struct sort_dimension pid_sort_dimension = { |
1149 | .name = "pid", | 1155 | .name = "pid", |
1150 | .cmp = pid_cmp, | 1156 | .cmp = pid_cmp, |
1151 | }; | 1157 | }; |
1152 | 1158 | ||
1153 | static int avg_cmp(struct task_atoms *l, struct task_atoms *r) | 1159 | static int avg_cmp(struct task_atoms *l, struct task_atoms *r) |
@@ -1172,8 +1178,8 @@ static int avg_cmp(struct task_atoms *l, struct task_atoms *r) | |||
1172 | } | 1178 | } |
1173 | 1179 | ||
1174 | static struct sort_dimension avg_sort_dimension = { | 1180 | static struct sort_dimension avg_sort_dimension = { |
1175 | .name = "avg", | 1181 | .name = "avg", |
1176 | .cmp = avg_cmp, | 1182 | .cmp = avg_cmp, |
1177 | }; | 1183 | }; |
1178 | 1184 | ||
1179 | static int max_cmp(struct task_atoms *l, struct task_atoms *r) | 1185 | static int max_cmp(struct task_atoms *l, struct task_atoms *r) |
@@ -1187,8 +1193,8 @@ static int max_cmp(struct task_atoms *l, struct task_atoms *r) | |||
1187 | } | 1193 | } |
1188 | 1194 | ||
1189 | static struct sort_dimension max_sort_dimension = { | 1195 | static struct sort_dimension max_sort_dimension = { |
1190 | .name = "max", | 1196 | .name = "max", |
1191 | .cmp = max_cmp, | 1197 | .cmp = max_cmp, |
1192 | }; | 1198 | }; |
1193 | 1199 | ||
1194 | static int switch_cmp(struct task_atoms *l, struct task_atoms *r) | 1200 | static int switch_cmp(struct task_atoms *l, struct task_atoms *r) |
@@ -1202,8 +1208,8 @@ static int switch_cmp(struct task_atoms *l, struct task_atoms *r) | |||
1202 | } | 1208 | } |
1203 | 1209 | ||
1204 | static struct sort_dimension switch_sort_dimension = { | 1210 | static struct sort_dimension switch_sort_dimension = { |
1205 | .name = "switch", | 1211 | .name = "switch", |
1206 | .cmp = switch_cmp, | 1212 | .cmp = switch_cmp, |
1207 | }; | 1213 | }; |
1208 | 1214 | ||
1209 | static int runtime_cmp(struct task_atoms *l, struct task_atoms *r) | 1215 | static int runtime_cmp(struct task_atoms *l, struct task_atoms *r) |
@@ -1217,8 +1223,8 @@ static int runtime_cmp(struct task_atoms *l, struct task_atoms *r) | |||
1217 | } | 1223 | } |
1218 | 1224 | ||
1219 | static struct sort_dimension runtime_sort_dimension = { | 1225 | static struct sort_dimension runtime_sort_dimension = { |
1220 | .name = "runtime", | 1226 | .name = "runtime", |
1221 | .cmp = runtime_cmp, | 1227 | .cmp = runtime_cmp, |
1222 | }; | 1228 | }; |
1223 | 1229 | ||
1224 | static struct sort_dimension *available_sorts[] = { | 1230 | static struct sort_dimension *available_sorts[] = { |
@@ -1666,8 +1672,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __used) | |||
1666 | argc = parse_options(argc, argv, latency_options, latency_usage, 0); | 1672 | argc = parse_options(argc, argv, latency_options, latency_usage, 0); |
1667 | if (argc) | 1673 | if (argc) |
1668 | usage_with_options(latency_usage, latency_options); | 1674 | usage_with_options(latency_usage, latency_options); |
1669 | setup_sorting(); | ||
1670 | } | 1675 | } |
1676 | setup_sorting(); | ||
1671 | __cmd_lat(); | 1677 | __cmd_lat(); |
1672 | } else if (!strncmp(argv[0], "rep", 3)) { | 1678 | } else if (!strncmp(argv[0], "rep", 3)) { |
1673 | trace_handler = &replay_ops; | 1679 | trace_handler = &replay_ops; |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 634f2809a342..665d1f3dc977 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -4,10 +4,10 @@ | |||
4 | #include "symbol.h" | 4 | #include "symbol.h" |
5 | 5 | ||
6 | struct thread { | 6 | struct thread { |
7 | struct rb_node rb_node; | 7 | struct rb_node rb_node; |
8 | struct list_head maps; | 8 | struct list_head maps; |
9 | pid_t pid; | 9 | pid_t pid; |
10 | char *comm; | 10 | char *comm; |
11 | }; | 11 | }; |
12 | 12 | ||
13 | int thread__set_comm(struct thread *self, const char *comm); | 13 | int thread__set_comm(struct thread *self, const char *comm); |