aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-sched.c')
-rw-r--r--tools/perf/builtin-sched.c161
1 files changed, 75 insertions, 86 deletions
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index fed9ae432c16..d8c51b2f263f 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -109,8 +109,9 @@ struct trace_sched_handler {
109 int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, 109 int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel,
110 struct perf_sample *sample, struct machine *machine); 110 struct perf_sample *sample, struct machine *machine);
111 111
112 int (*fork_event)(struct perf_sched *sched, struct perf_evsel *evsel, 112 /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */
113 struct perf_sample *sample); 113 int (*fork_event)(struct perf_sched *sched, union perf_event *event,
114 struct machine *machine);
114 115
115 int (*migrate_task_event)(struct perf_sched *sched, 116 int (*migrate_task_event)(struct perf_sched *sched,
116 struct perf_evsel *evsel, 117 struct perf_evsel *evsel,
@@ -717,22 +718,31 @@ static int replay_switch_event(struct perf_sched *sched,
717 return 0; 718 return 0;
718} 719}
719 720
720static int replay_fork_event(struct perf_sched *sched, struct perf_evsel *evsel, 721static int replay_fork_event(struct perf_sched *sched,
721 struct perf_sample *sample) 722 union perf_event *event,
723 struct machine *machine)
722{ 724{
723 const char *parent_comm = perf_evsel__strval(evsel, sample, "parent_comm"), 725 struct thread *child, *parent;
724 *child_comm = perf_evsel__strval(evsel, sample, "child_comm"); 726
725 const u32 parent_pid = perf_evsel__intval(evsel, sample, "parent_pid"), 727 child = machine__findnew_thread(machine, event->fork.pid,
726 child_pid = perf_evsel__intval(evsel, sample, "child_pid"); 728 event->fork.tid);
729 parent = machine__findnew_thread(machine, event->fork.ppid,
730 event->fork.ptid);
731
732 if (child == NULL || parent == NULL) {
733 pr_debug("thread does not exist on fork event: child %p, parent %p\n",
734 child, parent);
735 return 0;
736 }
727 737
728 if (verbose) { 738 if (verbose) {
729 printf("sched_fork event %p\n", evsel); 739 printf("fork event\n");
730 printf("... parent: %s/%d\n", parent_comm, parent_pid); 740 printf("... parent: %s/%d\n", parent->comm, parent->tid);
731 printf("... child: %s/%d\n", child_comm, child_pid); 741 printf("... child: %s/%d\n", child->comm, child->tid);
732 } 742 }
733 743
734 register_pid(sched, parent_pid, parent_comm); 744 register_pid(sched, parent->tid, parent->comm);
735 register_pid(sched, child_pid, child_comm); 745 register_pid(sched, child->tid, child->comm);
736 return 0; 746 return 0;
737} 747}
738 748
@@ -824,14 +834,6 @@ static int thread_atoms_insert(struct perf_sched *sched, struct thread *thread)
824 return 0; 834 return 0;
825} 835}
826 836
827static int latency_fork_event(struct perf_sched *sched __maybe_unused,
828 struct perf_evsel *evsel __maybe_unused,
829 struct perf_sample *sample __maybe_unused)
830{
831 /* should insert the newcomer */
832 return 0;
833}
834
835static char sched_out_state(u64 prev_state) 837static char sched_out_state(u64 prev_state)
836{ 838{
837 const char *str = TASK_STATE_TO_CHAR_STR; 839 const char *str = TASK_STATE_TO_CHAR_STR;
@@ -934,8 +936,8 @@ static int latency_switch_event(struct perf_sched *sched,
934 return -1; 936 return -1;
935 } 937 }
936 938
937 sched_out = machine__findnew_thread(machine, prev_pid); 939 sched_out = machine__findnew_thread(machine, 0, prev_pid);
938 sched_in = machine__findnew_thread(machine, next_pid); 940 sched_in = machine__findnew_thread(machine, 0, next_pid);
939 941
940 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 942 out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
941 if (!out_events) { 943 if (!out_events) {
@@ -978,7 +980,7 @@ static int latency_runtime_event(struct perf_sched *sched,
978{ 980{
979 const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 981 const u32 pid = perf_evsel__intval(evsel, sample, "pid");
980 const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 982 const u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
981 struct thread *thread = machine__findnew_thread(machine, pid); 983 struct thread *thread = machine__findnew_thread(machine, 0, pid);
982 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 984 struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
983 u64 timestamp = sample->time; 985 u64 timestamp = sample->time;
984 int cpu = sample->cpu; 986 int cpu = sample->cpu;
@@ -1016,7 +1018,7 @@ static int latency_wakeup_event(struct perf_sched *sched,
1016 if (!success) 1018 if (!success)
1017 return 0; 1019 return 0;
1018 1020
1019 wakee = machine__findnew_thread(machine, pid); 1021 wakee = machine__findnew_thread(machine, 0, pid);
1020 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1022 atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
1021 if (!atoms) { 1023 if (!atoms) {
1022 if (thread_atoms_insert(sched, wakee)) 1024 if (thread_atoms_insert(sched, wakee))
@@ -1070,12 +1072,12 @@ static int latency_migrate_task_event(struct perf_sched *sched,
1070 if (sched->profile_cpu == -1) 1072 if (sched->profile_cpu == -1)
1071 return 0; 1073 return 0;
1072 1074
1073 migrant = machine__findnew_thread(machine, pid); 1075 migrant = machine__findnew_thread(machine, 0, pid);
1074 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1076 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1075 if (!atoms) { 1077 if (!atoms) {
1076 if (thread_atoms_insert(sched, migrant)) 1078 if (thread_atoms_insert(sched, migrant))
1077 return -1; 1079 return -1;
1078 register_pid(sched, migrant->pid, migrant->comm); 1080 register_pid(sched, migrant->tid, migrant->comm);
1079 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1081 atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
1080 if (!atoms) { 1082 if (!atoms) {
1081 pr_err("migration-event: Internal tree error"); 1083 pr_err("migration-event: Internal tree error");
@@ -1115,7 +1117,7 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1115 sched->all_runtime += work_list->total_runtime; 1117 sched->all_runtime += work_list->total_runtime;
1116 sched->all_count += work_list->nb_atoms; 1118 sched->all_count += work_list->nb_atoms;
1117 1119
1118 ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->pid); 1120 ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->tid);
1119 1121
1120 for (i = 0; i < 24 - ret; i++) 1122 for (i = 0; i < 24 - ret; i++)
1121 printf(" "); 1123 printf(" ");
@@ -1131,9 +1133,9 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1131 1133
1132static int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1134static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
1133{ 1135{
1134 if (l->thread->pid < r->thread->pid) 1136 if (l->thread->tid < r->thread->tid)
1135 return -1; 1137 return -1;
1136 if (l->thread->pid > r->thread->pid) 1138 if (l->thread->tid > r->thread->tid)
1137 return 1; 1139 return 1;
1138 1140
1139 return 0; 1141 return 0;
@@ -1289,8 +1291,8 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1289 return -1; 1291 return -1;
1290 } 1292 }
1291 1293
1292 sched_out = machine__findnew_thread(machine, prev_pid); 1294 sched_out = machine__findnew_thread(machine, 0, prev_pid);
1293 sched_in = machine__findnew_thread(machine, next_pid); 1295 sched_in = machine__findnew_thread(machine, 0, next_pid);
1294 1296
1295 sched->curr_thread[this_cpu] = sched_in; 1297 sched->curr_thread[this_cpu] = sched_in;
1296 1298
@@ -1321,7 +1323,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1321 printf("*"); 1323 printf("*");
1322 1324
1323 if (sched->curr_thread[cpu]) { 1325 if (sched->curr_thread[cpu]) {
1324 if (sched->curr_thread[cpu]->pid) 1326 if (sched->curr_thread[cpu]->tid)
1325 printf("%2s ", sched->curr_thread[cpu]->shortname); 1327 printf("%2s ", sched->curr_thread[cpu]->shortname);
1326 else 1328 else
1327 printf(". "); 1329 printf(". ");
@@ -1332,7 +1334,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1332 printf(" %12.6f secs ", (double)timestamp/1e9); 1334 printf(" %12.6f secs ", (double)timestamp/1e9);
1333 if (new_shortname) { 1335 if (new_shortname) {
1334 printf("%s => %s:%d\n", 1336 printf("%s => %s:%d\n",
1335 sched_in->shortname, sched_in->comm, sched_in->pid); 1337 sched_in->shortname, sched_in->comm, sched_in->tid);
1336 } else { 1338 } else {
1337 printf("\n"); 1339 printf("\n");
1338 } 1340 }
@@ -1379,25 +1381,20 @@ static int process_sched_runtime_event(struct perf_tool *tool,
1379 return 0; 1381 return 0;
1380} 1382}
1381 1383
1382static int process_sched_fork_event(struct perf_tool *tool, 1384static int perf_sched__process_fork_event(struct perf_tool *tool,
1383 struct perf_evsel *evsel, 1385 union perf_event *event,
1384 struct perf_sample *sample, 1386 struct perf_sample *sample,
1385 struct machine *machine __maybe_unused) 1387 struct machine *machine)
1386{ 1388{
1387 struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1389 struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
1388 1390
1389 if (sched->tp_handler->fork_event) 1391 /* run the fork event through the perf machineruy */
1390 return sched->tp_handler->fork_event(sched, evsel, sample); 1392 perf_event__process_fork(tool, event, sample, machine);
1391 1393
1392 return 0; 1394 /* and then run additional processing needed for this command */
1393} 1395 if (sched->tp_handler->fork_event)
1396 return sched->tp_handler->fork_event(sched, event, machine);
1394 1397
1395static int process_sched_exit_event(struct perf_tool *tool __maybe_unused,
1396 struct perf_evsel *evsel,
1397 struct perf_sample *sample __maybe_unused,
1398 struct machine *machine __maybe_unused)
1399{
1400 pr_debug("sched_exit event %p\n", evsel);
1401 return 0; 1398 return 0;
1402} 1399}
1403 1400
@@ -1425,15 +1422,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1425 struct perf_evsel *evsel, 1422 struct perf_evsel *evsel,
1426 struct machine *machine) 1423 struct machine *machine)
1427{ 1424{
1428 struct thread *thread = machine__findnew_thread(machine, sample->tid);
1429 int err = 0; 1425 int err = 0;
1430 1426
1431 if (thread == NULL) {
1432 pr_debug("problem processing %s event, skipping it.\n",
1433 perf_evsel__name(evsel));
1434 return -1;
1435 }
1436
1437 evsel->hists.stats.total_period += sample->period; 1427 evsel->hists.stats.total_period += sample->period;
1438 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 1428 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
1439 1429
@@ -1445,7 +1435,7 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
1445 return err; 1435 return err;
1446} 1436}
1447 1437
1448static int perf_sched__read_events(struct perf_sched *sched, bool destroy, 1438static int perf_sched__read_events(struct perf_sched *sched,
1449 struct perf_session **psession) 1439 struct perf_session **psession)
1450{ 1440{
1451 const struct perf_evsel_str_handler handlers[] = { 1441 const struct perf_evsel_str_handler handlers[] = {
@@ -1453,8 +1443,6 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1453 { "sched:sched_stat_runtime", process_sched_runtime_event, }, 1443 { "sched:sched_stat_runtime", process_sched_runtime_event, },
1454 { "sched:sched_wakeup", process_sched_wakeup_event, }, 1444 { "sched:sched_wakeup", process_sched_wakeup_event, },
1455 { "sched:sched_wakeup_new", process_sched_wakeup_event, }, 1445 { "sched:sched_wakeup_new", process_sched_wakeup_event, },
1456 { "sched:sched_process_fork", process_sched_fork_event, },
1457 { "sched:sched_process_exit", process_sched_exit_event, },
1458 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1446 { "sched:sched_migrate_task", process_sched_migrate_task_event, },
1459 }; 1447 };
1460 struct perf_session *session; 1448 struct perf_session *session;
@@ -1480,11 +1468,10 @@ static int perf_sched__read_events(struct perf_sched *sched, bool destroy,
1480 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1468 sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST];
1481 } 1469 }
1482 1470
1483 if (destroy)
1484 perf_session__delete(session);
1485
1486 if (psession) 1471 if (psession)
1487 *psession = session; 1472 *psession = session;
1473 else
1474 perf_session__delete(session);
1488 1475
1489 return 0; 1476 return 0;
1490 1477
@@ -1529,8 +1516,11 @@ static int perf_sched__lat(struct perf_sched *sched)
1529 struct perf_session *session; 1516 struct perf_session *session;
1530 1517
1531 setup_pager(); 1518 setup_pager();
1532 if (perf_sched__read_events(sched, false, &session)) 1519
1520 /* save session -- references to threads are held in work_list */
1521 if (perf_sched__read_events(sched, &session))
1533 return -1; 1522 return -1;
1523
1534 perf_sched__sort_lat(sched); 1524 perf_sched__sort_lat(sched);
1535 1525
1536 printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1526 printf("\n ---------------------------------------------------------------------------------------------------------------\n");
@@ -1565,7 +1555,7 @@ static int perf_sched__map(struct perf_sched *sched)
1565 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1555 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1566 1556
1567 setup_pager(); 1557 setup_pager();
1568 if (perf_sched__read_events(sched, true, NULL)) 1558 if (perf_sched__read_events(sched, NULL))
1569 return -1; 1559 return -1;
1570 print_bad_events(sched); 1560 print_bad_events(sched);
1571 return 0; 1561 return 0;
@@ -1580,7 +1570,7 @@ static int perf_sched__replay(struct perf_sched *sched)
1580 1570
1581 test_calibrations(sched); 1571 test_calibrations(sched);
1582 1572
1583 if (perf_sched__read_events(sched, true, NULL)) 1573 if (perf_sched__read_events(sched, NULL))
1584 return -1; 1574 return -1;
1585 1575
1586 printf("nr_run_events: %ld\n", sched->nr_run_events); 1576 printf("nr_run_events: %ld\n", sched->nr_run_events);
@@ -1639,7 +1629,6 @@ static int __cmd_record(int argc, const char **argv)
1639 "-e", "sched:sched_stat_sleep", 1629 "-e", "sched:sched_stat_sleep",
1640 "-e", "sched:sched_stat_iowait", 1630 "-e", "sched:sched_stat_iowait",
1641 "-e", "sched:sched_stat_runtime", 1631 "-e", "sched:sched_stat_runtime",
1642 "-e", "sched:sched_process_exit",
1643 "-e", "sched:sched_process_fork", 1632 "-e", "sched:sched_process_fork",
1644 "-e", "sched:sched_wakeup", 1633 "-e", "sched:sched_wakeup",
1645 "-e", "sched:sched_migrate_task", 1634 "-e", "sched:sched_migrate_task",
@@ -1662,28 +1651,29 @@ static int __cmd_record(int argc, const char **argv)
1662 return cmd_record(i, rec_argv, NULL); 1651 return cmd_record(i, rec_argv, NULL);
1663} 1652}
1664 1653
1654static const char default_sort_order[] = "avg, max, switch, runtime";
1655static struct perf_sched sched = {
1656 .tool = {
1657 .sample = perf_sched__process_tracepoint_sample,
1658 .comm = perf_event__process_comm,
1659 .lost = perf_event__process_lost,
1660 .fork = perf_sched__process_fork_event,
1661 .ordered_samples = true,
1662 },
1663 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1664 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1665 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1666 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1667 .curr_pid = { [0 ... MAX_CPUS - 1] = -1 },
1668 .sort_order = default_sort_order,
1669 .replay_repeat = 10,
1670 .profile_cpu = -1,
1671 .next_shortname1 = 'A',
1672 .next_shortname2 = '0',
1673};
1674
1665int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 1675int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1666{ 1676{
1667 const char default_sort_order[] = "avg, max, switch, runtime";
1668 struct perf_sched sched = {
1669 .tool = {
1670 .sample = perf_sched__process_tracepoint_sample,
1671 .comm = perf_event__process_comm,
1672 .lost = perf_event__process_lost,
1673 .fork = perf_event__process_fork,
1674 .ordered_samples = true,
1675 },
1676 .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
1677 .sort_list = LIST_HEAD_INIT(sched.sort_list),
1678 .start_work_mutex = PTHREAD_MUTEX_INITIALIZER,
1679 .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER,
1680 .curr_pid = { [0 ... MAX_CPUS - 1] = -1 },
1681 .sort_order = default_sort_order,
1682 .replay_repeat = 10,
1683 .profile_cpu = -1,
1684 .next_shortname1 = 'A',
1685 .next_shortname2 = '0',
1686 };
1687 const struct option latency_options[] = { 1677 const struct option latency_options[] = {
1688 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1678 OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]",
1689 "sort by key(s): runtime, switch, avg, max"), 1679 "sort by key(s): runtime, switch, avg, max"),
@@ -1729,7 +1719,6 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1729 .wakeup_event = latency_wakeup_event, 1719 .wakeup_event = latency_wakeup_event,
1730 .switch_event = latency_switch_event, 1720 .switch_event = latency_switch_event,
1731 .runtime_event = latency_runtime_event, 1721 .runtime_event = latency_runtime_event,
1732 .fork_event = latency_fork_event,
1733 .migrate_task_event = latency_migrate_task_event, 1722 .migrate_task_event = latency_migrate_task_event,
1734 }; 1723 };
1735 struct trace_sched_handler map_ops = { 1724 struct trace_sched_handler map_ops = {