21 #include <subcmd/parse-options.h> 26 #include <linux/kernel.h> 27 #include <linux/log2.h> 28 #include <sys/prctl.h> 29 #include <sys/resource.h> 33 #include <semaphore.h> 36 #include <api/fs/fs.h> 37 #include <linux/time64.h> 41 #define PR_SET_NAME 15 45 #define MAX_PID 1024000 84 #define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" 87 #define TASK_RUNNING 0 88 #define TASK_INTERRUPTIBLE 1 89 #define TASK_UNINTERRUPTIBLE 2 90 #define __TASK_STOPPED 4 91 #define __TASK_TRACED 8 94 #define EXIT_ZOMBIE 32 95 #define EXIT_TRACE (EXIT_ZOMBIE | EXIT_DEAD) 98 #define TASK_WAKEKILL 128 99 #define TASK_WAKING 256 100 #define TASK_PARKED 512 110 struct list_head list;
119 struct list_head work_list;
154 #define COLOR_PIDS PERF_COLOR_BLUE 155 #define COLOR_CPUS PERF_COLOR_BG_RED 216 struct rb_root atom_root, sorted_atom_root, merged_atom_root;
217 struct list_head sort_list, cmp_pid;
274 struct rb_root sorted_root;
288 clock_gettime(CLOCK_MONOTONIC, &ts);
306 ts.tv_nsec = nsecs % 999999999;
307 ts.tv_sec = nsecs / 999999999;
309 nanosleep(&ts, NULL);
317 for (i = 0; i < 10; i++) {
322 min_delta =
min(min_delta, delta);
326 printf(
"run measurement overhead: %" PRIu64
" nsecs\n", min_delta);
334 for (i = 0; i < 10; i++) {
339 min_delta =
min(min_delta, delta);
344 printf(
"sleep measurement overhead: %" PRIu64
" nsecs\n", min_delta);
360 BUG_ON(!task->
atoms);
405 event->wakee =
wakee;
418 sem_init(wakee_event->
wait_sem, 0, 0);
420 event->wait_sem = wakee_event->
wait_sem;
426 u64
timestamp, u64 task_state __maybe_unused)
436 unsigned long pid,
const char *
comm)
442 if (sysctl__read_int(
"kernel/pid_max", &pid_max) < 0)
446 if (pid >= (
unsigned long)pid_max) {
449 while (pid >= (
unsigned long)pid_max)
458 task =
zalloc(
sizeof(*task));
461 strcpy(task->
comm, comm);
471 BUG_ON(!sched->
tasks);
475 printf(
"registered task #%ld, PID %ld (%s)\n", sched->
nr_tasks, pid, comm);
486 for (i = 0; i < sched->
nr_tasks; i++) {
487 task = sched->
tasks[i];
488 printf(
"task %6ld (%20s:%10ld), nr_events: %ld\n",
498 for (i = 0; i < sched->
nr_tasks; i++) {
499 task1 = sched->
tasks[i];
503 task2 = sched->
tasks[j];
513 switch (atom->
type) {
540 err = getrusage(RUSAGE_SELF, &ru);
543 sum = ru.ru_utime.tv_sec *
NSEC_PER_SEC + ru.ru_utime.tv_usec * NSEC_PER_USEC;
544 sum += ru.ru_stime.tv_sec *
NSEC_PER_SEC + ru.ru_stime.tv_usec * NSEC_PER_USEC;
551 struct perf_event_attr attr;
555 bool need_privilege =
false;
557 memset(&attr, 0,
sizeof(attr));
559 attr.type = PERF_TYPE_SOFTWARE;
560 attr.config = PERF_COUNT_SW_TASK_CLOCK;
567 if (errno == EMFILE) {
569 BUG_ON(getrlimit(RLIMIT_NOFILE, &limit) == -1);
570 limit.rlim_cur += sched->
nr_tasks - cur_task;
571 if (limit.rlim_cur > limit.rlim_max) {
572 limit.rlim_max = limit.rlim_cur;
573 need_privilege =
true;
575 if (setrlimit(RLIMIT_NOFILE, &limit) == -1) {
576 if (need_privilege && errno == EPERM)
577 strcpy(info,
"Need privilege\n");
581 strcpy(info,
"Have a try with -f option\n");
583 pr_err(
"Error: sys_perf_event_open() syscall returned " 584 "with %d (%s)\n%s", fd,
585 str_error_r(errno, sbuf,
sizeof(sbuf)), info);
596 ret = read(fd, &runtime,
sizeof(runtime));
597 BUG_ON(ret !=
sizeof(runtime));
613 u64 cpu_usage_0, cpu_usage_1;
614 unsigned long i, ret;
620 sprintf(comm2,
":%s", this_task->
comm);
634 for (i = 0; i < this_task->
nr_events; i++) {
640 this_task->
cpu_usage = cpu_usage_1 - cpu_usage_0;
659 err = pthread_attr_init(&attr);
661 err = pthread_attr_setstacksize(&attr,
662 (
size_t) max(16 * 1024, PTHREAD_STACK_MIN));
668 for (i = 0; i < sched->
nr_tasks; i++) {
670 BUG_ON(parms == NULL);
685 u64 cpu_usage_0, cpu_usage_1;
687 unsigned long i, ret;
693 for (i = 0; i < sched->
nr_tasks; i++) {
694 task = sched->
tasks[i];
706 for (i = 0; i < sched->
nr_tasks; i++) {
707 task = sched->
tasks[i];
729 for (i = 0; i < sched->
nr_tasks; i++) {
730 task = sched->
tasks[i];
738 u64 T0, T1, delta, avg_delta, fluct;
749 if (delta < avg_delta)
750 fluct = avg_delta - delta;
752 fluct = delta - avg_delta;
758 printf(
"#%-3ld: %0.3f, ", sched->
nr_runs, (
double)delta / NSEC_PER_MSEC);
760 printf(
"ravg: %0.2f, ", (
double)sched->
run_avg / NSEC_PER_MSEC);
762 printf(
"cpu: %0.2f / %0.2f",
770 printf(
" [%0.2f / %0.2f]",
790 printf(
"the run test took %" PRIu64
" nsecs\n", T1 - T0);
796 printf(
"the sleep test took %" PRIu64
" nsecs\n", T1 - T0);
809 printf(
"sched_wakeup event %p\n", evsel);
811 printf(
" ... pid %d woke up %s/%d\n", sample->
tid, comm, pid);
831 struct task_desc *prev, __maybe_unused *next;
832 u64 timestamp0, timestamp = sample->
time;
833 int cpu = sample->
cpu;
837 printf(
"sched_switch event %p\n", evsel);
844 delta = timestamp - timestamp0;
849 pr_err(
"hm, delta: %" PRIu64
" < 0 ?\n", delta);
853 pr_debug(
" ... switch from %s/%d to %s/%d [ran %" PRIu64
" nsecs]\n",
854 prev_comm, prev_pid, next_comm, next_pid, delta);
871 struct thread *child, *parent;
878 if (child == NULL || parent == NULL) {
879 pr_debug(
"thread does not exist on fork event: child %p, parent %p\n",
885 printf(
"fork event\n");
901 struct list_head list;
929 pr_debug(
"Failed to malloc memory for runtime data.\n");
941 BUG_ON(list_empty(list));
943 list_for_each_entry(sort, list, list) {
944 ret = sort->
cmp(l, r);
954 struct list_head *sort_list)
956 struct rb_node *
node = root->rb_node;
963 atoms = container_of(node,
struct work_atoms, node);
967 node = node->rb_left;
969 node = node->rb_right;
971 BUG_ON(thread != atoms->
thread);
980 struct list_head *sort_list)
982 struct rb_node **
new = &(root->rb_node), *parent = NULL;
994 new = &((*new)->rb_left);
996 new = &((*new)->rb_right);
999 rb_link_node(&data->
node, parent,
new);
1000 rb_insert_color(&data->
node, root);
1007 pr_err(
"No memory at %s\n", __func__);
1021 return str[prev_state];
1031 pr_err(
"Non memory at %s", __func__);
1037 if (run_state ==
'R') {
1048 u64 timestamp __maybe_unused)
1100 struct thread *sched_out, *sched_in;
1101 u64 timestamp0, timestamp = sample->
time;
1105 BUG_ON(cpu >=
MAX_CPUS || cpu < 0);
1110 delta = timestamp - timestamp0;
1115 pr_err(
"hm, delta: %" PRIu64
" < 0 ?\n", delta);
1121 if (sched_out == NULL || sched_in == NULL)
1130 pr_err(
"out-event: Internal tree error");
1143 pr_err(
"in-event: Internal tree error");
1170 u64 timestamp = sample->
time;
1171 int cpu = sample->
cpu,
err = -1;
1176 BUG_ON(cpu >=
MAX_CPUS || cpu < 0);
1182 pr_err(
"in-event: Internal tree error");
1205 u64 timestamp = sample->
time;
1217 pr_err(
"wakeup-event: Internal tree error");
1263 u64 timestamp = sample->
time;
1276 if (migrant == NULL)
1285 pr_err(
"migration-event: Internal tree error");
1312 char max_lat_at[32];
1330 for (i = 0; i < 24 - ret; i++)
1336 printf(
"|%11.3f ms |%9" PRIu64
" | avg:%9.3f ms | max:%9.3f ms | max at: %13s s\n",
1338 work_list->
nb_atoms, (
double)avg / NSEC_PER_MSEC,
1339 (
double)work_list->
max_lat / NSEC_PER_MSEC,
1429 &pid_sort_dimension,
1430 &avg_sort_dimension,
1431 &max_sort_dimension,
1432 &switch_sort_dimension,
1433 &runtime_sort_dimension,
1436 for (i = 0; i < ARRAY_SIZE(available_sorts); i++) {
1437 if (!strcmp(available_sorts[i]->
name, tok)) {
1438 list_add_tail(&available_sorts[i]->list, list);
1449 struct rb_node *
node;
1450 struct rb_root *
root = &sched->atom_root;
1454 node = rb_first(root);
1458 rb_erase(node, root);
1459 data = rb_entry(node,
struct work_atoms, node);
1462 if (root == &sched->atom_root) {
1520 u64 timestamp0, timestamp = sample->
time;
1522 int i, this_cpu = sample->
cpu;
1524 bool new_cpu =
false;
1526 char stimestamp[32];
1528 BUG_ON(this_cpu >=
MAX_CPUS || this_cpu < 0);
1530 if (this_cpu > sched->
max_cpu)
1534 cpus_nr = bitmap_weight(sched->
map.comp_cpus_mask,
MAX_CPUS);
1535 if (!test_and_set_bit(this_cpu, sched->
map.comp_cpus_mask)) {
1545 delta = timestamp - timestamp0;
1550 pr_err(
"hm, delta: %" PRIu64
" < 0 ?\n", delta);
1555 if (sched_in == NULL)
1594 for (i = 0; i < cpus_nr; i++) {
1598 const char *pid_color = color;
1599 const char *cpu_color = color;
1610 if (cpu != this_cpu)
1617 if (curr_tr == NULL) {
1632 const char *pid_color = color;
1642 if (sched->
map.
comp && new_cpu)
1659 int this_cpu = sample->
cpu,
err = 0;
1663 if (sched->
curr_pid[this_cpu] != (u32)-1) {
1668 if (sched->
curr_pid[this_cpu] != prev_pid)
1675 sched->
curr_pid[this_cpu] = next_pid;
1737 err =
f(tool, evsel, sample, machine);
1758 pr_err(
"Internal error: can't find thread\n");
1789 .force = sched->
force,
1794 if (session == NULL) {
1795 pr_debug(
"No Memory for session\n");
1807 pr_err(
"Failed to process events, error %d", err);
1827 unsigned long msecs;
1828 unsigned long usecs;
1830 msecs = nsecs / NSEC_PER_MSEC;
1831 nsecs -= msecs * NSEC_PER_MSEC;
1832 usecs = nsecs / NSEC_PER_USEC;
1833 printf(
"%*lu.%03lu ", width, msecs, usecs);
1856 u64 timestamp, u32 cpu)
1864 int i, n = __roundup_pow_of_two(cpu+1);
1867 p = realloc(r->
last_time, n *
sizeof(u64));
1872 for (i = r->
ncpu; i < n; ++i)
1886 if ((r == NULL) || (r->
last_time == NULL) || (cpu >= r->
ncpu))
1896 static char str[32];
1898 pid_t tid = thread->
tid;
1903 n = scnprintf(str,
sizeof(str),
"%s", comm);
1905 else if (tid != pid)
1906 n = scnprintf(str,
sizeof(str),
"%s[%d/%d]", comm, tid, pid);
1909 n = scnprintf(str,
sizeof(str),
"%s[%d]", comm, tid);
1922 printf(
"%15s %6s ",
"time",
"cpu");
1926 for (i = 0, j = 0; i <
ncpus; ++i) {
1935 "task name",
"wait time",
"sch delay",
"run time");
1938 printf(
" %s",
"state");
1945 printf(
"%15s %-6s ",
"",
"");
1948 printf(
" %*s ", ncpus,
"");
1951 "[tid/pid]",
"(msec)",
"(msec)",
"(msec)");
1979 unsigned bit = state ? ffs(state) : 0;
1982 if (thread->
tid == 0)
1985 return bit <
sizeof(state_to_char) - 1 ? state_to_char[bit] :
'?';
1998 u32 max_cpus = sched->
max_cpu + 1;
2004 printf(
"%15s [%04d] ", tstr, sample->
cpu);
2011 for (i = 0; i < max_cpus; ++i) {
2013 if (i == sample->
cpu)
2014 c = (thread->
tid == 0) ?
'i' :
's';
2034 snprintf(nstr,
sizeof(nstr),
"next: %s[%d]", next_comm, next_pid);
2041 if (thread->
tid == 0)
2093 pr_debug(
"time travel: wakeup time for task > previous sched_switch event\n");
2099 pr_debug(
"time travel: last sched out time for task > previous sched_switch event\n");
2128 return sample->
pid == 0;
2141 if (thread == NULL) {
2142 pr_debug(
"Failed to get thread for pid %d.\n", sample->
pid);
2150 NULL, NULL, sched->
max_stack + 2) != 0) {
2152 pr_err(
"Failed to resolve callchain. Skipping\n");
2169 if (!strcmp(sym->
name,
"schedule") ||
2170 !strcmp(sym->
name,
"__schedule") ||
2171 !strcmp(sym->
name,
"preempt_schedule"))
2185 itr =
zalloc(
sizeof(*itr));
2212 for (i = 0; i < ncpu; ++i) {
2214 if (idle_threads[i] == NULL)
2229 if (idle_threads == NULL)
2233 if ((idle_threads[i]))
2247 int i, j = __roundup_pow_of_two(cpu+1);
2250 p = realloc(idle_threads, j *
sizeof(
struct thread *));
2254 idle_threads = (
struct thread **) p;
2256 idle_threads[i] = NULL;
2262 if (idle_threads[cpu] == NULL) {
2265 if (idle_threads[cpu]) {
2271 return idle_threads[
cpu];
2294 pr_err(
"Failed to get idle thread for cpu %d.\n", sample->
cpu);
2299 sample->
tid ?: sample->
pid);
2300 if (thread == NULL) {
2301 pr_debug(
"Failed to get thread for tid %d. skipping sample.\n",
2307 struct thread *idle;
2312 pr_err(
"Failed to get idle thread for cpu %d.\n", sample->
cpu);
2374 printf(
"%15s [%04d] ", tstr, sample->
cpu);
2376 printf(
" %*s ", sched->
max_cpu + 1,
"");
2381 printf(
" %9s %9s %9s ",
"",
"",
"");
2427 u32 max_cpus = sched->
max_cpu + 1;
2433 max_cpus = sched->
max_cpu + 1;
2447 printf(
"%15s [%04d] ", tstr, sample->
cpu);
2454 for (i = 0; i < max_cpus; ++i) {
2455 c = (i == sample->
cpu) ?
'm' :
' ';
2464 printf(
" %9s %9s %9s ",
"",
"",
"");
2467 printf(
" cpu %d => %d", ocpu, dcpu);
2511 u64 tprev, t = sample->
time;
2517 pr_err(
"problem processing %d event. skipping it\n",
2524 if (thread == NULL) {
2548 if (tprev && ptime->
start > tprev)
2549 tprev = ptime->
start;
2558 if (tprev > ptime->
end)
2572 BUG_ON(thread->
tid != 0);
2579 if (last_tr == NULL)
2607 if (ptime->
end == 0 || t <= ptime->end)
2643 printf(
"%15s ", tstr);
2644 printf(
"lost %" PRIu64
" events on cpu %d\n", event->
lost.
lost, sample->
cpu);
2656 printf(
"%*s %5d %9" PRIu64
" ",
2668 printf(
"%5.2f", stddev);
2676 printf(
"%*s %5d %9" PRIu64
" ",
2739 const char *sep =
" <- ";
2751 list_for_each_entry(chain, &node->
val,
list) {
2752 if (chain->
ip >= PERF_CONTEXT_MAX)
2756 ret += fprintf(fp,
"%s%s", first ?
"" : sep,
2770 struct rb_node *rb_node = rb_first(root);
2772 printf(
" %16s %8s %s\n",
"Idle time (msec)",
"Count",
"Callchains");
2778 rb_node = rb_next(rb_node);
2780 ret += fprintf(fp,
" ");
2783 ret += fprintf(fp,
" %8d ", chain->
count);
2785 ret += fprintf(fp,
"\n");
2802 memset(&totals, 0,
sizeof(totals));
2803 totals.
sched = sched;
2806 printf(
"\nIdle-time summary\n");
2807 printf(
"%*s parent sched-out ",
comm_width,
"comm");
2808 printf(
" idle-time min-idle avg-idle max-idle stddev migrations\n");
2810 printf(
"\nWait-time summary\n");
2811 printf(
"%*s parent sched-in ",
comm_width,
"comm");
2812 printf(
" run-time sleep iowait preempt delay\n");
2814 printf(
"\nRuntime summary\n");
2815 printf(
"%*s parent sched-in ",
comm_width,
"comm");
2816 printf(
" run-time min-run avg-run max-run stddev migrations\n");
2819 printf(
" (msec) (msec) (msec) (msec) %s\n",
2826 printf(
"<no still running tasks>\n");
2828 printf(
"\nTerminated tasks:\n");
2831 printf(
"<no terminated tasks>\n");
2837 printf(
"\nIdle stats:\n");
2839 t = idle_threads[i];
2846 printf(
" CPU %2d idle for ", i);
2848 printf(
" msec (%6.2f%%)\n", 100.0 * r->
total_run_time / hist_time);
2850 printf(
" CPU %2d idle entire time window\n", i);
2859 printf(
"\nIdle stats by callchain:\n");
2863 t = idle_threads[i];
2874 printf(
" CPU %2d:", i);
2883 " Total number of unique tasks: %" PRIu64
"\n" 2884 "Total number of context switches: %" PRIu64
"\n",
2887 printf(
" Total run time (msec): ");
2891 printf(
" Total scheduling time (msec): ");
2893 printf(
" (x %d)\n", sched->
max_cpu);
2910 int this_cpu = sample->
cpu;
2912 if (this_cpu > sched->
max_cpu)
2918 err =
f(tool, event, evsel, sample, machine);
2930 list_for_each_entry(evsel, &evlist->
entries,
node) {
2933 pr_err(
"Failed to allocate memory for evsel runtime data\n");
2938 pr_info(
"Samples do not have callchains.\n");
2962 .force = sched->
force,
2988 if (session == NULL)
2991 evlist = session->
evlist;
2996 pr_err(
"Invalid time string\n");
3011 "sched:sched_switch")) {
3012 pr_err(
"No sched_switch events found. Have you run 'perf sched record'?\n");
3036 pr_err(
"Failed to process events, error %d", err);
3058 printf(
" INFO: %.3f%% unordered timestamps (%ld out of %ld)\n",
3063 printf(
" INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n",
3068 printf(
" INFO: %.3f%% context switch bugs (%ld out of %ld)",
3072 printf(
" (due to lost events?)");
3079 struct rb_node **
new = &(root->rb_node), *parent = NULL;
3090 cmp = strcmp(comm, this_comm);
3092 new = &((*new)->rb_left);
3093 }
else if (cmp < 0) {
3094 new = &((*new)->rb_right);
3100 list_splice(&data->
work_list, &this->work_list);
3101 if (this->max_lat < data->
max_lat) {
3102 this->max_lat = data->
max_lat;
3111 rb_link_node(&data->
node, parent,
new);
3112 rb_insert_color(&data->
node, root);
3118 struct rb_node *
node;
3123 while ((node = rb_first(&sched->atom_root))) {
3124 rb_erase(node, &sched->atom_root);
3125 data = rb_entry(node,
struct work_atoms, node);
3132 struct rb_node *next;
3142 printf(
"\n -----------------------------------------------------------------------------------------------------------------\n");
3143 printf(
" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n");
3144 printf(
" -----------------------------------------------------------------------------------------------------------------\n");
3146 next = rb_first(&sched->sorted_atom_root);
3153 next = rb_next(next);
3157 printf(
" -----------------------------------------------------------------------------------------------------------------\n");
3158 printf(
" TOTAL: |%11.3f ms |%9" PRIu64
" |\n",
3161 printf(
" ---------------------------------------------------\n");
3173 sched->
max_cpu = sysconf(_SC_NPROCESSORS_CONF);
3267 printf(
"run atoms optimized: %ld\n",
3274 printf(
"------------------------------------------------------------\n");
3282 const char *
const usage_msg[])
3286 for (tok = strtok_r(str,
", ", &tmp);
3287 tok; tok = strtok_r(NULL,
", ", &tmp)) {
3289 usage_with_options_msg(usage_msg, options,
3290 "Unknown --sort key: `%s'", tok);
3301 unsigned int rec_argc, i, j;
3302 const char **rec_argv;
3303 const char *
const record_args[] = {
3309 "-e",
"sched:sched_switch",
3310 "-e",
"sched:sched_stat_wait",
3311 "-e",
"sched:sched_stat_sleep",
3312 "-e",
"sched:sched_stat_iowait",
3313 "-e",
"sched:sched_stat_runtime",
3314 "-e",
"sched:sched_process_fork",
3315 "-e",
"sched:sched_wakeup",
3316 "-e",
"sched:sched_wakeup_new",
3317 "-e",
"sched:sched_migrate_task",
3320 rec_argc = ARRAY_SIZE(record_args) + argc - 1;
3321 rec_argv = calloc(rec_argc + 1,
sizeof(
char *));
3323 if (rec_argv == NULL)
3326 for (i = 0; i < ARRAY_SIZE(record_args); i++)
3327 rec_argv[i] = strdup(record_args[i]);
3329 for (j = 1; j < (
unsigned int)argc; j++, i++)
3330 rec_argv[i] = argv[j];
3332 BUG_ON(i != rec_argc);
3347 .ordered_events =
true,
3349 .cmp_pid = LIST_HEAD_INIT(sched.
cmp_pid),
3350 .sort_list = LIST_HEAD_INIT(sched.sort_list),
3351 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
3352 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
3354 .replay_repeat = 10,
3356 .next_shortname1 =
'A',
3357 .next_shortname2 =
'0',
3359 .show_callchain = 1,
3362 const struct option sched_options[] = {
3363 OPT_STRING(
'i',
"input", &
input_name,
"file",
3365 OPT_INCR(
'v',
"verbose", &
verbose,
3366 "be more verbose (show symbol address, etc)"),
3367 OPT_BOOLEAN(
'D',
"dump-raw-trace", &
dump_trace,
3368 "dump raw trace in ASCII"),
3369 OPT_BOOLEAN(
'f',
"force", &sched.
force,
"don't complain, do it"),
3372 const struct option latency_options[] = {
3373 OPT_STRING(
's',
"sort", &sched.
sort_order,
"key[,key2...]",
3374 "sort by key(s): runtime, switch, avg, max"),
3376 "CPU to profile on"),
3378 "latency stats per pid instead of per comm"),
3379 OPT_PARENT(sched_options)
3381 const struct option replay_options[] = {
3383 "repeat the workload replay N times (-1: infinite)"),
3384 OPT_PARENT(sched_options)
3386 const struct option map_options[] = {
3387 OPT_BOOLEAN(0,
"compact", &sched.
map.
comp,
3388 "map output in compact mode"),
3390 "highlight given pids in map"),
3392 "highlight given CPUs in map"),
3393 OPT_STRING(0,
"cpus", &sched.
map.
cpus_str,
"cpus",
3394 "display given CPUs in map"),
3395 OPT_PARENT(sched_options)
3397 const struct option timehist_options[] = {
3399 "file",
"vmlinux pathname"),
3401 "file",
"kallsyms pathname"),
3403 "Display call chains if present (default on)"),
3404 OPT_UINTEGER(0,
"max-stack", &sched.
max_stack,
3405 "Maximum number of functions to display backtrace."),
3407 "Look for files with symbols relative to this directory"),
3409 "Show only syscall summary with statistics"),
3410 OPT_BOOLEAN(
'S',
"with-summary", &sched.
summary,
3411 "Show all syscalls and summary with statistics"),
3412 OPT_BOOLEAN(
'w',
"wakeups", &sched.
show_wakeups,
"Show wakeup events"),
3413 OPT_BOOLEAN(
'n',
"next", &sched.
show_next,
"Show next task"),
3414 OPT_BOOLEAN(
'M',
"migrations", &sched.
show_migrations,
"Show migration events"),
3415 OPT_BOOLEAN(
'V',
"cpu-visual", &sched.
show_cpu_visual,
"Add CPU visual"),
3416 OPT_BOOLEAN(
'I',
"idle-hist", &sched.
idle_hist,
"Show idle events only"),
3417 OPT_STRING(0,
"time", &sched.
time_str,
"str",
3418 "Time span for analysis (start,stop)"),
3419 OPT_BOOLEAN(0,
"state", &sched.
show_state,
"Show task state when sched-out"),
3421 "analyze events only for given process id(s)"),
3423 "analyze events only for given thread id(s)"),
3424 OPT_PARENT(sched_options)
3427 const char *
const latency_usage[] = {
3428 "perf sched latency [<options>]",
3431 const char *
const replay_usage[] = {
3432 "perf sched replay [<options>]",
3435 const char *
const map_usage[] = {
3436 "perf sched map [<options>]",
3439 const char *
const timehist_usage[] = {
3440 "perf sched timehist [<options>]",
3443 const char *
const sched_subcommands[] = {
"record",
"latency",
"map",
3446 const char *sched_usage[] = {
3466 for (i = 0; i < ARRAY_SIZE(sched.
curr_pid); i++)
3469 argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands,
3470 sched_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3472 usage_with_options(sched_usage, sched_options);
3477 if (!strcmp(argv[0],
"script"))
3480 if (!strncmp(argv[0],
"rec", 3)) {
3482 }
else if (!strncmp(argv[0],
"lat", 3)) {
3485 argc = parse_options(argc, argv, latency_options, latency_usage, 0);
3487 usage_with_options(latency_usage, latency_options);
3491 }
else if (!strcmp(argv[0],
"map")) {
3493 argc = parse_options(argc, argv, map_options, map_usage, 0);
3495 usage_with_options(map_usage, map_options);
3500 }
else if (!strncmp(argv[0],
"rep", 3)) {
3503 argc = parse_options(argc, argv, replay_options, replay_usage, 0);
3505 usage_with_options(replay_usage, replay_options);
3508 }
else if (!strcmp(argv[0],
"timehist")) {
3510 argc = parse_options(argc, argv, timehist_options,
3513 usage_with_options(timehist_usage, timehist_options);
3517 pr_err(
" Error: -s and -[n|w] are mutually exclusive.\n");
3518 parse_options_usage(timehist_usage, timehist_options,
"s",
true);
3520 parse_options_usage(NULL, timehist_options,
"w",
true);
3522 parse_options_usage(NULL, timehist_options,
"n",
true);
3528 usage_with_options(sched_usage, sched_options);
pthread_mutex_t work_done_wait_mutex
static void setup_sorting(struct perf_sched *sched, const struct option *options, const char *const usage_msg[])
static bool thread__is_filtered(struct thread *thread)
struct thread_map * thread_map__new_by_tid_str(const char *tid_str)
u64 runavg_parent_cpu_usage
int color_fprintf(FILE *fp, const char *color, const char *fmt,...)
static int setup_color_pids(struct perf_sched *sched)
static int perf_timehist__process_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static struct thread * timehist_get_thread(struct perf_sched *sched, struct perf_sample *sample, struct machine *machine, struct perf_evsel *evsel)
const struct trace_sched_handler * tp_handler
static int perf_sched__lat(struct perf_sched *sched)
struct thread * curr_thread[MAX_CPUS]
static int process_sched_migrate_task_event(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
double avg_stats(struct stats *stats)
static struct task_desc * register_pid(struct perf_sched *sched, unsigned long pid, const char *comm)
struct perf_evlist * evlist
static int replay_wakeup_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused)
#define EVSEL__PRINT_ONELINE
static int replay_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused)
static int show_thread_runtime(struct thread *t, void *priv)
int callchain_cursor__copy(struct callchain_cursor *dst, struct callchain_cursor *src)
int machine__resolve(struct machine *machine, struct addr_location *al, struct perf_sample *sample)
static void print_thread_runtime(struct thread *t, struct thread_runtime *r)
static void timehist_header(struct perf_sched *sched)
const char * vmlinux_name
unsigned long nr_timestamps
struct callchain_root callchain
static u64 get_nsecs(void)
unsigned long multitarget_wakeups
static void run_one_test(struct perf_sched *sched)
static void perf_sched__process_event(struct perf_sched *sched, struct sched_atom *atom)
static int perf_sched__map(struct perf_sched *sched)
struct task_desc ** tasks
int cmd_record(int argc, const char **argv)
static int process_sched_runtime_event(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static void callchain_cursor_reset(struct callchain_cursor *cursor)
static void timehist_print_migration_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *migrated)
static void test_calibrations(struct perf_sched *sched)
#define thread__zput(thread)
int(* migrate_task_event)(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
const char * graph_dotted_line
static struct perf_time_interval ptime
__thread struct callchain_cursor callchain_cursor
static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
static int switch_cmp(struct work_atoms *l, struct work_atoms *r)
#define TASK_STATE_TO_CHAR_STR
static int add_sched_out_event(struct work_atoms *atoms, char run_state, u64 timestamp)
static bool is_idle_sample(struct perf_sample *sample, struct perf_evsel *evsel)
struct ip_callchain * callchain
struct callchain_cursor cursor
char * callchain_list__sym_name(struct callchain_list *cl, char *bf, size_t bfsize, bool show_dso)
static struct sched_atom * last_event(struct task_desc *task)
int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al, int left_alignment, unsigned int print_opts, struct callchain_cursor *cursor, FILE *fp)
static struct evsel_runtime * perf_evsel__get_runtime(struct perf_evsel *evsel)
static void perf_sched__sort_lat(struct perf_sched *sched)
struct perf_data_file file
int machine__for_each_thread(struct machine *machine, int(*fn)(struct thread *thread, void *p), void *priv)
const char * tid_list_str
static struct thread_runtime * thread__init_runtime(struct thread *thread)
unsigned long nr_sleep_events
static struct work_atoms * thread_atoms_search(struct rb_root *root, struct thread *thread, struct list_head *sort_list)
unsigned long nr_sleep_corrections
static void * thread_func(void *ctx)
static struct thread * map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid)
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task, u64 timestamp, u64 task_state __maybe_unused)
int perf_event__process_exit(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static void callchain_cursor_commit(struct callchain_cursor *cursor)
static int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, int cpu, int group_fd, unsigned long flags)
int timestamp__scnprintf_usec(u64 timestamp, char *buf, size_t sz)
static void timehist_print_wakeup_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine, struct thread *awakened)
int perf_event__process_fork(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static u64 perf_evsel__get_time(struct perf_evsel *evsel, u32 cpu)
static void timehist_print_summary(struct perf_sched *sched, struct perf_session *session)
static int perf_sched__read_events(struct perf_sched *sched)
int(* fork_event)(struct perf_sched *sched, union perf_event *event, struct machine *machine)
static void save_task_callchain(struct perf_sched *sched, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
double stddev_stats(struct stats *stats)
static void print_sched_time(unsigned long long nsecs, int width)
bool perf_time__skip_sample(struct perf_time_interval *ptime, u64 timestamp)
struct perf_time_interval ptime
static u64 get_cpu_usage_nsec_parent(void)
bool perf_session__has_traces(struct perf_session *session, const char *msg)
void thread__delete(struct thread *thread)
x86 movsq based memset() in arch/x86/lib/memset_64.S") MEMSET_FN(memset_erms
int cmd_script(int argc, const char **argv)
#define TASK_UNINTERRUPTIBLE
static void perf_evsel__save_time(struct perf_evsel *evsel, u64 timestamp, u32 cpu)
static int latency_wakeup_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
void perf_session__delete(struct perf_session *session)
unsigned long nr_context_switch_bugs
static void init_stats(struct stats *stats)
struct sched_atom ** atoms
#define PERF_COLOR_NORMAL
static int avg_cmp(struct work_atoms *l, struct work_atoms *r)
struct task_desc ** pid_to_task
static void create_tasks(struct perf_sched *sched)
static void burn_nsecs(struct perf_sched *sched, u64 nsecs)
int(* sched_handler)(struct perf_tool *tool, union perf_event *event, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
#define EVSEL__PRINT_CALLCHAIN_ARROW
struct thread * machine__find_thread(struct machine *machine, pid_t pid, pid_t tid)
static int process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine __maybe_unused)
static int sort_dimension__add(const char *tok, struct list_head *list)
const char * thread__comm_str(const struct thread *thread)
struct rb_root sorted_root
#define pr_debug(fmt,...)
static bool timehist_skip_sample(struct perf_sched *sched, struct thread *thread, struct perf_evsel *evsel, struct perf_sample *sample)
static char * timehist_get_commstr(struct thread *thread)
void update_stats(struct stats *stats, u64 val)
static struct perf_session * session
struct thread * last_thread
static bool thread__has_color(struct thread *thread)
static int replay_fork_event(struct perf_sched *sched, union perf_event *event, struct machine *machine)
static void callchain_cursor_advance(struct callchain_cursor *cursor)
static void timehist_print_sample(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, struct thread *thread, u64 t, int state)
const char * default_sort_order
static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task, u64 timestamp, struct task_desc *wakee)
static char * perf_evsel__strval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
static void wait_for_tasks(struct perf_sched *sched)
static void print_thread_waittime(struct thread *t, struct thread_runtime *r)
struct callchain_node * parent
static int max_cmp(struct work_atoms *l, struct work_atoms *r)
static void calibrate_sleep_measurement_overhead(struct perf_sched *sched)
static void calibrate_run_measurement_overhead(struct perf_sched *sched)
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS)
static struct perf_tool tool
static char task_state_char(struct thread *thread, int state)
static int str(yyscan_t scanner, int token)
static int timehist_sched_switch_event(struct perf_tool *tool, union perf_event *event, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine __maybe_unused)
bool thread_map__has(struct thread_map *threads, pid_t pid)
unsigned long targetless_wakeups
int cmd_sched(int argc, const char **argv)
double rel_stddev_stats(double stddev, double avg)
unsigned long nr_run_events_optimized
static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task, u64 timestamp, u64 duration)
struct list_head work_list
static int setup_color_cpus(struct perf_sched *sched)
u64 run_measurement_overhead
unsigned long nr_wakeup_events
static int perf_sched__replay(struct perf_sched *sched)
static int show_deadthread_runtime(struct thread *t, void *priv)
const char * pid_list_str
int callchain_append(struct callchain_root *root, struct callchain_cursor *cursor, u64 period)
struct thread_map_data map[]
static void add_cross_task_wakeups(struct perf_sched *sched)
int(* wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, const char *name)
static void callchain_init(struct callchain_root *root)
static int perf_sched__process_comm(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
bool cpu_map__has(struct cpu_map *cpus, int cpu)
int(* sort_fn_t)(struct work_atoms *, struct work_atoms *)
static struct thread * get_idle_thread(int cpu)
struct perf_time_interval hist_time
static int process_sched_switch_event(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static u64 get_cpu_usage_nsec_self(int fd)
struct perf_sched_map map
unsigned long nr_run_events
static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
const char * perf_evsel__name(struct perf_evsel *evsel)
static void sleep_nsecs(u64 nsecs)
struct rb_root atom_root sorted_atom_root merged_atom_root
struct perf_event_header header
struct perf_sched * sched
static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine)
static int timehist_migrate_task_event(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static int runtime_cmp(struct work_atoms *l, struct work_atoms *r)
static struct sched_atom * get_new_event(struct task_desc *task, u64 timestamp)
static int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp)
unsigned long perf_event_open_cloexec_flag(void)
static void timehist_update_runtime_stats(struct thread_runtime *r, u64 t, u64 tprev)
#define EVSEL__PRINT_SKIP_IGNORED
unsigned long nr_lost_chunks
int(* runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
struct perf_session * perf_session__new(struct perf_data *data, bool repipe, struct perf_tool *tool)
const char * kallsyms_name
void thread__put(struct thread *thread)
static int thread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r)
static int process_sched_wakeup_event(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
int perf_session__process_events(struct perf_session *session)
static int __cmd_record(int argc, const char **argv)
static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list)
static int latency_runtime_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static int sym(yyscan_t scanner, int type, int config)
static int timehist_sched_wakeup_event(struct perf_tool *tool, union perf_event *event __maybe_unused, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
struct events_stats stats
struct perf_evsel * perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist, const char *name)
u64 cpu_last_switched[MAX_CPUS]
static unsigned int ncpus
unsigned long nr_lost_events
struct thread * thread__new(pid_t pid, pid_t tid)
const char * color_pids_str
struct perf_header header
int symbol__init(struct perf_env *env)
static unsigned int nsecs
static void perf_sched__merge_lat(struct perf_sched *sched)
static int init_idle_thread(struct thread *thread)
static void __thread_latency_insert(struct rb_root *root, struct work_atoms *data, struct list_head *sort_list)
static void free_idle_threads(void)
unsigned int replay_repeat
u32 nr_events[PERF_RECORD_HEADER_MAX]
static void save_idle_callchain(struct perf_sched *sched, struct idle_thread_runtime *itr, struct perf_sample *sample)
static size_t timehist_print_idlehist_callchain(struct rb_root *root)
static struct thread_runtime * thread__get_runtime(struct thread *thread)
static void add_runtime_event(struct work_atoms *atoms, u64 delta, u64 timestamp __maybe_unused)
int(* switch_event)(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static size_t callchain__fprintf_folded(FILE *fp, struct callchain_node *node)
static void print_task_traces(struct perf_sched *sched)
static void __merge_work_atoms(struct rb_root *root, struct work_atoms *data)
enum sched_event_type type
static void thread__set_priv(struct thread *thread, void *p)
int perf_event__process_lost(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
struct thread_map * color_pids
int thread__resolve_callchain(struct thread *thread, struct callchain_cursor *cursor, struct perf_evsel *evsel, struct perf_sample *sample, struct symbol **parent, struct addr_location *root_al, int max_stack)
static void add_sched_in_event(struct work_atoms *atoms, u64 timestamp)
u64 sleep_measurement_overhead
struct thread * thread__get(struct thread *thread)
static int latency_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
struct cpu_map * cpu_map__new(const char *cpu_list)
#define perf_session__set_tracepoints_handlers(session, array)
static int perf_sched__process_fork_event(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct machine *machine)
const char * color_cpus_str
static bool evsel__has_callchain(const struct perf_evsel *evsel)
static int __show_thread_runtime(struct thread *t, void *priv)
int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
static int setup_map_cpus(struct perf_sched *sched)
struct cpu_map * color_cpus
static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
int callchain_register_param(struct callchain_param *param)
static int timehist_check_attr(struct perf_sched *sched, struct perf_evlist *evlist)
static int perf_sched__timehist(struct perf_sched *sched)
static int init_idle_threads(int ncpu)
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
int perf_time__parse_str(struct perf_time_interval *ptime, const char *ostr)
static struct thread ** idle_threads
struct perf_sched * sched
int(* tracepoint_handler)(struct perf_tool *tool, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
static int timehist_sched_change_event(struct perf_tool *tool, union perf_event *event, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
pthread_mutex_t start_work_mutex
static int latency_migrate_task_event(struct perf_sched *sched, struct perf_evsel *evsel, struct perf_sample *sample, struct machine *machine)
unsigned long nr_unordered_timestamps
struct timeval start end runtime
static struct callchain_cursor_node * callchain_cursor_current(struct callchain_cursor *cursor)
static void * thread__priv(struct thread *thread)
void static void * zalloc(size_t size)
static void print_bad_events(struct perf_sched *sched)
static char sched_out_state(u64 prev_state)
struct list_head sort_list cmp_pid