4 #include "util/cache.h"
5 #include "util/symbol.h"
6 #include "util/thread.h"
7 #include "util/header.h"
9 #include "util/parse-options.h"
12 #include "util/debug.h"
14 #include "util/trace-event.h"
15 #include <sys/types.h>
17 static char const *input_name
= "perf.data";
19 static unsigned long page_size
;
20 static unsigned long mmap_window
= 32;
22 static unsigned long total_comm
= 0;
24 static struct rb_root threads
;
25 static struct thread
*last_match
;
27 static struct perf_header
*header
;
28 static u64 sample_type
;
32 * Scheduler benchmarks
34 #include <sys/resource.h>
35 #include <sys/types.h>
38 #include <sys/prctl.h>
40 #include <linux/unistd.h>
42 #include <semaphore.h>
56 #define PR_SET_NAME 15 /* Set process name */
58 #define BUG_ON(x) assert(!(x))
62 typedef unsigned long long nsec_t
;
64 static nsec_t run_measurement_overhead
;
65 static nsec_t sleep_measurement_overhead
;
67 static nsec_t
get_nsecs(void)
71 clock_gettime(CLOCK_MONOTONIC
, &ts
);
73 return ts
.tv_sec
* 1000000000ULL + ts
.tv_nsec
;
76 static void burn_nsecs(nsec_t nsecs
)
78 nsec_t T0
= get_nsecs(), T1
;
82 } while (T1
+ run_measurement_overhead
< T0
+ nsecs
);
85 static void sleep_nsecs(nsec_t nsecs
)
89 ts
.tv_nsec
= nsecs
% 999999999;
90 ts
.tv_sec
= nsecs
/ 999999999;
95 static void calibrate_run_measurement_overhead(void)
97 nsec_t T0
, T1
, delta
, min_delta
= 1000000000ULL;
100 for (i
= 0; i
< 10; i
++) {
105 min_delta
= min(min_delta
, delta
);
107 run_measurement_overhead
= min_delta
;
109 printf("run measurement overhead: %Ld nsecs\n", min_delta
);
112 static void calibrate_sleep_measurement_overhead(void)
114 nsec_t T0
, T1
, delta
, min_delta
= 1000000000ULL;
117 for (i
= 0; i
< 10; i
++) {
122 min_delta
= min(min_delta
, delta
);
125 sleep_measurement_overhead
= min_delta
;
127 printf("sleep measurement overhead: %Ld nsecs\n", min_delta
);
133 #define MAX_PID 65536
135 static unsigned long nr_tasks
;
144 unsigned long nr_events
;
145 unsigned long curr_event
;
146 struct sched_event
**events
;
151 sem_t ready_for_work
;
157 enum sched_event_type
{
164 enum sched_event_type type
;
170 struct task_desc
*wakee
;
173 static struct task_desc
*pid_to_task
[MAX_PID
];
175 static struct task_desc
**tasks
;
177 static pthread_mutex_t start_work_mutex
= PTHREAD_MUTEX_INITIALIZER
;
178 static nsec_t start_time
;
180 static pthread_mutex_t work_done_wait_mutex
= PTHREAD_MUTEX_INITIALIZER
;
182 static unsigned long nr_run_events
;
183 static unsigned long nr_sleep_events
;
184 static unsigned long nr_wakeup_events
;
186 static unsigned long nr_sleep_corrections
;
187 static unsigned long nr_run_events_optimized
;
189 static struct sched_event
*
190 get_new_event(struct task_desc
*task
, nsec_t timestamp
)
192 struct sched_event
*event
= calloc(1, sizeof(*event
));
193 unsigned long idx
= task
->nr_events
;
196 event
->timestamp
= timestamp
;
200 size
= sizeof(struct sched_event
*) * task
->nr_events
;
201 task
->events
= realloc(task
->events
, size
);
202 BUG_ON(!task
->events
);
204 task
->events
[idx
] = event
;
209 static struct sched_event
*last_event(struct task_desc
*task
)
211 if (!task
->nr_events
)
214 return task
->events
[task
->nr_events
- 1];
218 add_sched_event_run(struct task_desc
*task
, nsec_t timestamp
, u64 duration
)
220 struct sched_event
*event
, *curr_event
= last_event(task
);
223 * optimize an existing RUN event by merging this one
226 if (curr_event
&& curr_event
->type
== SCHED_EVENT_RUN
) {
227 nr_run_events_optimized
++;
228 curr_event
->duration
+= duration
;
232 event
= get_new_event(task
, timestamp
);
234 event
->type
= SCHED_EVENT_RUN
;
235 event
->duration
= duration
;
240 static unsigned long targetless_wakeups
;
241 static unsigned long multitarget_wakeups
;
244 add_sched_event_wakeup(struct task_desc
*task
, nsec_t timestamp
,
245 struct task_desc
*wakee
)
247 struct sched_event
*event
, *wakee_event
;
249 event
= get_new_event(task
, timestamp
);
250 event
->type
= SCHED_EVENT_WAKEUP
;
251 event
->wakee
= wakee
;
253 wakee_event
= last_event(wakee
);
254 if (!wakee_event
|| wakee_event
->type
!= SCHED_EVENT_SLEEP
) {
255 targetless_wakeups
++;
258 if (wakee_event
->wait_sem
) {
259 multitarget_wakeups
++;
263 wakee_event
->wait_sem
= calloc(1, sizeof(*wakee_event
->wait_sem
));
264 sem_init(wakee_event
->wait_sem
, 0, 0);
265 wakee_event
->specific_wait
= 1;
266 event
->wait_sem
= wakee_event
->wait_sem
;
272 add_sched_event_sleep(struct task_desc
*task
, nsec_t timestamp
,
273 u64 task_state __used
)
275 struct sched_event
*event
= get_new_event(task
, timestamp
);
277 event
->type
= SCHED_EVENT_SLEEP
;
282 static struct task_desc
*register_pid(unsigned long pid
, const char *comm
)
284 struct task_desc
*task
;
286 BUG_ON(pid
>= MAX_PID
);
288 task
= pid_to_task
[pid
];
293 task
= calloc(1, sizeof(*task
));
296 strcpy(task
->comm
, comm
);
298 * every task starts in sleeping state - this gets ignored
299 * if there's no wakeup pointing to this sleep state:
301 add_sched_event_sleep(task
, 0, 0);
303 pid_to_task
[pid
] = task
;
305 tasks
= realloc(tasks
, nr_tasks
*sizeof(struct task_task
*));
307 tasks
[task
->nr
] = task
;
310 printf("registered task #%ld, PID %ld (%s)\n", nr_tasks
, pid
, comm
);
316 static void print_task_traces(void)
318 struct task_desc
*task
;
321 for (i
= 0; i
< nr_tasks
; i
++) {
323 printf("task %6ld (%20s:%10ld), nr_events: %ld\n",
324 task
->nr
, task
->comm
, task
->pid
, task
->nr_events
);
328 static void add_cross_task_wakeups(void)
330 struct task_desc
*task1
, *task2
;
333 for (i
= 0; i
< nr_tasks
; i
++) {
339 add_sched_event_wakeup(task1
, 0, task2
);
344 process_sched_event(struct task_desc
*this_task __used
, struct sched_event
*event
)
351 delta
= start_time
+ event
->timestamp
- now
;
353 switch (event
->type
) {
354 case SCHED_EVENT_RUN
:
355 burn_nsecs(event
->duration
);
357 case SCHED_EVENT_SLEEP
:
359 ret
= sem_wait(event
->wait_sem
);
362 case SCHED_EVENT_WAKEUP
:
364 ret
= sem_post(event
->wait_sem
);
372 static nsec_t
get_cpu_usage_nsec_parent(void)
378 err
= getrusage(RUSAGE_SELF
, &ru
);
381 sum
= ru
.ru_utime
.tv_sec
*1e9
+ ru
.ru_utime
.tv_usec
*1e3
;
382 sum
+= ru
.ru_stime
.tv_sec
*1e9
+ ru
.ru_stime
.tv_usec
*1e3
;
387 static nsec_t
get_cpu_usage_nsec_self(void)
389 char filename
[] = "/proc/1234567890/sched";
390 unsigned long msecs
, nsecs
;
398 sprintf(filename
, "/proc/%d/sched", getpid());
399 file
= fopen(filename
, "r");
402 while ((chars
= getline(&line
, &len
, file
)) != -1) {
403 ret
= sscanf(line
, "se.sum_exec_runtime : %ld.%06ld\n",
406 total
= msecs
*1e6
+ nsecs
;
417 static void *thread_func(void *ctx
)
419 struct task_desc
*this_task
= ctx
;
420 nsec_t cpu_usage_0
, cpu_usage_1
;
421 unsigned long i
, ret
;
424 sprintf(comm2
, ":%s", this_task
->comm
);
425 prctl(PR_SET_NAME
, comm2
);
428 ret
= sem_post(&this_task
->ready_for_work
);
430 ret
= pthread_mutex_lock(&start_work_mutex
);
432 ret
= pthread_mutex_unlock(&start_work_mutex
);
435 cpu_usage_0
= get_cpu_usage_nsec_self();
437 for (i
= 0; i
< this_task
->nr_events
; i
++) {
438 this_task
->curr_event
= i
;
439 process_sched_event(this_task
, this_task
->events
[i
]);
442 cpu_usage_1
= get_cpu_usage_nsec_self();
443 this_task
->cpu_usage
= cpu_usage_1
- cpu_usage_0
;
445 ret
= sem_post(&this_task
->work_done_sem
);
448 ret
= pthread_mutex_lock(&work_done_wait_mutex
);
450 ret
= pthread_mutex_unlock(&work_done_wait_mutex
);
456 static void create_tasks(void)
458 struct task_desc
*task
;
463 err
= pthread_attr_init(&attr
);
465 err
= pthread_attr_setstacksize(&attr
, (size_t)(16*1024));
467 err
= pthread_mutex_lock(&start_work_mutex
);
469 err
= pthread_mutex_lock(&work_done_wait_mutex
);
471 for (i
= 0; i
< nr_tasks
; i
++) {
473 sem_init(&task
->sleep_sem
, 0, 0);
474 sem_init(&task
->ready_for_work
, 0, 0);
475 sem_init(&task
->work_done_sem
, 0, 0);
476 task
->curr_event
= 0;
477 err
= pthread_create(&task
->thread
, &attr
, thread_func
, task
);
482 static nsec_t cpu_usage
;
483 static nsec_t runavg_cpu_usage
;
484 static nsec_t parent_cpu_usage
;
485 static nsec_t runavg_parent_cpu_usage
;
487 static void wait_for_tasks(void)
489 nsec_t cpu_usage_0
, cpu_usage_1
;
490 struct task_desc
*task
;
491 unsigned long i
, ret
;
493 start_time
= get_nsecs();
495 pthread_mutex_unlock(&work_done_wait_mutex
);
497 for (i
= 0; i
< nr_tasks
; i
++) {
499 ret
= sem_wait(&task
->ready_for_work
);
501 sem_init(&task
->ready_for_work
, 0, 0);
503 ret
= pthread_mutex_lock(&work_done_wait_mutex
);
506 cpu_usage_0
= get_cpu_usage_nsec_parent();
508 pthread_mutex_unlock(&start_work_mutex
);
510 for (i
= 0; i
< nr_tasks
; i
++) {
512 ret
= sem_wait(&task
->work_done_sem
);
514 sem_init(&task
->work_done_sem
, 0, 0);
515 cpu_usage
+= task
->cpu_usage
;
519 cpu_usage_1
= get_cpu_usage_nsec_parent();
520 if (!runavg_cpu_usage
)
521 runavg_cpu_usage
= cpu_usage
;
522 runavg_cpu_usage
= (runavg_cpu_usage
*9 + cpu_usage
)/10;
524 parent_cpu_usage
= cpu_usage_1
- cpu_usage_0
;
525 if (!runavg_parent_cpu_usage
)
526 runavg_parent_cpu_usage
= parent_cpu_usage
;
527 runavg_parent_cpu_usage
= (runavg_parent_cpu_usage
*9 +
528 parent_cpu_usage
)/10;
530 ret
= pthread_mutex_lock(&start_work_mutex
);
533 for (i
= 0; i
< nr_tasks
; i
++) {
535 sem_init(&task
->sleep_sem
, 0, 0);
536 task
->curr_event
= 0;
540 static int __cmd_sched(void);
542 static void parse_trace(void)
546 printf("nr_run_events: %ld\n", nr_run_events
);
547 printf("nr_sleep_events: %ld\n", nr_sleep_events
);
548 printf("nr_wakeup_events: %ld\n", nr_wakeup_events
);
550 if (targetless_wakeups
)
551 printf("target-less wakeups: %ld\n", targetless_wakeups
);
552 if (multitarget_wakeups
)
553 printf("multi-target wakeups: %ld\n", multitarget_wakeups
);
554 if (nr_run_events_optimized
)
555 printf("run events optimized: %ld\n",
556 nr_run_events_optimized
);
559 static unsigned long nr_runs
;
560 static nsec_t sum_runtime
;
561 static nsec_t sum_fluct
;
562 static nsec_t run_avg
;
564 static void run_one_test(void)
566 nsec_t T0
, T1
, delta
, avg_delta
, fluct
, std_dev
;
573 sum_runtime
+= delta
;
576 avg_delta
= sum_runtime
/ nr_runs
;
577 if (delta
< avg_delta
)
578 fluct
= avg_delta
- delta
;
580 fluct
= delta
- avg_delta
;
582 std_dev
= sum_fluct
/ nr_runs
/ sqrt(nr_runs
);
585 run_avg
= (run_avg
*9 + delta
)/10;
587 printf("#%-3ld: %0.3f, ",
588 nr_runs
, (double)delta
/1000000.0);
591 printf("%0.2f +- %0.2f, ",
592 (double)avg_delta
/1e6
, (double)std_dev
/1e6
);
594 printf("ravg: %0.2f, ",
595 (double)run_avg
/1e6
);
597 printf("cpu: %0.2f / %0.2f",
598 (double)cpu_usage
/1e6
, (double)runavg_cpu_usage
/1e6
);
602 * rusage statistics done by the parent, these are less
603 * accurate than the sum_exec_runtime based statistics:
605 printf(" [%0.2f / %0.2f]",
606 (double)parent_cpu_usage
/1e6
,
607 (double)runavg_parent_cpu_usage
/1e6
);
612 if (nr_sleep_corrections
)
613 printf(" (%ld sleep corrections)\n", nr_sleep_corrections
);
614 nr_sleep_corrections
= 0;
617 static void test_calibrations(void)
625 printf("the run test took %Ld nsecs\n", T1
-T0
);
631 printf("the sleep test took %Ld nsecs\n", T1
-T0
);
635 process_comm_event(event_t
*event
, unsigned long offset
, unsigned long head
)
637 struct thread
*thread
;
639 thread
= threads__findnew(event
->comm
.pid
, &threads
, &last_match
);
641 dump_printf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
642 (void *)(offset
+ head
),
643 (void *)(long)(event
->header
.size
),
644 event
->comm
.comm
, event
->comm
.pid
);
646 if (thread
== NULL
||
647 thread__set_comm(thread
, event
->comm
.comm
)) {
648 dump_printf("problem processing PERF_EVENT_COMM, skipping event.\n");
657 struct raw_event_sample
{
662 #define FILL_FIELD(ptr, field, event, data) \
663 ptr.field = (typeof(ptr.field)) raw_field_value(event, #field, data)
665 #define FILL_ARRAY(ptr, array, event, data) \
667 void *__array = raw_field_ptr(event, #array, data); \
668 memcpy(ptr.array, __array, sizeof(ptr.array)); \
671 #define FILL_COMMON_FIELDS(ptr, event, data) \
673 FILL_FIELD(ptr, common_type, event, data); \
674 FILL_FIELD(ptr, common_flags, event, data); \
675 FILL_FIELD(ptr, common_preempt_count, event, data); \
676 FILL_FIELD(ptr, common_pid, event, data); \
677 FILL_FIELD(ptr, common_tgid, event, data); \
680 struct trace_wakeup_event
{
685 u8 common_preempt_count
;
698 process_sched_wakeup_event(struct raw_event_sample
*raw
, struct event
*event
,
699 int cpu __used
, u64 timestamp __used
, struct thread
*thread __used
)
701 struct task_desc
*waker
, *wakee
;
702 struct trace_wakeup_event wakeup_event
;
704 FILL_COMMON_FIELDS(wakeup_event
, event
, raw
->data
);
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
);
714 printf("sched_wakeup event %p\n", event
);
716 printf(" ... pid %d woke up %s/%d\n",
717 wakeup_event
.common_pid
,
722 waker
= register_pid(wakeup_event
.common_pid
, "<unknown>");
723 wakee
= register_pid(wakeup_event
.pid
, wakeup_event
.comm
);
725 add_sched_event_wakeup(waker
, timestamp
, wakee
);
728 struct trace_switch_event
{
733 u8 common_preempt_count
;
746 #define MAX_CPUS 4096
748 unsigned long cpu_last_switched
[MAX_CPUS
];
751 process_sched_switch_event(struct raw_event_sample
*raw
, struct event
*event
,
752 int cpu __used
, u64 timestamp __used
, struct thread
*thread __used
)
754 struct trace_switch_event switch_event
;
755 struct task_desc
*prev
, *next
;
759 FILL_COMMON_FIELDS(switch_event
, event
, raw
->data
);
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
);
770 printf("sched_switch event %p\n", event
);
772 if (cpu
>= MAX_CPUS
|| cpu
< 0)
775 timestamp0
= cpu_last_switched
[cpu
];
777 delta
= timestamp
- timestamp0
;
782 die("hm, delta: %Ld < 0 ?\n", delta
);
785 printf(" ... switch from %s/%d to %s/%d [ran %Ld nsecs]\n",
786 switch_event
.prev_comm
, switch_event
.prev_pid
,
787 switch_event
.next_comm
, switch_event
.next_pid
,
791 prev
= register_pid(switch_event
.prev_pid
, switch_event
.prev_comm
);
792 next
= register_pid(switch_event
.next_pid
, switch_event
.next_comm
);
794 cpu_last_switched
[cpu
] = timestamp
;
796 add_sched_event_run(prev
, timestamp
, delta
);
797 add_sched_event_sleep(prev
, timestamp
, switch_event
.prev_state
);
800 struct trace_fork_event
{
805 u8 common_preempt_count
;
809 char parent_comm
[16];
816 process_sched_fork_event(struct raw_event_sample
*raw
, struct event
*event
,
817 int cpu __used
, u64 timestamp __used
, struct thread
*thread __used
)
819 struct trace_fork_event fork_event
;
821 FILL_COMMON_FIELDS(fork_event
, event
, raw
->data
);
823 FILL_ARRAY(fork_event
, parent_comm
, event
, raw
->data
);
824 FILL_FIELD(fork_event
, parent_pid
, event
, raw
->data
);
825 FILL_ARRAY(fork_event
, child_comm
, event
, raw
->data
);
826 FILL_FIELD(fork_event
, child_pid
, event
, raw
->data
);
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
);
833 register_pid(fork_event
.parent_pid
, fork_event
.parent_comm
);
834 register_pid(fork_event
.child_pid
, fork_event
.child_comm
);
837 static void process_sched_exit_event(struct event
*event
,
838 int cpu __used
, u64 timestamp __used
, struct thread
*thread __used
)
841 printf("sched_exit event %p\n", event
);
845 process_raw_event(event_t
*raw_event __used
, void *more_data
,
846 int cpu
, u64 timestamp
, struct thread
*thread
)
848 struct raw_event_sample
*raw
= more_data
;
852 type
= trace_parse_common_type(raw
->data
);
853 event
= trace_find_event(type
);
855 if (!strcmp(event
->name
, "sched_switch"))
856 process_sched_switch_event(raw
, event
, cpu
, timestamp
, thread
);
857 if (!strcmp(event
->name
, "sched_wakeup"))
858 process_sched_wakeup_event(raw
, event
, cpu
, timestamp
, thread
);
859 if (!strcmp(event
->name
, "sched_wakeup_new"))
860 process_sched_wakeup_event(raw
, event
, cpu
, timestamp
, thread
);
861 if (!strcmp(event
->name
, "sched_process_fork"))
862 process_sched_fork_event(raw
, event
, cpu
, timestamp
, thread
);
863 if (!strcmp(event
->name
, "sched_process_exit"))
864 process_sched_exit_event(event
, cpu
, timestamp
, thread
);
868 process_sample_event(event_t
*event
, unsigned long offset
, unsigned long head
)
872 struct dso
*dso
= NULL
;
873 struct thread
*thread
;
874 u64 ip
= event
->ip
.ip
;
878 void *more_data
= event
->ip
.__more_data
;
881 thread
= threads__findnew(event
->ip
.pid
, &threads
, &last_match
);
883 if (sample_type
& PERF_SAMPLE_TIME
) {
884 timestamp
= *(u64
*)more_data
;
885 more_data
+= sizeof(u64
);
888 if (sample_type
& PERF_SAMPLE_CPU
) {
889 cpu
= *(u32
*)more_data
;
890 more_data
+= sizeof(u32
);
891 more_data
+= sizeof(u32
); /* reserved */
894 if (sample_type
& PERF_SAMPLE_PERIOD
) {
895 period
= *(u64
*)more_data
;
896 more_data
+= sizeof(u64
);
899 dump_printf("%p [%p]: PERF_EVENT_SAMPLE (IP, %d): %d/%d: %p period: %Ld\n",
900 (void *)(offset
+ head
),
901 (void *)(long)(event
->header
.size
),
903 event
->ip
.pid
, event
->ip
.tid
,
907 dump_printf(" ... thread: %s:%d\n", thread
->comm
, thread
->pid
);
909 if (thread
== NULL
) {
910 eprintf("problem processing %d event, skipping it.\n",
915 cpumode
= event
->header
.misc
& PERF_EVENT_MISC_CPUMODE_MASK
;
917 if (cpumode
== PERF_EVENT_MISC_KERNEL
) {
923 dump_printf(" ...... dso: %s\n", dso
->name
);
925 } else if (cpumode
== PERF_EVENT_MISC_USER
) {
934 dso
= hypervisor_dso
;
936 dump_printf(" ...... dso: [hypervisor]\n");
939 if (sample_type
& PERF_SAMPLE_RAW
)
940 process_raw_event(event
, more_data
, cpu
, timestamp
, thread
);
946 process_event(event_t
*event
, unsigned long offset
, unsigned long head
)
950 switch (event
->header
.type
) {
951 case PERF_EVENT_MMAP
... PERF_EVENT_LOST
:
954 case PERF_EVENT_COMM
:
955 return process_comm_event(event
, offset
, head
);
957 case PERF_EVENT_EXIT
... PERF_EVENT_READ
:
960 case PERF_EVENT_SAMPLE
:
961 return process_sample_event(event
, offset
, head
);
971 static int __cmd_sched(void)
973 int ret
, rc
= EXIT_FAILURE
;
974 unsigned long offset
= 0;
975 unsigned long head
= 0;
976 struct stat perf_stat
;
982 register_idle_thread(&threads
, &last_match
);
984 input
= open(input_name
, O_RDONLY
);
986 perror("failed to open file");
990 ret
= fstat(input
, &perf_stat
);
992 perror("failed to stat file");
996 if (!perf_stat
.st_size
) {
997 fprintf(stderr
, "zero-sized file, nothing to do!\n");
1000 header
= perf_header__read(input
);
1001 head
= header
->data_offset
;
1002 sample_type
= perf_header__sample_type(header
);
1004 if (!(sample_type
& PERF_SAMPLE_RAW
))
1005 die("No trace sample to read. Did you call perf record "
1008 if (load_kernel() < 0) {
1009 perror("failed to load kernel symbols");
1010 return EXIT_FAILURE
;
1014 buf
= (char *)mmap(NULL
, page_size
* mmap_window
, PROT_READ
,
1015 MAP_SHARED
, input
, offset
);
1016 if (buf
== MAP_FAILED
) {
1017 perror("failed to mmap file");
1022 event
= (event_t
*)(buf
+ head
);
1024 size
= event
->header
.size
;
1028 if (head
+ event
->header
.size
>= page_size
* mmap_window
) {
1029 unsigned long shift
= page_size
* (head
/ page_size
);
1032 res
= munmap(buf
, page_size
* mmap_window
);
1040 size
= event
->header
.size
;
1043 if (!size
|| process_event(event
, offset
, head
) < 0) {
1046 * assume we lost track of the stream, check alignment, and
1047 * increment a single u64 in the hope to catch on again 'soon'.
1050 if (unlikely(head
& 7))
1058 if (offset
+ head
< (unsigned long)perf_stat
.st_size
)
1067 static const char * const annotate_usage
[] = {
1068 "perf trace [<options>] <command>",
1072 static const struct option options
[] = {
1073 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace
,
1074 "dump raw trace in ASCII"),
1075 OPT_BOOLEAN('v', "verbose", &verbose
,
1076 "be more verbose (show symbol address, etc)"),
1080 int cmd_sched(int argc
, const char **argv
, const char *prefix __used
)
1082 long nr_iterations
= 10, i
;
1085 page_size
= getpagesize();
1087 argc
= parse_options(argc
, argv
, options
, annotate_usage
, 0);
1090 * Special case: if there's an argument left then assume tha
1091 * it's a symbol filter:
1094 usage_with_options(annotate_usage
, options
);
1099 calibrate_run_measurement_overhead();
1100 calibrate_sleep_measurement_overhead();
1102 test_calibrations();
1105 print_task_traces();
1106 add_cross_task_wakeups();
1109 printf("------------------------------------------------------------\n");
1110 for (i
= 0; i
< nr_iterations
; i
++)