Lines Matching full:sched
103 int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel,
106 int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel,
109 int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel,
113 int (*fork_event)(struct perf_sched *sched, union perf_event *event,
116 int (*migrate_task_event)(struct perf_sched *sched,
188 static void burn_nsecs(struct perf_sched *sched, u64 nsecs)
194 } while (T1 + sched->run_measurement_overhead < T0 + nsecs);
207 static void calibrate_run_measurement_overhead(struct perf_sched *sched)
214 burn_nsecs(sched, 0);
219 sched->run_measurement_overhead = min_delta;
224 static void calibrate_sleep_measurement_overhead(struct perf_sched *sched)
237 sched->sleep_measurement_overhead = min_delta;
270 static void add_sched_event_run(struct perf_sched *sched, struct task_desc *task,
280 sched->nr_run_events_optimized++;
290 sched->nr_run_events++;
293 static void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task,
304 sched->targetless_wakeups++;
308 sched->multitarget_wakeups++;
317 sched->nr_wakeup_events++;
320 static void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task,
327 sched->nr_sleep_events++;
330 static struct task_desc *register_pid(struct perf_sched *sched,
337 task = sched->pid_to_task[pid];
344 task->nr = sched->nr_tasks;
350 add_sched_event_sleep(sched, task, 0, 0);
352 sched->pid_to_task[pid] = task;
353 sched->nr_tasks++;
354 sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *));
355 BUG_ON(!sched->tasks);
356 sched->tasks[task->nr] = task;
359 printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm);
365 static void print_task_traces(struct perf_sched *sched)
370 for (i = 0; i < sched->nr_tasks; i++) {
371 task = sched->tasks[i];
377 static void add_cross_task_wakeups(struct perf_sched *sched)
382 for (i = 0; i < sched->nr_tasks; i++) {
383 task1 = sched->tasks[i];
385 if (j == sched->nr_tasks)
387 task2 = sched->tasks[j];
388 add_sched_event_wakeup(sched, task1, 0, task2);
392 static void perf_sched__process_event(struct perf_sched *sched,
399 burn_nsecs(sched, atom->duration);
464 struct perf_sched *sched;
472 struct perf_sched *sched = parms->sched;
488 ret = pthread_mutex_lock(&sched->start_work_mutex);
490 ret = pthread_mutex_unlock(&sched->start_work_mutex);
497 perf_sched__process_event(sched, this_task->atoms[i]);
505 ret = pthread_mutex_lock(&sched->work_done_wait_mutex);
507 ret = pthread_mutex_unlock(&sched->work_done_wait_mutex);
517 static void create_tasks(struct perf_sched *sched)
529 err = pthread_mutex_lock(&sched->start_work_mutex);
531 err = pthread_mutex_lock(&sched->work_done_wait_mutex);
533 for (i = 0; i < sched->nr_tasks; i++) {
536 parms->task = task = sched->tasks[i];
537 parms->sched = sched;
547 static void wait_for_tasks(struct perf_sched *sched)
553 sched->start_time = get_nsecs();
554 sched->cpu_usage = 0;
555 pthread_mutex_unlock(&sched->work_done_wait_mutex);
557 for (i = 0; i < sched->nr_tasks; i++) {
558 task = sched->tasks[i];
563 ret = pthread_mutex_lock(&sched->work_done_wait_mutex);
568 pthread_mutex_unlock(&sched->start_work_mutex);
570 for (i = 0; i < sched->nr_tasks; i++) {
571 task = sched->tasks[i];
575 sched->cpu_usage += task->cpu_usage;
580 if (!sched->runavg_cpu_usage)
581 sched->runavg_cpu_usage = sched->cpu_usage;
582 sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10;
584 sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0;
585 if (!sched->runavg_parent_cpu_usage)
586 sched->runavg_parent_cpu_usage = sched->parent_cpu_usage;
587 sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 +
588 sched->parent_cpu_usage)/10;
590 ret = pthread_mutex_lock(&sched->start_work_mutex);
593 for (i = 0; i < sched->nr_tasks; i++) {
594 task = sched->tasks[i];
600 static void run_one_test(struct perf_sched *sched)
605 wait_for_tasks(sched);
609 sched->sum_runtime += delta;
610 sched->nr_runs++;
612 avg_delta = sched->sum_runtime / sched->nr_runs;
617 sched->sum_fluct += fluct;
618 if (!sched->run_avg)
619 sched->run_avg = delta;
620 sched->run_avg = (sched->run_avg * 9 + delta) / 10;
622 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0);
624 printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6);
627 (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6);
632 * accurate than the sched->sum_exec_runtime based statistics:
635 (double)sched->parent_cpu_usage/1e6,
636 (double)sched->runavg_parent_cpu_usage/1e6);
641 if (sched->nr_sleep_corrections)
642 printf(" (%ld sleep corrections)\n", sched->nr_sleep_corrections);
643 sched->nr_sleep_corrections = 0;
646 static void test_calibrations(struct perf_sched *sched)
651 burn_nsecs(sched, 1e6);
664 replay_wakeup_event(struct perf_sched *sched,
678 waker = register_pid(sched, sample->tid, "<unknown>");
679 wakee = register_pid(sched, pid, comm);
681 add_sched_event_wakeup(sched, waker, sample->time, wakee);
685 static int replay_switch_event(struct perf_sched *sched,
706 timestamp0 = sched->cpu_last_switched[cpu];
720 prev = register_pid(sched, prev_pid, prev_comm);
721 next = register_pid(sched, next_pid, next_comm);
723 sched->cpu_last_switched[cpu] = timestamp;
725 add_sched_event_run(sched, prev, timestamp, delta);
726 add_sched_event_sleep(sched, prev, timestamp, prev_state);
731 static int replay_fork_event(struct perf_sched *sched,
754 register_pid(sched, parent->tid, parent->comm);
755 register_pid(sched, child->tid, child->comm);
833 static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
843 __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid);
921 static int latency_switch_event(struct perf_sched *sched,
937 timestamp0 = sched->cpu_last_switched[cpu];
938 sched->cpu_last_switched[cpu] = timestamp;
952 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
954 if (thread_atoms_insert(sched, sched_out))
956 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
965 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
967 if (thread_atoms_insert(sched, sched_in))
969 in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid);
986 static int latency_runtime_event(struct perf_sched *sched,
994 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1000 if (thread_atoms_insert(sched, thread))
1002 atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
1015 static int latency_wakeup_event(struct perf_sched *sched,
1032 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1034 if (thread_atoms_insert(sched, wakee))
1036 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1054 if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING)
1055 sched->nr_state_machine_bugs++;
1057 sched->nr_timestamps++;
1059 sched->nr_unordered_timestamps++;
1068 static int latency_migrate_task_event(struct perf_sched *sched,
1082 if (sched->profile_cpu == -1)
1086 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1088 if (thread_atoms_insert(sched, migrant))
1090 register_pid(sched, migrant->tid, migrant->comm);
1091 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1105 sched->nr_timestamps++;
1108 sched->nr_unordered_timestamps++;
1113 static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list)
1127 sched->all_runtime += work_list->total_runtime;
1128 sched->all_count += work_list->nb_atoms;
1247 static void perf_sched__sort_lat(struct perf_sched *sched)
1253 node = rb_first(&sched->atom_root);
1257 rb_erase(node, &sched->atom_root);
1259 __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list);
1268 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1270 if (sched->tp_handler->wakeup_event)
1271 return sched->tp_handler->wakeup_event(sched, evsel, sample, machine);
1276 static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1289 if (this_cpu > sched->max_cpu)
1290 sched->max_cpu = this_cpu;
1292 timestamp0 = sched->cpu_last_switched[this_cpu];
1293 sched->cpu_last_switched[this_cpu] = timestamp;
1307 sched->curr_thread[this_cpu] = sched_in;
1313 sched_in->shortname[0] = sched->next_shortname1;
1314 sched_in->shortname[1] = sched->next_shortname2;
1316 if (sched->next_shortname1 < 'Z') {
1317 sched->next_shortname1++;
1319 sched->next_shortname1='A';
1320 if (sched->next_shortname2 < '9') {
1321 sched->next_shortname2++;
1323 sched->next_shortname2='0';
1329 for (cpu = 0; cpu <= sched->max_cpu; cpu++) {
1335 if (sched->curr_thread[cpu]) {
1336 if (sched->curr_thread[cpu]->tid)
1337 printf("%2s ", sched->curr_thread[cpu]->shortname);
1360 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1365 if (sched->curr_pid[this_cpu] != (u32)-1) {
1370 if (sched->curr_pid[this_cpu] != prev_pid)
1371 sched->nr_context_switch_bugs++;
1374 if (sched->tp_handler->switch_event)
1375 err = schedsched, evsel, sample, machine);
1377 sched->curr_pid[this_cpu] = next_pid;
1386 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1388 if (sched->tp_handler->runtime_event)
1389 return sched->tp_handler->runtime_event(sched, evsel, sample, machine);
1399 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1405 if (sched->tp_handler->fork_event)
1406 return sched->tp_handler->fork_event(sched, event, machine);
1416 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1418 if (sched->tp_handler->migrate_task_event)
1419 return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine);
1448 static int perf_sched__read_events(struct perf_sched *sched,
1452 { "sched:sched_switch", process_sched_switch_event, },
1453 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1454 { "sched:sched_wakeup", process_sched_wakeup_event, },
1455 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1456 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1460 session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool);
1470 int err = perf_session__process_events(session, &sched->tool);
1476 sched->nr_events = session->stats.nr_events[0];
1477 sched->nr_lost_events = session->stats.total_lost;
1478 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST];
1493 static void print_bad_events(struct perf_sched *sched)
1495 if (sched->nr_unordered_timestamps && sched->nr_timestamps) {
1497 (double)sched->nr_unordered_timestamps/(double)sched->nr_timestamps*100.0,
1498 sched->nr_unordered_timestamps, sched->nr_timestamps);
1500 if (sched->nr_lost_events && sched->nr_events) {
1502 (double)sched->nr_lost_events/(double)sched->nr_events * 100.0,
1503 sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks);
1505 if (sched->nr_state_machine_bugs && sched->nr_timestamps) {
1507 (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0,
1508 sched->nr_state_machine_bugs, sched->nr_timestamps);
1509 if (sched->nr_lost_events)
1513 if (sched->nr_context_switch_bugs && sched->nr_timestamps) {
1515 (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0,
1516 sched->nr_context_switch_bugs, sched->nr_timestamps);
1517 if (sched->nr_lost_events)
1523 static int perf_sched__lat(struct perf_sched *sched)
1531 if (perf_sched__read_events(sched, &session))
1534 perf_sched__sort_lat(sched);
1540 next = rb_first(&sched->sorted_atom_root);
1546 output_lat_thread(sched, work_list);
1552 (double)sched->all_runtime / 1e6, sched->all_count);
1556 print_bad_events(sched);
1563 static int perf_sched__map(struct perf_sched *sched)
1565 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1568 if (perf_sched__read_events(sched, NULL))
1570 print_bad_events(sched);
1574 static int perf_sched__replay(struct perf_sched *sched)
1578 calibrate_run_measurement_overhead(sched);
1579 calibrate_sleep_measurement_overhead(sched);
1581 test_calibrations(sched);
1583 if (perf_sched__read_events(sched, NULL))
1586 printf("nr_run_events: %ld\n", sched->nr_run_events);
1587 printf("nr_sleep_events: %ld\n", sched->nr_sleep_events);
1588 printf("nr_wakeup_events: %ld\n", sched->nr_wakeup_events);
1590 if (sched->targetless_wakeups)
1591 printf("target-less wakeups: %ld\n", sched->targetless_wakeups);
1592 if (sched->multitarget_wakeups)
1593 printf("multi-target wakeups: %ld\n", sched->multitarget_wakeups);
1594 if (sched->nr_run_events_optimized)
1596 sched->nr_run_events_optimized);
1598 print_task_traces(sched);
1599 add_cross_task_wakeups(sched);
1601 create_tasks(sched);
1603 for (i = 0; i < sched->replay_repeat; i++)
1604 run_one_test(sched);
1609 static void setup_sorting(struct perf_sched *sched, const struct option *options,
1612 char *tmp, *tok, *str = strdup(sched->sort_order);
1616 if (sort_dimension__add(tok, &sched->sort_list) < 0) {
1624 sort_dimension__add("pid", &sched->cmp_pid);
1637 "-e", "sched:sched_switch",
1638 "-e", "sched:sched_stat_wait",
1639 "-e", "sched:sched_stat_sleep",
1640 "-e", "sched:sched_stat_iowait",
1641 "-e", "sched:sched_stat_runtime",
1642 "-e", "sched:sched_process_fork",
1643 "-e", "sched:sched_wakeup",
1644 "-e", "sched:sched_migrate_task",
1665 static struct perf_sched sched = {
1673 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1674 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1688 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
1692 OPT_INTEGER('C', "CPU", &sched.profile_cpu,
1699 OPT_UINTEGER('r', "repeat", &sched.replay_repeat,
1717 "perf sched latency [<options>]",
1721 "perf sched replay [<options>]",
1725 "perf sched [<options>] {record|latency|map|replay|script}",
1758 sched.tp_handler = &lat_ops;
1764 setup_sorting(&sched, latency_options, latency_usage);
1765 return perf_sched__lat(&sched);
1767 sched.tp_handler = &map_ops;
1768 setup_sorting(&sched, latency_options, latency_usage);
1769 return perf_sched__map(&sched);
1771 sched.tp_handler = &replay_ops;
1777 return perf_sched__replay(&sched);