diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/builtin-sched.c | 399 |
1 files changed, 184 insertions, 215 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index e01cc63b98cc..cc2dbd5b50eb 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -1,4 +1,5 @@ | |||
1 | #include "builtin.h" | 1 | #include "builtin.h" |
2 | #include "perf.h" | ||
2 | 3 | ||
3 | #include "util/util.h" | 4 | #include "util/util.h" |
4 | #include "util/cache.h" | 5 | #include "util/cache.h" |
@@ -7,15 +8,16 @@ | |||
7 | #include "util/header.h" | 8 | #include "util/header.h" |
8 | 9 | ||
9 | #include "util/parse-options.h" | 10 | #include "util/parse-options.h" |
11 | #include "util/trace-event.h" | ||
10 | 12 | ||
11 | #include "perf.h" | ||
12 | #include "util/debug.h" | 13 | #include "util/debug.h" |
13 | 14 | ||
14 | #include "util/trace-event.h" | ||
15 | #include <sys/types.h> | 15 | #include <sys/types.h> |
16 | #include <sys/prctl.h> | ||
16 | 17 | ||
17 | 18 | #include <semaphore.h> | |
18 | #define MAX_CPUS 4096 | 19 | #include <pthread.h> |
20 | #include <math.h> | ||
19 | 21 | ||
20 | static char const *input_name = "perf.data"; | 22 | static char const *input_name = "perf.data"; |
21 | static int input; | 23 | static int input; |
@@ -33,44 +35,126 @@ static u64 sample_type; | |||
33 | static char default_sort_order[] = "avg, max, switch, runtime"; | 35 | static char default_sort_order[] = "avg, max, switch, runtime"; |
34 | static char *sort_order = default_sort_order; | 36 | static char *sort_order = default_sort_order; |
35 | 37 | ||
38 | #define PR_SET_NAME 15 /* Set process name */ | ||
39 | #define MAX_CPUS 4096 | ||
36 | 40 | ||
37 | /* | 41 | #define BUG_ON(x) assert(!(x)) |
38 | * Scheduler benchmarks | ||
39 | */ | ||
40 | #include <sys/resource.h> | ||
41 | #include <sys/types.h> | ||
42 | #include <sys/stat.h> | ||
43 | #include <sys/time.h> | ||
44 | #include <sys/prctl.h> | ||
45 | 42 | ||
46 | #include <linux/unistd.h> | 43 | static u64 run_measurement_overhead; |
44 | static u64 sleep_measurement_overhead; | ||
47 | 45 | ||
48 | #include <semaphore.h> | 46 | #define COMM_LEN 20 |
49 | #include <pthread.h> | 47 | #define SYM_LEN 129 |
50 | #include <signal.h> | ||
51 | #include <values.h> | ||
52 | #include <string.h> | ||
53 | #include <unistd.h> | ||
54 | #include <stdlib.h> | ||
55 | #include <assert.h> | ||
56 | #include <fcntl.h> | ||
57 | #include <time.h> | ||
58 | #include <math.h> | ||
59 | 48 | ||
60 | #include <stdio.h> | 49 | #define MAX_PID 65536 |
61 | 50 | ||
62 | #define PR_SET_NAME 15 /* Set process name */ | 51 | static unsigned long nr_tasks; |
63 | 52 | ||
64 | #define BUG_ON(x) assert(!(x)) | 53 | struct sched_event; |
65 | 54 | ||
66 | #define DEBUG 0 | 55 | struct task_desc { |
56 | unsigned long nr; | ||
57 | unsigned long pid; | ||
58 | char comm[COMM_LEN]; | ||
67 | 59 | ||
68 | typedef unsigned long long nsec_t; | 60 | unsigned long nr_events; |
61 | unsigned long curr_event; | ||
62 | struct sched_event **events; | ||
63 | |||
64 | pthread_t thread; | ||
65 | sem_t sleep_sem; | ||
69 | 66 | ||
70 | static nsec_t run_measurement_overhead; | 67 | sem_t ready_for_work; |
71 | static nsec_t sleep_measurement_overhead; | 68 | sem_t work_done_sem; |
69 | |||
70 | u64 cpu_usage; | ||
71 | }; | ||
72 | |||
73 | enum sched_event_type { | ||
74 | SCHED_EVENT_RUN, | ||
75 | SCHED_EVENT_SLEEP, | ||
76 | SCHED_EVENT_WAKEUP, | ||
77 | }; | ||
78 | |||
79 | struct sched_event { | ||
80 | enum sched_event_type type; | ||
81 | u64 timestamp; | ||
82 | u64 duration; | ||
83 | unsigned long nr; | ||
84 | int specific_wait; | ||
85 | sem_t *wait_sem; | ||
86 | struct task_desc *wakee; | ||
87 | }; | ||
88 | |||
89 | static struct task_desc *pid_to_task[MAX_PID]; | ||
90 | |||
91 | static struct task_desc **tasks; | ||
92 | |||
93 | static pthread_mutex_t start_work_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
94 | static u64 start_time; | ||
95 | |||
96 | static pthread_mutex_t work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
72 | 97 | ||
73 | static nsec_t get_nsecs(void) | 98 | static unsigned long nr_run_events; |
99 | static unsigned long nr_sleep_events; | ||
100 | static unsigned long nr_wakeup_events; | ||
101 | |||
102 | static unsigned long nr_sleep_corrections; | ||
103 | static unsigned long nr_run_events_optimized; | ||
104 | |||
105 | static unsigned long targetless_wakeups; | ||
106 | static unsigned long multitarget_wakeups; | ||
107 | |||
108 | static u64 cpu_usage; | ||
109 | static u64 runavg_cpu_usage; | ||
110 | static u64 parent_cpu_usage; | ||
111 | static u64 runavg_parent_cpu_usage; | ||
112 | |||
113 | static unsigned long nr_runs; | ||
114 | static u64 sum_runtime; | ||
115 | static u64 sum_fluct; | ||
116 | static u64 run_avg; | ||
117 | |||
118 | static unsigned long replay_repeat = 10; | ||
119 | |||
120 | #define TASK_STATE_TO_CHAR_STR "RSDTtZX" | ||
121 | |||
122 | enum thread_state { | ||
123 | THREAD_SLEEPING = 0, | ||
124 | THREAD_WAIT_CPU, | ||
125 | THREAD_SCHED_IN, | ||
126 | THREAD_IGNORE | ||
127 | }; | ||
128 | |||
129 | struct work_atom { | ||
130 | struct list_head list; | ||
131 | enum thread_state state; | ||
132 | u64 wake_up_time; | ||
133 | u64 sched_in_time; | ||
134 | u64 runtime; | ||
135 | }; | ||
136 | |||
137 | struct task_atoms { | ||
138 | struct list_head atom_list; | ||
139 | struct thread *thread; | ||
140 | struct rb_node node; | ||
141 | u64 max_lat; | ||
142 | u64 total_lat; | ||
143 | u64 nb_atoms; | ||
144 | u64 total_runtime; | ||
145 | }; | ||
146 | |||
147 | typedef int (*sort_thread_lat)(struct task_atoms *, struct task_atoms *); | ||
148 | |||
149 | static struct rb_root atom_root, sorted_atom_root; | ||
150 | |||
151 | static u64 all_runtime; | ||
152 | static u64 all_count; | ||
153 | |||
154 | static int read_events(void); | ||
155 | |||
156 | |||
157 | static u64 get_nsecs(void) | ||
74 | { | 158 | { |
75 | struct timespec ts; | 159 | struct timespec ts; |
76 | 160 | ||
@@ -79,16 +163,16 @@ static nsec_t get_nsecs(void) | |||
79 | return ts.tv_sec * 1000000000ULL + ts.tv_nsec; | 163 | return ts.tv_sec * 1000000000ULL + ts.tv_nsec; |
80 | } | 164 | } |
81 | 165 | ||
82 | static void burn_nsecs(nsec_t nsecs) | 166 | static void burn_nsecs(u64 nsecs) |
83 | { | 167 | { |
84 | nsec_t T0 = get_nsecs(), T1; | 168 | u64 T0 = get_nsecs(), T1; |
85 | 169 | ||
86 | do { | 170 | do { |
87 | T1 = get_nsecs(); | 171 | T1 = get_nsecs(); |
88 | } while (T1 + run_measurement_overhead < T0 + nsecs); | 172 | } while (T1 + run_measurement_overhead < T0 + nsecs); |
89 | } | 173 | } |
90 | 174 | ||
91 | static void sleep_nsecs(nsec_t nsecs) | 175 | static void sleep_nsecs(u64 nsecs) |
92 | { | 176 | { |
93 | struct timespec ts; | 177 | struct timespec ts; |
94 | 178 | ||
@@ -100,7 +184,7 @@ static void sleep_nsecs(nsec_t nsecs) | |||
100 | 184 | ||
101 | static void calibrate_run_measurement_overhead(void) | 185 | static void calibrate_run_measurement_overhead(void) |
102 | { | 186 | { |
103 | nsec_t T0, T1, delta, min_delta = 1000000000ULL; | 187 | u64 T0, T1, delta, min_delta = 1000000000ULL; |
104 | int i; | 188 | int i; |
105 | 189 | ||
106 | for (i = 0; i < 10; i++) { | 190 | for (i = 0; i < 10; i++) { |
@@ -117,7 +201,7 @@ static void calibrate_run_measurement_overhead(void) | |||
117 | 201 | ||
118 | static void calibrate_sleep_measurement_overhead(void) | 202 | static void calibrate_sleep_measurement_overhead(void) |
119 | { | 203 | { |
120 | nsec_t T0, T1, delta, min_delta = 1000000000ULL; | 204 | u64 T0, T1, delta, min_delta = 1000000000ULL; |
121 | int i; | 205 | int i; |
122 | 206 | ||
123 | for (i = 0; i < 10; i++) { | 207 | for (i = 0; i < 10; i++) { |
@@ -133,67 +217,8 @@ static void calibrate_sleep_measurement_overhead(void) | |||
133 | printf("sleep measurement overhead: %Ld nsecs\n", min_delta); | 217 | printf("sleep measurement overhead: %Ld nsecs\n", min_delta); |
134 | } | 218 | } |
135 | 219 | ||
136 | #define COMM_LEN 20 | ||
137 | #define SYM_LEN 129 | ||
138 | |||
139 | #define MAX_PID 65536 | ||
140 | |||
141 | static unsigned long nr_tasks; | ||
142 | |||
143 | struct sched_event; | ||
144 | |||
145 | struct task_desc { | ||
146 | unsigned long nr; | ||
147 | unsigned long pid; | ||
148 | char comm[COMM_LEN]; | ||
149 | |||
150 | unsigned long nr_events; | ||
151 | unsigned long curr_event; | ||
152 | struct sched_event **events; | ||
153 | |||
154 | pthread_t thread; | ||
155 | sem_t sleep_sem; | ||
156 | |||
157 | sem_t ready_for_work; | ||
158 | sem_t work_done_sem; | ||
159 | |||
160 | nsec_t cpu_usage; | ||
161 | }; | ||
162 | |||
163 | enum sched_event_type { | ||
164 | SCHED_EVENT_RUN, | ||
165 | SCHED_EVENT_SLEEP, | ||
166 | SCHED_EVENT_WAKEUP, | ||
167 | }; | ||
168 | |||
169 | struct sched_event { | ||
170 | enum sched_event_type type; | ||
171 | nsec_t timestamp; | ||
172 | nsec_t duration; | ||
173 | unsigned long nr; | ||
174 | int specific_wait; | ||
175 | sem_t *wait_sem; | ||
176 | struct task_desc *wakee; | ||
177 | }; | ||
178 | |||
179 | static struct task_desc *pid_to_task[MAX_PID]; | ||
180 | |||
181 | static struct task_desc **tasks; | ||
182 | |||
183 | static pthread_mutex_t start_work_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
184 | static nsec_t start_time; | ||
185 | |||
186 | static pthread_mutex_t work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER; | ||
187 | |||
188 | static unsigned long nr_run_events; | ||
189 | static unsigned long nr_sleep_events; | ||
190 | static unsigned long nr_wakeup_events; | ||
191 | |||
192 | static unsigned long nr_sleep_corrections; | ||
193 | static unsigned long nr_run_events_optimized; | ||
194 | |||
195 | static struct sched_event * | 220 | static struct sched_event * |
196 | get_new_event(struct task_desc *task, nsec_t timestamp) | 221 | get_new_event(struct task_desc *task, u64 timestamp) |
197 | { | 222 | { |
198 | struct sched_event *event = calloc(1, sizeof(*event)); | 223 | struct sched_event *event = calloc(1, sizeof(*event)); |
199 | unsigned long idx = task->nr_events; | 224 | unsigned long idx = task->nr_events; |
@@ -221,7 +246,7 @@ static struct sched_event *last_event(struct task_desc *task) | |||
221 | } | 246 | } |
222 | 247 | ||
223 | static void | 248 | static void |
224 | add_sched_event_run(struct task_desc *task, nsec_t timestamp, u64 duration) | 249 | add_sched_event_run(struct task_desc *task, u64 timestamp, u64 duration) |
225 | { | 250 | { |
226 | struct sched_event *event, *curr_event = last_event(task); | 251 | struct sched_event *event, *curr_event = last_event(task); |
227 | 252 | ||
@@ -243,11 +268,8 @@ add_sched_event_run(struct task_desc *task, nsec_t timestamp, u64 duration) | |||
243 | nr_run_events++; | 268 | nr_run_events++; |
244 | } | 269 | } |
245 | 270 | ||
246 | static unsigned long targetless_wakeups; | ||
247 | static unsigned long multitarget_wakeups; | ||
248 | |||
249 | static void | 271 | static void |
250 | add_sched_event_wakeup(struct task_desc *task, nsec_t timestamp, | 272 | add_sched_event_wakeup(struct task_desc *task, u64 timestamp, |
251 | struct task_desc *wakee) | 273 | struct task_desc *wakee) |
252 | { | 274 | { |
253 | struct sched_event *event, *wakee_event; | 275 | struct sched_event *event, *wakee_event; |
@@ -275,7 +297,7 @@ add_sched_event_wakeup(struct task_desc *task, nsec_t timestamp, | |||
275 | } | 297 | } |
276 | 298 | ||
277 | static void | 299 | static void |
278 | add_sched_event_sleep(struct task_desc *task, nsec_t timestamp, | 300 | add_sched_event_sleep(struct task_desc *task, u64 timestamp, |
279 | u64 task_state __used) | 301 | u64 task_state __used) |
280 | { | 302 | { |
281 | struct sched_event *event = get_new_event(task, timestamp); | 303 | struct sched_event *event = get_new_event(task, timestamp); |
@@ -350,7 +372,7 @@ static void | |||
350 | process_sched_event(struct task_desc *this_task __used, struct sched_event *event) | 372 | process_sched_event(struct task_desc *this_task __used, struct sched_event *event) |
351 | { | 373 | { |
352 | int ret = 0; | 374 | int ret = 0; |
353 | nsec_t now; | 375 | u64 now; |
354 | long long delta; | 376 | long long delta; |
355 | 377 | ||
356 | now = get_nsecs(); | 378 | now = get_nsecs(); |
@@ -375,10 +397,10 @@ process_sched_event(struct task_desc *this_task __used, struct sched_event *even | |||
375 | } | 397 | } |
376 | } | 398 | } |
377 | 399 | ||
378 | static nsec_t get_cpu_usage_nsec_parent(void) | 400 | static u64 get_cpu_usage_nsec_parent(void) |
379 | { | 401 | { |
380 | struct rusage ru; | 402 | struct rusage ru; |
381 | nsec_t sum; | 403 | u64 sum; |
382 | int err; | 404 | int err; |
383 | 405 | ||
384 | err = getrusage(RUSAGE_SELF, &ru); | 406 | err = getrusage(RUSAGE_SELF, &ru); |
@@ -390,12 +412,12 @@ static nsec_t get_cpu_usage_nsec_parent(void) | |||
390 | return sum; | 412 | return sum; |
391 | } | 413 | } |
392 | 414 | ||
393 | static nsec_t get_cpu_usage_nsec_self(void) | 415 | static u64 get_cpu_usage_nsec_self(void) |
394 | { | 416 | { |
395 | char filename [] = "/proc/1234567890/sched"; | 417 | char filename [] = "/proc/1234567890/sched"; |
396 | unsigned long msecs, nsecs; | 418 | unsigned long msecs, nsecs; |
397 | char *line = NULL; | 419 | char *line = NULL; |
398 | nsec_t total = 0; | 420 | u64 total = 0; |
399 | size_t len = 0; | 421 | size_t len = 0; |
400 | ssize_t chars; | 422 | ssize_t chars; |
401 | FILE *file; | 423 | FILE *file; |
@@ -423,7 +445,7 @@ static nsec_t get_cpu_usage_nsec_self(void) | |||
423 | static void *thread_func(void *ctx) | 445 | static void *thread_func(void *ctx) |
424 | { | 446 | { |
425 | struct task_desc *this_task = ctx; | 447 | struct task_desc *this_task = ctx; |
426 | nsec_t cpu_usage_0, cpu_usage_1; | 448 | u64 cpu_usage_0, cpu_usage_1; |
427 | unsigned long i, ret; | 449 | unsigned long i, ret; |
428 | char comm2[22]; | 450 | char comm2[22]; |
429 | 451 | ||
@@ -485,14 +507,9 @@ static void create_tasks(void) | |||
485 | } | 507 | } |
486 | } | 508 | } |
487 | 509 | ||
488 | static nsec_t cpu_usage; | ||
489 | static nsec_t runavg_cpu_usage; | ||
490 | static nsec_t parent_cpu_usage; | ||
491 | static nsec_t runavg_parent_cpu_usage; | ||
492 | |||
493 | static void wait_for_tasks(void) | 510 | static void wait_for_tasks(void) |
494 | { | 511 | { |
495 | nsec_t cpu_usage_0, cpu_usage_1; | 512 | u64 cpu_usage_0, cpu_usage_1; |
496 | struct task_desc *task; | 513 | struct task_desc *task; |
497 | unsigned long i, ret; | 514 | unsigned long i, ret; |
498 | 515 | ||
@@ -543,16 +560,9 @@ static void wait_for_tasks(void) | |||
543 | } | 560 | } |
544 | } | 561 | } |
545 | 562 | ||
546 | static int read_events(void); | ||
547 | |||
548 | static unsigned long nr_runs; | ||
549 | static nsec_t sum_runtime; | ||
550 | static nsec_t sum_fluct; | ||
551 | static nsec_t run_avg; | ||
552 | |||
553 | static void run_one_test(void) | 563 | static void run_one_test(void) |
554 | { | 564 | { |
555 | nsec_t T0, T1, delta, avg_delta, fluct, std_dev; | 565 | u64 T0, T1, delta, avg_delta, fluct, std_dev; |
556 | 566 | ||
557 | T0 = get_nsecs(); | 567 | T0 = get_nsecs(); |
558 | wait_for_tasks(); | 568 | wait_for_tasks(); |
@@ -576,10 +586,6 @@ static void run_one_test(void) | |||
576 | printf("#%-3ld: %0.3f, ", | 586 | printf("#%-3ld: %0.3f, ", |
577 | nr_runs, (double)delta/1000000.0); | 587 | nr_runs, (double)delta/1000000.0); |
578 | 588 | ||
579 | #if 0 | ||
580 | printf("%0.2f +- %0.2f, ", | ||
581 | (double)avg_delta/1e6, (double)std_dev/1e6); | ||
582 | #endif | ||
583 | printf("ravg: %0.2f, ", | 589 | printf("ravg: %0.2f, ", |
584 | (double)run_avg/1e6); | 590 | (double)run_avg/1e6); |
585 | 591 | ||
@@ -605,7 +611,7 @@ static void run_one_test(void) | |||
605 | 611 | ||
606 | static void test_calibrations(void) | 612 | static void test_calibrations(void) |
607 | { | 613 | { |
608 | nsec_t T0, T1; | 614 | u64 T0, T1; |
609 | 615 | ||
610 | T0 = get_nsecs(); | 616 | T0 = get_nsecs(); |
611 | burn_nsecs(1e6); | 617 | burn_nsecs(1e6); |
@@ -620,8 +626,6 @@ static void test_calibrations(void) | |||
620 | printf("the sleep test took %Ld nsecs\n", T1-T0); | 626 | printf("the sleep test took %Ld nsecs\n", T1-T0); |
621 | } | 627 | } |
622 | 628 | ||
623 | static unsigned long replay_repeat = 10; | ||
624 | |||
625 | static void __cmd_replay(void) | 629 | static void __cmd_replay(void) |
626 | { | 630 | { |
627 | unsigned long i; | 631 | unsigned long i; |
@@ -865,47 +869,8 @@ static struct trace_sched_handler replay_ops = { | |||
865 | .fork_event = replay_fork_event, | 869 | .fork_event = replay_fork_event, |
866 | }; | 870 | }; |
867 | 871 | ||
868 | #define TASK_STATE_TO_CHAR_STR "RSDTtZX" | ||
869 | |||
870 | enum thread_state { | ||
871 | THREAD_SLEEPING = 0, | ||
872 | THREAD_WAIT_CPU, | ||
873 | THREAD_SCHED_IN, | ||
874 | THREAD_IGNORE | ||
875 | }; | ||
876 | |||
877 | struct work_atom { | ||
878 | struct list_head list; | ||
879 | enum thread_state state; | ||
880 | u64 wake_up_time; | ||
881 | u64 sched_in_time; | ||
882 | u64 runtime; | ||
883 | }; | ||
884 | |||
885 | struct task_atoms { | ||
886 | struct list_head snapshot_list; | ||
887 | struct thread *thread; | ||
888 | struct rb_node node; | ||
889 | u64 max_lat; | ||
890 | u64 total_lat; | ||
891 | u64 nb_atoms; | ||
892 | u64 total_runtime; | ||
893 | }; | ||
894 | |||
895 | typedef int (*sort_thread_lat)(struct task_atoms *, struct task_atoms *); | ||
896 | |||
897 | struct sort_dimension { | ||
898 | const char *name; | ||
899 | sort_thread_lat cmp; | ||
900 | struct list_head list; | ||
901 | }; | ||
902 | |||
903 | static LIST_HEAD(cmp_pid); | ||
904 | |||
905 | static struct rb_root lat_snapshot_root, sorted_lat_snapshot_root; | ||
906 | |||
907 | static struct task_atoms * | 872 | static struct task_atoms * |
908 | thread_atom_list_search(struct rb_root *root, struct thread *thread) | 873 | thread_atoms_search(struct rb_root *root, struct thread *thread) |
909 | { | 874 | { |
910 | struct rb_node *node = root->rb_node; | 875 | struct rb_node *node = root->rb_node; |
911 | 876 | ||
@@ -924,6 +889,14 @@ thread_atom_list_search(struct rb_root *root, struct thread *thread) | |||
924 | return NULL; | 889 | return NULL; |
925 | } | 890 | } |
926 | 891 | ||
892 | struct sort_dimension { | ||
893 | const char *name; | ||
894 | sort_thread_lat cmp; | ||
895 | struct list_head list; | ||
896 | }; | ||
897 | |||
898 | static LIST_HEAD(cmp_pid); | ||
899 | |||
927 | static int | 900 | static int |
928 | thread_lat_cmp(struct list_head *list, struct task_atoms *l, | 901 | thread_lat_cmp(struct list_head *list, struct task_atoms *l, |
929 | struct task_atoms *r) | 902 | struct task_atoms *r) |
@@ -965,16 +938,17 @@ __thread_latency_insert(struct rb_root *root, struct task_atoms *data, | |||
965 | rb_insert_color(&data->node, root); | 938 | rb_insert_color(&data->node, root); |
966 | } | 939 | } |
967 | 940 | ||
968 | static void thread_atom_list_insert(struct thread *thread) | 941 | static void thread_atoms_insert(struct thread *thread) |
969 | { | 942 | { |
970 | struct task_atoms *atoms; | 943 | struct task_atoms *atoms; |
944 | |||
971 | atoms = calloc(sizeof(*atoms), 1); | 945 | atoms = calloc(sizeof(*atoms), 1); |
972 | if (!atoms) | 946 | if (!atoms) |
973 | die("No memory"); | 947 | die("No memory"); |
974 | 948 | ||
975 | atoms->thread = thread; | 949 | atoms->thread = thread; |
976 | INIT_LIST_HEAD(&atoms->snapshot_list); | 950 | INIT_LIST_HEAD(&atoms->atom_list); |
977 | __thread_latency_insert(&lat_snapshot_root, atoms, &cmp_pid); | 951 | __thread_latency_insert(&atom_root, atoms, &cmp_pid); |
978 | } | 952 | } |
979 | 953 | ||
980 | static void | 954 | static void |
@@ -1001,50 +975,49 @@ lat_sched_out(struct task_atoms *atoms, | |||
1001 | u64 delta, | 975 | u64 delta, |
1002 | u64 timestamp) | 976 | u64 timestamp) |
1003 | { | 977 | { |
1004 | struct work_atom *snapshot; | 978 | struct work_atom *atom; |
1005 | 979 | ||
1006 | snapshot = calloc(sizeof(*snapshot), 1); | 980 | atom = calloc(sizeof(*atom), 1); |
1007 | if (!snapshot) | 981 | if (!atom) |
1008 | die("Non memory"); | 982 | die("Non memory"); |
1009 | 983 | ||
1010 | if (sched_out_state(switch_event) == 'R') { | 984 | if (sched_out_state(switch_event) == 'R') { |
1011 | snapshot->state = THREAD_WAIT_CPU; | 985 | atom->state = THREAD_WAIT_CPU; |
1012 | snapshot->wake_up_time = timestamp; | 986 | atom->wake_up_time = timestamp; |
1013 | } | 987 | } |
1014 | 988 | ||
1015 | snapshot->runtime = delta; | 989 | atom->runtime = delta; |
1016 | list_add_tail(&snapshot->list, &atoms->snapshot_list); | 990 | list_add_tail(&atom->list, &atoms->atom_list); |
1017 | } | 991 | } |
1018 | 992 | ||
1019 | static void | 993 | static void |
1020 | lat_sched_in(struct task_atoms *atoms, u64 timestamp) | 994 | lat_sched_in(struct task_atoms *atoms, u64 timestamp) |
1021 | { | 995 | { |
1022 | struct work_atom *snapshot; | 996 | struct work_atom *atom; |
1023 | u64 delta; | 997 | u64 delta; |
1024 | 998 | ||
1025 | if (list_empty(&atoms->snapshot_list)) | 999 | if (list_empty(&atoms->atom_list)) |
1026 | return; | 1000 | return; |
1027 | 1001 | ||
1028 | snapshot = list_entry(atoms->snapshot_list.prev, struct work_atom, | 1002 | atom = list_entry(atoms->atom_list.prev, struct work_atom, list); |
1029 | list); | ||
1030 | 1003 | ||
1031 | if (snapshot->state != THREAD_WAIT_CPU) | 1004 | if (atom->state != THREAD_WAIT_CPU) |
1032 | return; | 1005 | return; |
1033 | 1006 | ||
1034 | if (timestamp < snapshot->wake_up_time) { | 1007 | if (timestamp < atom->wake_up_time) { |
1035 | snapshot->state = THREAD_IGNORE; | 1008 | atom->state = THREAD_IGNORE; |
1036 | return; | 1009 | return; |
1037 | } | 1010 | } |
1038 | 1011 | ||
1039 | snapshot->state = THREAD_SCHED_IN; | 1012 | atom->state = THREAD_SCHED_IN; |
1040 | snapshot->sched_in_time = timestamp; | 1013 | atom->sched_in_time = timestamp; |
1041 | 1014 | ||
1042 | delta = snapshot->sched_in_time - snapshot->wake_up_time; | 1015 | delta = atom->sched_in_time - atom->wake_up_time; |
1043 | atoms->total_lat += delta; | 1016 | atoms->total_lat += delta; |
1044 | if (delta > atoms->max_lat) | 1017 | if (delta > atoms->max_lat) |
1045 | atoms->max_lat = delta; | 1018 | atoms->max_lat = delta; |
1046 | atoms->nb_atoms++; | 1019 | atoms->nb_atoms++; |
1047 | atoms->total_runtime += snapshot->runtime; | 1020 | atoms->total_runtime += atom->runtime; |
1048 | } | 1021 | } |
1049 | 1022 | ||
1050 | static void | 1023 | static void |
@@ -1076,20 +1049,20 @@ latency_switch_event(struct trace_switch_event *switch_event, | |||
1076 | sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); | 1049 | sched_out = threads__findnew(switch_event->prev_pid, &threads, &last_match); |
1077 | sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); | 1050 | sched_in = threads__findnew(switch_event->next_pid, &threads, &last_match); |
1078 | 1051 | ||
1079 | in_atoms = thread_atom_list_search(&lat_snapshot_root, sched_in); | 1052 | in_atoms = thread_atoms_search(&atom_root, sched_in); |
1080 | if (!in_atoms) { | 1053 | if (!in_atoms) { |
1081 | thread_atom_list_insert(sched_in); | 1054 | thread_atoms_insert(sched_in); |
1082 | in_atoms = thread_atom_list_search(&lat_snapshot_root, sched_in); | 1055 | in_atoms = thread_atoms_search(&atom_root, sched_in); |
1083 | if (!in_atoms) | 1056 | if (!in_atoms) |
1084 | die("Internal latency tree error"); | 1057 | die("in-atom: Internal tree error"); |
1085 | } | 1058 | } |
1086 | 1059 | ||
1087 | out_atoms = thread_atom_list_search(&lat_snapshot_root, sched_out); | 1060 | out_atoms = thread_atoms_search(&atom_root, sched_out); |
1088 | if (!out_atoms) { | 1061 | if (!out_atoms) { |
1089 | thread_atom_list_insert(sched_out); | 1062 | thread_atoms_insert(sched_out); |
1090 | out_atoms = thread_atom_list_search(&lat_snapshot_root, sched_out); | 1063 | out_atoms = thread_atoms_search(&atom_root, sched_out); |
1091 | if (!out_atoms) | 1064 | if (!out_atoms) |
1092 | die("Internal latency tree error"); | 1065 | die("out-atom: Internal tree error"); |
1093 | } | 1066 | } |
1094 | 1067 | ||
1095 | lat_sched_in(in_atoms, timestamp); | 1068 | lat_sched_in(in_atoms, timestamp); |
@@ -1104,7 +1077,7 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event, | |||
1104 | struct thread *thread __used) | 1077 | struct thread *thread __used) |
1105 | { | 1078 | { |
1106 | struct task_atoms *atoms; | 1079 | struct task_atoms *atoms; |
1107 | struct work_atom *snapshot; | 1080 | struct work_atom *atom; |
1108 | struct thread *wakee; | 1081 | struct thread *wakee; |
1109 | 1082 | ||
1110 | /* Note for later, it may be interesting to observe the failing cases */ | 1083 | /* Note for later, it may be interesting to observe the failing cases */ |
@@ -1112,23 +1085,22 @@ latency_wakeup_event(struct trace_wakeup_event *wakeup_event, | |||
1112 | return; | 1085 | return; |
1113 | 1086 | ||
1114 | wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); | 1087 | wakee = threads__findnew(wakeup_event->pid, &threads, &last_match); |
1115 | atoms = thread_atom_list_search(&lat_snapshot_root, wakee); | 1088 | atoms = thread_atoms_search(&atom_root, wakee); |
1116 | if (!atoms) { | 1089 | if (!atoms) { |
1117 | thread_atom_list_insert(wakee); | 1090 | thread_atoms_insert(wakee); |
1118 | return; | 1091 | return; |
1119 | } | 1092 | } |
1120 | 1093 | ||
1121 | if (list_empty(&atoms->snapshot_list)) | 1094 | if (list_empty(&atoms->atom_list)) |
1122 | return; | 1095 | return; |
1123 | 1096 | ||
1124 | snapshot = list_entry(atoms->snapshot_list.prev, struct work_atom, | 1097 | atom = list_entry(atoms->atom_list.prev, struct work_atom, list); |
1125 | list); | ||
1126 | 1098 | ||
1127 | if (snapshot->state != THREAD_SLEEPING) | 1099 | if (atom->state != THREAD_SLEEPING) |
1128 | return; | 1100 | return; |
1129 | 1101 | ||
1130 | snapshot->state = THREAD_WAIT_CPU; | 1102 | atom->state = THREAD_WAIT_CPU; |
1131 | snapshot->wake_up_time = timestamp; | 1103 | atom->wake_up_time = timestamp; |
1132 | } | 1104 | } |
1133 | 1105 | ||
1134 | static struct trace_sched_handler lat_ops = { | 1106 | static struct trace_sched_handler lat_ops = { |
@@ -1137,9 +1109,6 @@ static struct trace_sched_handler lat_ops = { | |||
1137 | .fork_event = latency_fork_event, | 1109 | .fork_event = latency_fork_event, |
1138 | }; | 1110 | }; |
1139 | 1111 | ||
1140 | static u64 all_runtime; | ||
1141 | static u64 all_count; | ||
1142 | |||
1143 | static void output_lat_thread(struct task_atoms *atom_list) | 1112 | static void output_lat_thread(struct task_atoms *atom_list) |
1144 | { | 1113 | { |
1145 | int i; | 1114 | int i; |
@@ -1287,13 +1256,13 @@ static void sort_lat(void) | |||
1287 | 1256 | ||
1288 | for (;;) { | 1257 | for (;;) { |
1289 | struct task_atoms *data; | 1258 | struct task_atoms *data; |
1290 | node = rb_first(&lat_snapshot_root); | 1259 | node = rb_first(&atom_root); |
1291 | if (!node) | 1260 | if (!node) |
1292 | break; | 1261 | break; |
1293 | 1262 | ||
1294 | rb_erase(node, &lat_snapshot_root); | 1263 | rb_erase(node, &atom_root); |
1295 | data = rb_entry(node, struct task_atoms, node); | 1264 | data = rb_entry(node, struct task_atoms, node); |
1296 | __thread_latency_insert(&sorted_lat_snapshot_root, data, &sort_list); | 1265 | __thread_latency_insert(&sorted_atom_root, data, &sort_list); |
1297 | } | 1266 | } |
1298 | } | 1267 | } |
1299 | 1268 | ||
@@ -1309,7 +1278,7 @@ static void __cmd_lat(void) | |||
1309 | printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |\n"); | 1278 | printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms |\n"); |
1310 | printf("-----------------------------------------------------------------------------------\n"); | 1279 | printf("-----------------------------------------------------------------------------------\n"); |
1311 | 1280 | ||
1312 | next = rb_first(&sorted_lat_snapshot_root); | 1281 | next = rb_first(&sorted_atom_root); |
1313 | 1282 | ||
1314 | while (next) { | 1283 | while (next) { |
1315 | struct task_atoms *atom_list; | 1284 | struct task_atoms *atom_list; |