Lines Matching refs:sched
97 /* task state bitmask, copied from include/linux/sched.h */
147 int (*switch_event)(struct perf_sched *sched, struct evsel *evsel,
150 int (*runtime_event)(struct perf_sched *sched, struct evsel *evsel,
153 int (*wakeup_event)(struct perf_sched *sched, struct evsel *evsel,
157 int (*fork_event)(struct perf_sched *sched, union perf_event *event,
160 int (*migrate_task_event)(struct perf_sched *sched,
254 u64 last_time; /* time of previous sched in/out event */
259 u64 dt_delay; /* time between wakeup and sched-in */
306 static void burn_nsecs(struct perf_sched *sched, u64 nsecs)
312 } while (T1 + sched->run_measurement_overhead < T0 + nsecs);
325 static void calibrate_run_measurement_overhead(struct perf_sched *sched)
332 burn_nsecs(sched, 0);
337 sched->run_measurement_overhead = min_delta;
342 static void calibrate_sleep_measurement_overhead(struct perf_sched *sched)
355 sched->sleep_measurement_overhead = min_delta;
388 static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task,
398 sched->nr_run_events_optimized++;
408 sched->nr_run_events++;
411 static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task,
422 sched->targetless_wakeups++;
426 sched->multitarget_wakeups++;
435 sched->nr_wakeup_events++;
438 static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task,
445 sched->nr_sleep_events++;
448 static struct task_desc *register_pid(struct perf_sched *sched,
454 if (sched->pid_to_task == NULL) {
457 BUG_ON((sched->pid_to_task = calloc(pid_max, sizeof(struct task_desc *))) == NULL);
460 BUG_ON((sched->pid_to_task = realloc(sched->pid_to_task, (pid + 1) *
463 sched->pid_to_task[pid_max++] = NULL;
466 task = sched->pid_to_task[pid];
473 task->nr = sched->nr_tasks;
479 add_sched_event_sleep(sched, task, 0, 0);
481 sched->pid_to_task[pid] = task;
482 sched->nr_tasks++;
483 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_desc *));
484 BUG_ON(!sched->tasks);
485 sched->tasks[task->nr] = task;
488 printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm);
494 static void print_task_traces(struct perf_sched *sched)
499 for (i = 0; i < sched->nr_tasks; i++) {
500 task = sched->tasks[i];
506 static void add_cross_task_wakeups(struct perf_sched *sched)
511 for (i = 0; i < sched->nr_tasks; i++) {
512 task1 = sched->tasks[i];
514 if (j == sched->nr_tasks)
516 task2 = sched->tasks[j];
517 add_sched_event_wakeup(sched, task1, 0, task2);
521 static void perf_sched__process_event(struct perf_sched *sched,
528 burn_nsecs(sched, atom->duration);
562 static int self_open_counters(struct perf_sched *sched, unsigned long cur_task)
581 if (sched->force) {
583 limit.rlim_cur += sched->nr_tasks - cur_task;
617 struct perf_sched *sched;
625 struct perf_sched *sched = parms->sched;
638 while (!sched->thread_funcs_exit) {
641 mutex_lock(&sched->start_work_mutex);
642 mutex_unlock(&sched->start_work_mutex);
648 perf_sched__process_event(sched, this_task->atoms[i]);
656 mutex_lock(&sched->work_done_wait_mutex);
657 mutex_unlock(&sched->work_done_wait_mutex);
662 static void create_tasks(struct perf_sched *sched)
663 EXCLUSIVE_LOCK_FUNCTION(sched->start_work_mutex)
664 EXCLUSIVE_LOCK_FUNCTION(sched->work_done_wait_mutex)
676 mutex_lock(&sched->start_work_mutex);
677 mutex_lock(&sched->work_done_wait_mutex);
678 for (i = 0; i < sched->nr_tasks; i++) {
681 parms->task = task = sched->tasks[i];
682 parms->sched = sched;
683 parms->fd = self_open_counters(sched, i);
693 static void destroy_tasks(struct perf_sched *sched)
694 UNLOCK_FUNCTION(sched->start_work_mutex)
695 UNLOCK_FUNCTION(sched->work_done_wait_mutex)
701 mutex_unlock(&sched->start_work_mutex);
702 mutex_unlock(&sched->work_done_wait_mutex);
704 for (i = 0; i < sched->nr_tasks; i++) {
705 task = sched->tasks[i];
714 static void wait_for_tasks(struct perf_sched *sched)
715 EXCLUSIVE_LOCKS_REQUIRED(sched->work_done_wait_mutex)
716 EXCLUSIVE_LOCKS_REQUIRED(sched->start_work_mutex)
722 sched->start_time = get_nsecs();
723 sched->cpu_usage = 0;
724 mutex_unlock(&sched->work_done_wait_mutex);
726 for (i = 0; i < sched->nr_tasks; i++) {
727 task = sched->tasks[i];
732 mutex_lock(&sched->work_done_wait_mutex);
736 mutex_unlock(&sched->start_work_mutex);
738 for (i = 0; i < sched->nr_tasks; i++) {
739 task = sched->tasks[i];
743 sched->cpu_usage += task->cpu_usage;
748 if (!sched->runavg_cpu_usage)
749 sched->runavg_cpu_usage = sched->cpu_usage;
750 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * (sched->replay_repeat - 1) + sched->cpu_usage) / sched->replay_repeat;
752 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
753 if (!sched->runavg_parent_cpu_usage)
754 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage;
755 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * (sched->replay_repeat - 1) +
756 sched->parent_cpu_usage)/sched->replay_repeat;
758 mutex_lock(&sched->start_work_mutex);
760 for (i = 0; i < sched->nr_tasks; i++) {
761 task = sched->tasks[i];
767 static void run_one_test(struct perf_sched *sched)
768 EXCLUSIVE_LOCKS_REQUIRED(sched->work_done_wait_mutex)
769 EXCLUSIVE_LOCKS_REQUIRED(sched->start_work_mutex)
774 wait_for_tasks(sched);
778 sched->sum_runtime += delta;
779 sched->nr_runs++;
781 avg_delta = sched->sum_runtime / sched->nr_runs;
786 sched->sum_fluct += fluct;
787 if (!sched->run_avg)
788 sched->run_avg = delta;
789 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
791 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / NSEC_PER_MSEC);
793 printf("ravg: %0.2f, ", (double)sched->run_avg / NSEC_PER_MSEC);
796 (double)sched->cpu_usage / NSEC_PER_MSEC, (double)sched->runavg_cpu_usage / NSEC_PER_MSEC);
801 * accurate than the sched->sum_exec_runtime based statistics:
804 (double)sched->parent_cpu_usage / NSEC_PER_MSEC,
805 (double)sched->runavg_parent_cpu_usage / NSEC_PER_MSEC);
810 if (sched->nr_sleep_corrections)
811 printf(" (%ld sleep corrections)\n", sched->nr_sleep_corrections);
812 sched->nr_sleep_corrections = 0;
815 static void test_calibrations(struct perf_sched *sched)
820 burn_nsecs(sched, NSEC_PER_MSEC);
833 replay_wakeup_event(struct perf_sched *sched,
847 waker = register_pid(sched, sample->tid, "<unknown>");
848 wakee = register_pid(sched, pid, comm);
850 add_sched_event_wakeup(sched, waker, sample->time, wakee);
854 static int replay_switch_event(struct perf_sched *sched,
875 timestamp0 = sched->cpu_last_switched[cpu];
889 prev = register_pid(sched, prev_pid, prev_comm);
890 next = register_pid(sched, next_pid, next_comm);
892 sched->cpu_last_switched[cpu] = timestamp;
894 add_sched_event_run(sched, prev, timestamp, delta);
895 add_sched_event_sleep(sched, prev, timestamp, prev_state);
900 static int replay_fork_event(struct perf_sched *sched,
923 register_pid(sched, thread__tid(parent), thread__comm_str(parent));
924 register_pid(sched, thread__tid(child), thread__comm_str(child));
1039 static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
1049 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
1128 static int latency_switch_event(struct perf_sched *sched,
1144 timestamp0 = sched->cpu_last_switched[cpu];
1145 sched->cpu_last_switched[cpu] = timestamp;
1161 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
1163 if (thread_atoms_insert(sched, sched_out))
1165 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
1174 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
1176 if (thread_atoms_insert(sched, sched_in))
1178 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
1198 static int latency_runtime_event(struct perf_sched *sched,
1206 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1215 if (thread_atoms_insert(sched, thread))
1217 atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1233 static int latency_wakeup_event(struct perf_sched *sched,
1248 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1250 if (thread_atoms_insert(sched, wakee))
1252 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1276 if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1279 sched->nr_timestamps++;
1281 sched->nr_unordered_timestamps++;
1294 static int latency_migrate_task_event(struct perf_sched *sched,
1309 if (sched->profile_cpu == -1)
1315 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1317 if (thread_atoms_insert(sched, migrant))
1319 register_pid(sched, thread__tid(migrant), thread__comm_str(migrant));
1320 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1334 sched->nr_timestamps++;
1337 sched->nr_unordered_timestamps++;
1344 static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list)
1359 sched->all_runtime += work_list->total_runtime;
1360 sched->all_count += work_list->nb_atoms;
1492 static void perf_sched__sort_lat(struct perf_sched *sched)
1495 struct rb_root_cached *root = &sched->atom_root;
1505 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list);
1507 if (root == &sched->atom_root) {
1508 root = &sched->merged_atom_root;
1518 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1520 if (sched->tp_handler->wakeup_event)
1521 return sched->tp_handler->wakeup_event(sched, evsel, sample, machine);
1549 map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid)
1556 if (!sched->map.color_pids || !thread || thread__priv(thread))
1559 if (thread_map__has(sched->map.color_pids, tid))
1566 static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,
1586 if (this_cpu.cpu > sched->max_cpu.cpu)
1587 sched->max_cpu = this_cpu;
1589 if (sched->map.comp) {
1590 cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS);
1591 if (!__test_and_set_bit(this_cpu.cpu, sched->map.comp_cpus_mask)) {
1592 sched->map.comp_cpus[cpus_nr++] = this_cpu;
1596 cpus_nr = sched->max_cpu.cpu;
1598 timestamp0 = sched->cpu_last_switched[this_cpu.cpu];
1599 sched->cpu_last_switched[this_cpu.cpu] = timestamp;
1610 sched_in = map__findnew_thread(sched, machine, -1, next_pid);
1620 sched->curr_thread[this_cpu.cpu] = thread__get(sched_in);
1634 tr->shortname[0] = sched->next_shortname1;
1635 tr->shortname[1] = sched->next_shortname2;
1637 if (sched->next_shortname1 < 'Z') {
1638 sched->next_shortname1++;
1640 sched->next_shortname1 = 'A';
1641 if (sched->next_shortname2 < '9')
1642 sched->next_shortname2++;
1644 sched->next_shortname2 = '0';
1652 .cpu = sched->map.comp ? sched->map.comp_cpus[i].cpu : i,
1654 struct thread *curr_thread = sched->curr_thread[cpu.cpu];
1662 if (sched->map.cpus && !perf_cpu_map__has(sched->map.cpus, cpu))
1665 if (sched->map.color_cpus && perf_cpu_map__has(sched->map.color_cpus, cpu))
1673 if (sched->curr_thread[cpu.cpu]) {
1674 curr_tr = thread__get_runtime(sched->curr_thread[cpu.cpu]);
1684 if (sched->map.cpus && !perf_cpu_map__has(sched->map.cpus, this_cpu))
1700 if (sched->map.comp && new_cpu)
1716 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1721 if (sched->curr_pid[this_cpu] != (u32)-1) {
1726 if (sched->curr_pid[this_cpu] != prev_pid)
1727 sched->nr_context_switch_bugs++;
1730 if (sched->tp_handler->switch_event)
1731 err = sched->tp_handler->switch_event(sched, evsel, sample, machine);
1733 sched->curr_pid[this_cpu] = next_pid;
1742 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1744 if (sched->tp_handler->runtime_event)
1745 return sched->tp_handler->runtime_event(sched, evsel, sample, machine);
1755 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1761 if (sched->tp_handler->fork_event)
1762 return sched->tp_handler->fork_event(sched, event, machine);
1772 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1774 if (sched->tp_handler->migrate_task_event)
1775 return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine);
1832 static int perf_sched__read_events(struct perf_sched *sched)
1835 { "sched:sched_switch", process_sched_switch_event, },
1836 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1837 { "sched:sched_wakeup", process_sched_wakeup_event, },
1838 { "sched:sched_waking", process_sched_wakeup_event, },
1839 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1840 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1846 .force = sched->force,
1850 session = perf_session__new(&data, &sched->tool);
1859 if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking"))
1872 sched->nr_events = session->evlist->stats.nr_events[0];
1873 sched->nr_lost_events = session->evlist->stats.total_lost;
1874 sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
1977 static void timehist_header(struct perf_sched *sched)
1979 u32 ncpus = sched->max_cpu.cpu + 1;
1984 if (sched->show_cpu_visual) {
1997 if (sched->show_state)
2007 if (sched->show_cpu_visual)
2013 if (sched->show_state)
2023 if (sched->show_cpu_visual)
2030 if (sched->show_state)
2048 static void timehist_print_sample(struct perf_sched *sched,
2058 u32 max_cpus = sched->max_cpu.cpu + 1;
2069 if (sched->show_cpu_visual) {
2075 /* flag idle times with 'i'; others are sched events */
2093 if (sched->show_state)
2096 if (sched->show_next) {
2101 if (sched->show_wakeups && !sched->show_next)
2107 if (sched->show_callchain)
2124 * tprev = time of previous sched out event
2126 * last_time = time of last sched change event for current task
2162 pr_debug("time travel: last sched out time for task > previous sched_switch event\n");
2188 if (strcmp(evsel__name(evsel), "sched:sched_switch") == 0)
2194 static void save_task_callchain(struct perf_sched *sched,
2209 if (!sched->show_callchain || sample->callchain == NULL)
2215 NULL, NULL, sched->max_stack + 2) != 0) {
2339 static void save_idle_callchain(struct perf_sched *sched,
2345 if (!sched->show_callchain || sample->callchain == NULL)
2355 static struct thread *timehist_get_thread(struct perf_sched *sched,
2376 save_task_callchain(sched, sample, evsel, machine);
2377 if (sched->idle_hist) {
2395 save_idle_callchain(sched, itr, sample);
2402 static bool timehist_skip_sample(struct perf_sched *sched,
2411 sched->skipped_samples++;
2414 if (sched->idle_hist) {
2415 if (strcmp(evsel__name(evsel), "sched:sched_switch"))
2425 static void timehist_print_wakeup_event(struct perf_sched *sched,
2439 if (timehist_skip_sample(sched, thread, evsel, sample) &&
2440 timehist_skip_sample(sched, awakened, evsel, sample)) {
2446 if (sched->show_cpu_visual)
2447 printf(" %*s ", sched->max_cpu.cpu + 1, "");
2474 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
2492 if (sched->show_wakeups &&
2493 !perf_time__skip_sample(&sched->ptime, sample->time))
2494 timehist_print_wakeup_event(sched, evsel, sample, machine, thread);
2499 static void timehist_print_migration_event(struct perf_sched *sched,
2510 if (sched->summary_only)
2513 max_cpus = sched->max_cpu.cpu + 1;
2521 if (timehist_skip_sample(sched, thread, evsel, sample) &&
2522 timehist_skip_sample(sched, migrated, evsel, sample)) {
2529 if (sched->show_cpu_visual) {
2558 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
2575 timehist_print_migration_event(sched, evsel, sample, machine, thread);
2586 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
2587 struct perf_time_interval *ptime = &sched->ptime;
2603 thread = timehist_get_thread(sched, sample, machine, evsel);
2609 if (timehist_skip_sample(sched, thread, evsel, sample))
2633 * - previous sched event is out of window - we are done
2645 if (!sched->idle_hist || thread__tid(thread) == 0) {
2649 if (sched->idle_hist) {
2682 if (!sched->summary_only)
2683 timehist_print_sample(sched, evsel, sample, &al, thread, t, state);
2686 if (sched->hist_time.start == 0 && t >= ptime->start)
2687 sched->hist_time.start = t;
2689 sched->hist_time.end = t;
2698 /* sched out event for task so reset ready to run time */
2774 struct perf_sched *sched;
2794 if (stats->sched->show_state)
2857 static void timehist_print_summary(struct perf_sched *sched,
2866 u64 hist_time = sched->hist_time.end - sched->hist_time.start;
2869 totals.sched = sched;
2871 if (sched->idle_hist) {
2873 printf("%*s parent sched-out ", comm_width, "comm");
2875 } else if (sched->show_state) {
2877 printf("%*s parent sched-in ", comm_width, "comm");
2881 printf("%*s parent sched-in ", comm_width, "comm");
2886 sched->show_state ? "(msec)" : "%");
2895 if (sched->skipped_samples && !sched->idle_hist)
2917 if (sched->idle_hist && sched->show_callchain) {
2957 printf(" (x %d)\n", sched->max_cpu.cpu);
2972 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
2978 if (this_cpu.cpu > sched->max_cpu.cpu)
2979 sched->max_cpu = this_cpu;
2990 static int timehist_check_attr(struct perf_sched *sched,
3003 if (sched->show_callchain && !evsel__has_callchain(evsel)) {
3005 sched->show_callchain = 0;
3013 static int perf_sched__timehist(struct perf_sched *sched)
3016 { "sched:sched_switch", timehist_sched_switch_event, },
3017 { "sched:sched_wakeup", timehist_sched_wakeup_event, },
3018 { "sched:sched_waking", timehist_sched_wakeup_event, },
3019 { "sched:sched_wakeup_new", timehist_sched_wakeup_event, },
3022 { "sched:sched_migrate_task", timehist_migrate_task_event, },
3027 .force = sched->force,
3037 sched->tool.sample = perf_timehist__process_sample;
3038 sched->tool.mmap = perf_event__process_mmap;
3039 sched->tool.comm = perf_event__process_comm;
3040 sched->tool.exit = perf_event__process_exit;
3041 sched->tool.fork = perf_event__process_fork;
3042 sched->tool.lost = process_lost;
3043 sched->tool.attr = perf_event__process_attr;
3044 sched->tool.tracing_data = perf_event__process_tracing_data;
3045 sched->tool.build_id = perf_event__process_build_id;
3047 sched->tool.ordered_events = true;
3048 sched->tool.ordering_requires_timestamps = true;
3050 symbol_conf.use_callchain = sched->show_callchain;
3052 session = perf_session__new(&data, &sched->tool);
3066 if (perf_time__parse_str(&sched->ptime, sched->time_str) != 0) {
3071 if (timehist_check_attr(sched, evlist) != 0)
3077 if (evlist__find_tracepoint_by_name(session->evlist, "sched:sched_waking"))
3085 if (!evlist__find_tracepoint_by_name(session->evlist, "sched:sched_switch")) {
3086 pr_err("No sched_switch events found. Have you run 'perf sched record'?\n");
3090 if (sched->show_migrations &&
3095 sched->max_cpu.cpu = session->header.env.nr_cpus_online;
3096 if (sched->max_cpu.cpu == 0)
3097 sched->max_cpu.cpu = 4;
3098 if (init_idle_threads(sched->max_cpu.cpu))
3102 if (sched->summary_only)
3103 sched->summary = sched->summary_only;
3105 if (!sched->summary_only)
3106 timehist_header(sched);
3114 sched->nr_events = evlist->stats.nr_events[0];
3115 sched->nr_lost_events = evlist->stats.total_lost;
3116 sched->nr_lost_chunks = evlist->stats.nr_events[PERF_RECORD_LOST];
3118 if (sched->summary)
3119 timehist_print_summary(sched, session);
3129 static void print_bad_events(struct perf_sched *sched)
3131 if (sched->nr_unordered_timestamps && sched->nr_timestamps) {
3133 (double)sched->nr_unordered_timestamps/(double)sched->nr_timestamps*100.0,
3134 sched->nr_unordered_timestamps, sched->nr_timestamps);
3136 if (sched->nr_lost_events && sched->nr_events) {
3138 (double)sched->nr_lost_events/(double)sched->nr_events * 100.0,
3139 sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks);
3141 if (sched->nr_context_switch_bugs && sched->nr_timestamps) {
3143 (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0,
3144 sched->nr_context_switch_bugs, sched->nr_timestamps);
3145 if (sched->nr_lost_events)
3192 static void perf_sched__merge_lat(struct perf_sched *sched)
3197 if (sched->skip_merge)
3200 while ((node = rb_first_cached(&sched->atom_root))) {
3201 rb_erase_cached(node, &sched->atom_root);
3203 __merge_work_atoms(&sched->merged_atom_root, data);
3207 static int perf_sched__lat(struct perf_sched *sched)
3213 if (perf_sched__read_events(sched))
3216 perf_sched__merge_lat(sched);
3217 perf_sched__sort_lat(sched);
3223 next = rb_first_cached(&sched->sorted_atom_root);
3229 output_lat_thread(sched, work_list);
3236 (double)sched->all_runtime / NSEC_PER_MSEC, sched->all_count);
3240 print_bad_events(sched);
3246 static int setup_map_cpus(struct perf_sched *sched)
3250 sched->max_cpu.cpu = sysconf(_SC_NPROCESSORS_CONF);
3252 if (sched->map.comp) {
3253 sched->map.comp_cpus = zalloc(sched->max_cpu.cpu * sizeof(int));
3254 if (!sched->map.comp_cpus)
3258 if (!sched->map.cpus_str)
3261 map = perf_cpu_map__new(sched->map.cpus_str);
3263 pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
3267 sched->map.cpus = map;
3271 static int setup_color_pids(struct perf_sched *sched)
3275 if (!sched->map.color_pids_str)
3278 map = thread_map__new_by_tid_str(sched->map.color_pids_str);
3280 pr_err("failed to get thread map from %s\n", sched->map.color_pids_str);
3284 sched->map.color_pids = map;
3288 static int setup_color_cpus(struct perf_sched *sched)
3292 if (!sched->map.color_cpus_str)
3295 map = perf_cpu_map__new(sched->map.color_cpus_str);
3297 pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
3301 sched->map.color_cpus = map;
3305 static int perf_sched__map(struct perf_sched *sched)
3307 if (setup_map_cpus(sched))
3310 if (setup_color_pids(sched))
3313 if (setup_color_cpus(sched))
3317 if (perf_sched__read_events(sched))
3319 print_bad_events(sched);
3323 static int perf_sched__replay(struct perf_sched *sched)
3327 calibrate_run_measurement_overhead(sched);
3328 calibrate_sleep_measurement_overhead(sched);
3330 test_calibrations(sched);
3332 if (perf_sched__read_events(sched))
3335 printf("nr_run_events: %ld\n", sched->nr_run_events);
3336 printf("nr_sleep_events: %ld\n", sched->nr_sleep_events);
3337 printf("nr_wakeup_events: %ld\n", sched->nr_wakeup_events);
3339 if (sched->targetless_wakeups)
3340 printf("target-less wakeups: %ld\n", sched->targetless_wakeups);
3341 if (sched->multitarget_wakeups)
3342 printf("multi-target wakeups: %ld\n", sched->multitarget_wakeups);
3343 if (sched->nr_run_events_optimized)
3345 sched->nr_run_events_optimized);
3347 print_task_traces(sched);
3348 add_cross_task_wakeups(sched);
3350 sched->thread_funcs_exit = false;
3351 create_tasks(sched);
3353 for (i = 0; i < sched->replay_repeat; i++)
3354 run_one_test(sched);
3356 sched->thread_funcs_exit = true;
3357 destroy_tasks(sched);
3361 static void setup_sorting(struct perf_sched *sched, const struct option *options,
3364 char *tmp, *tok, *str = strdup(sched->sort_order);
3368 if (sort_dimension__add(tok, &sched->sort_list) < 0) {
3376 sort_dimension__add("pid", &sched->cmp_pid);
3382 * Select "sched:sched_stat_wait" event to check
3385 return IS_ERR(trace_event__tp_format("sched", "sched_stat_wait")) ?
3400 "-e", "sched:sched_switch",
3401 "-e", "sched:sched_stat_runtime",
3402 "-e", "sched:sched_process_fork",
3403 "-e", "sched:sched_wakeup_new",
3404 "-e", "sched:sched_migrate_task",
3410 * to prevent "perf sched record" execution failure, determine
3414 "-e", "sched:sched_stat_wait",
3415 "-e", "sched:sched_stat_sleep",
3416 "-e", "sched:sched_stat_iowait",
3425 * +2 for either "-e", "sched:sched_wakeup" or
3426 * "-e", "sched:sched_waking"
3442 waking_event = trace_event__tp_format("sched", "sched_waking");
3444 rec_argv[i++] = strdup("sched:sched_waking");
3446 rec_argv[i++] = strdup("sched:sched_wakeup");
3470 struct perf_sched sched = {
3479 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
3480 .sort_list = LIST_HEAD_INIT(sched.sort_list),
3497 OPT_BOOLEAN('f', "force", &sched.force, "don't complain, do it"),
3501 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
3503 OPT_INTEGER('C', "CPU", &sched.profile_cpu,
3505 OPT_BOOLEAN('p', "pids", &sched.skip_merge,
3510 OPT_UINTEGER('r', "repeat", &sched.replay_repeat,
3515 OPT_BOOLEAN(0, "compact", &sched.map.comp,
3517 OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids",
3519 OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus",
3521 OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus",
3530 OPT_BOOLEAN('g', "call-graph", &sched.show_callchain,
3532 OPT_UINTEGER(0, "max-stack", &sched.max_stack,
3536 OPT_BOOLEAN('s', "summary", &sched.summary_only,
3538 OPT_BOOLEAN('S', "with-summary", &sched.summary,
3540 OPT_BOOLEAN('w', "wakeups", &sched.show_wakeups, "Show wakeup events"),
3541 OPT_BOOLEAN('n', "next", &sched.show_next, "Show next task"),
3542 OPT_BOOLEAN('M', "migrations", &sched.show_migrations, "Show migration events"),
3543 OPT_BOOLEAN('V', "cpu-visual", &sched.show_cpu_visual, "Add CPU visual"),
3544 OPT_BOOLEAN('I', "idle-hist", &sched.idle_hist, "Show idle events only"),
3545 OPT_STRING(0, "time", &sched.time_str, "str",
3547 OPT_BOOLEAN(0, "state", &sched.show_state, "Show task state when sched-out"),
3557 "perf sched latency [<options>]",
3561 "perf sched replay [<options>]",
3565 "perf sched map [<options>]",
3569 "perf sched timehist [<options>]",
3596 mutex_init(&sched.start_work_mutex);
3597 mutex_init(&sched.work_done_wait_mutex);
3598 sched.curr_thread = calloc(MAX_CPUS, sizeof(*sched.curr_thread));
3599 if (!sched.curr_thread) {
3603 sched.cpu_last_switched = calloc(MAX_CPUS, sizeof(*sched.cpu_last_switched));
3604 if (!sched.cpu_last_switched) {
3608 sched.curr_pid = malloc(MAX_CPUS * sizeof(*sched.curr_pid));
3609 if (!sched.curr_pid) {
3614 sched.curr_pid[i] = -1;
3629 sched.tp_handler = &lat_ops;
3635 setup_sorting(&sched, latency_options, latency_usage);
3636 ret = perf_sched__lat(&sched);
3643 sched.tp_handler = &map_ops;
3644 setup_sorting(&sched, latency_options, latency_usage);
3645 ret = perf_sched__map(&sched);
3647 sched.tp_handler = &replay_ops;
3653 ret = perf_sched__replay(&sched);
3661 if ((sched.show_wakeups || sched.show_next) &&
3662 sched.summary_only) {
3665 if (sched.show_wakeups)
3667 if (sched.show_next)
3676 ret = perf_sched__timehist(&sched);
3682 free(sched.curr_pid);
3683 free(sched.cpu_last_switched);
3684 free(sched.curr_thread);
3685 mutex_destroy(&sched.start_work_mutex);
3686 mutex_destroy(&sched.work_done_wait_mutex);