builtin-sched.c (e4da3fbfbd1de56d2367653e3823e6445e49f8a9) | builtin-sched.c (efad14150a0b4429f37da7245001a8096ef7ee38) |
---|---|
1#include "builtin.h" 2#include "perf.h" 3 4#include "util/util.h" | 1#include "builtin.h" 2#include "perf.h" 3 4#include "util/util.h" |
5#include "util/evlist.h" |
|
5#include "util/cache.h" | 6#include "util/cache.h" |
7#include "util/evsel.h" |
|
6#include "util/symbol.h" 7#include "util/thread.h" 8#include "util/header.h" 9#include "util/session.h" | 8#include "util/symbol.h" 9#include "util/thread.h" 10#include "util/header.h" 11#include "util/session.h" |
12#include "util/tool.h" |
|
10 11#include "util/parse-options.h" 12#include "util/trace-event.h" 13 14#include "util/debug.h" 15 16#include <sys/prctl.h> 17 18#include <semaphore.h> 19#include <pthread.h> 20#include <math.h> 21 | 13 14#include "util/parse-options.h" 15#include "util/trace-event.h" 16 17#include "util/debug.h" 18 19#include <sys/prctl.h> 20 21#include <semaphore.h> 22#include <pthread.h> 23#include <math.h> 24 |
22static char const *input_name = "perf.data"; | 25static const char *input_name; |
23 24static char default_sort_order[] = "avg, max, switch, runtime"; 25static const char *sort_order = default_sort_order; 26 27static int profile_cpu = -1; 28 29#define PR_SET_NAME 15 /* Set process name */ 30#define MAX_CPUS 4096 --- 687 unchanged lines hidden (view full) --- 718 u32 pid; 719 720 u32 prio; 721 u32 cpu; 722}; 723 724struct trace_sched_handler { 725 void (*switch_event)(struct trace_switch_event *, | 26 27static char default_sort_order[] = "avg, max, switch, runtime"; 28static const char *sort_order = default_sort_order; 29 30static int profile_cpu = -1; 31 32#define PR_SET_NAME 15 /* Set process name */ 33#define MAX_CPUS 4096 --- 687 unchanged lines hidden (view full) --- 721 u32 pid; 722 723 u32 prio; 724 u32 cpu; 725}; 726 727struct trace_sched_handler { 728 void (*switch_event)(struct trace_switch_event *, |
726 struct perf_session *, | 729 struct machine *, |
727 struct event *, 728 int cpu, 729 u64 timestamp, 730 struct thread *thread); 731 732 void (*runtime_event)(struct trace_runtime_event *, | 730 struct event *, 731 int cpu, 732 u64 timestamp, 733 struct thread *thread); 734 735 void (*runtime_event)(struct trace_runtime_event *, |
733 struct perf_session *, | 736 struct machine *, |
734 struct event *, 735 int cpu, 736 u64 timestamp, 737 struct thread *thread); 738 739 void (*wakeup_event)(struct trace_wakeup_event *, | 737 struct event *, 738 int cpu, 739 u64 timestamp, 740 struct thread *thread); 741 742 void (*wakeup_event)(struct trace_wakeup_event *, |
740 struct perf_session *, | 743 struct machine *, |
741 struct event *, 742 int cpu, 743 u64 timestamp, 744 struct thread *thread); 745 746 void (*fork_event)(struct trace_fork_event *, 747 struct event *, 748 int cpu, 749 u64 timestamp, 750 struct thread *thread); 751 752 void (*migrate_task_event)(struct trace_migrate_task_event *, | 744 struct event *, 745 int cpu, 746 u64 timestamp, 747 struct thread *thread); 748 749 void (*fork_event)(struct trace_fork_event *, 750 struct event *, 751 int cpu, 752 u64 timestamp, 753 struct thread *thread); 754 755 void (*migrate_task_event)(struct trace_migrate_task_event *, |
753 struct perf_session *session, | 756 struct machine *machine, |
754 struct event *, 755 int cpu, 756 u64 timestamp, 757 struct thread *thread); 758}; 759 760 761static void 762replay_wakeup_event(struct trace_wakeup_event *wakeup_event, | 757 struct event *, 758 int cpu, 759 u64 timestamp, 760 struct thread *thread); 761}; 762 763 764static void 765replay_wakeup_event(struct trace_wakeup_event *wakeup_event, |
763 struct perf_session *session __used, | 766 struct machine *machine __used, |
764 struct event *event, 765 int cpu __used, 766 u64 timestamp __used, 767 struct thread *thread __used) 768{ 769 struct task_desc *waker, *wakee; 770 771 if (verbose) { --- 10 unchanged lines hidden (view full) --- 782 783 add_sched_event_wakeup(waker, timestamp, wakee); 784} 785 786static u64 cpu_last_switched[MAX_CPUS]; 787 788static void 789replay_switch_event(struct trace_switch_event *switch_event, | 767 struct event *event, 768 int cpu __used, 769 u64 timestamp __used, 770 struct thread *thread __used) 771{ 772 struct task_desc *waker, *wakee; 773 774 if (verbose) { --- 10 unchanged lines hidden (view full) --- 785 786 add_sched_event_wakeup(waker, timestamp, wakee); 787} 788 789static u64 cpu_last_switched[MAX_CPUS]; 790 791static void 792replay_switch_event(struct trace_switch_event *switch_event, |
790 struct perf_session *session __used, | 793 struct machine *machine __used, |
791 struct event *event, 792 int cpu, 793 u64 timestamp, 794 struct thread *thread __used) 795{ 796 struct task_desc *prev, __used *next; 797 u64 timestamp0; 798 s64 delta; --- 217 unchanged lines hidden (view full) --- 1016 atoms->max_lat = delta; 1017 atoms->max_lat_at = timestamp; 1018 } 1019 atoms->nb_atoms++; 1020} 1021 1022static void 1023latency_switch_event(struct trace_switch_event *switch_event, | 794 struct event *event, 795 int cpu, 796 u64 timestamp, 797 struct thread *thread __used) 798{ 799 struct task_desc *prev, __used *next; 800 u64 timestamp0; 801 s64 delta; --- 217 unchanged lines hidden (view full) --- 1019 atoms->max_lat = delta; 1020 atoms->max_lat_at = timestamp; 1021 } 1022 atoms->nb_atoms++; 1023} 1024 1025static void 1026latency_switch_event(struct trace_switch_event *switch_event, |
1024 struct perf_session *session, | 1027 struct machine *machine, |
1025 struct event *event __used, 1026 int cpu, 1027 u64 timestamp, 1028 struct thread *thread __used) 1029{ 1030 struct work_atoms *out_events, *in_events; 1031 struct thread *sched_out, *sched_in; 1032 u64 timestamp0; --- 7 unchanged lines hidden (view full) --- 1040 delta = timestamp - timestamp0; 1041 else 1042 delta = 0; 1043 1044 if (delta < 0) 1045 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1046 1047 | 1028 struct event *event __used, 1029 int cpu, 1030 u64 timestamp, 1031 struct thread *thread __used) 1032{ 1033 struct work_atoms *out_events, *in_events; 1034 struct thread *sched_out, *sched_in; 1035 u64 timestamp0; --- 7 unchanged lines hidden (view full) --- 1043 delta = timestamp - timestamp0; 1044 else 1045 delta = 0; 1046 1047 if (delta < 0) 1048 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1049 1050 |
1048 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1049 sched_in = perf_session__findnew(session, switch_event->next_pid); | 1051 sched_out = machine__findnew_thread(machine, switch_event->prev_pid); 1052 sched_in = machine__findnew_thread(machine, switch_event->next_pid); |
1050 1051 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1052 if (!out_events) { 1053 thread_atoms_insert(sched_out); 1054 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1055 if (!out_events) 1056 die("out-event: Internal tree error"); 1057 } --- 11 unchanged lines hidden (view full) --- 1069 */ 1070 add_sched_out_event(in_events, 'R', timestamp); 1071 } 1072 add_sched_in_event(in_events, timestamp); 1073} 1074 1075static void 1076latency_runtime_event(struct trace_runtime_event *runtime_event, | 1053 1054 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1055 if (!out_events) { 1056 thread_atoms_insert(sched_out); 1057 out_events = thread_atoms_search(&atom_root, sched_out, &cmp_pid); 1058 if (!out_events) 1059 die("out-event: Internal tree error"); 1060 } --- 11 unchanged lines hidden (view full) --- 1072 */ 1073 add_sched_out_event(in_events, 'R', timestamp); 1074 } 1075 add_sched_in_event(in_events, timestamp); 1076} 1077 1078static void 1079latency_runtime_event(struct trace_runtime_event *runtime_event, |
1077 struct perf_session *session, | 1080 struct machine *machine, |
1078 struct event *event __used, 1079 int cpu, 1080 u64 timestamp, 1081 struct thread *this_thread __used) 1082{ | 1081 struct event *event __used, 1082 int cpu, 1083 u64 timestamp, 1084 struct thread *this_thread __used) 1085{ |
1083 struct thread *thread = perf_session__findnew(session, runtime_event->pid); | 1086 struct thread *thread = machine__findnew_thread(machine, runtime_event->pid); |
1084 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1085 1086 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1087 if (!atoms) { 1088 thread_atoms_insert(thread); 1089 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1090 if (!atoms) 1091 die("in-event: Internal tree error"); 1092 add_sched_out_event(atoms, 'R', timestamp); 1093 } 1094 1095 add_runtime_event(atoms, runtime_event->runtime, timestamp); 1096} 1097 1098static void 1099latency_wakeup_event(struct trace_wakeup_event *wakeup_event, | 1087 struct work_atoms *atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1088 1089 BUG_ON(cpu >= MAX_CPUS || cpu < 0); 1090 if (!atoms) { 1091 thread_atoms_insert(thread); 1092 atoms = thread_atoms_search(&atom_root, thread, &cmp_pid); 1093 if (!atoms) 1094 die("in-event: Internal tree error"); 1095 add_sched_out_event(atoms, 'R', timestamp); 1096 } 1097 1098 add_runtime_event(atoms, runtime_event->runtime, timestamp); 1099} 1100 1101static void 1102latency_wakeup_event(struct trace_wakeup_event *wakeup_event, |
1100 struct perf_session *session, | 1103 struct machine *machine, |
1101 struct event *__event __used, 1102 int cpu __used, 1103 u64 timestamp, 1104 struct thread *thread __used) 1105{ 1106 struct work_atoms *atoms; 1107 struct work_atom *atom; 1108 struct thread *wakee; 1109 1110 /* Note for later, it may be interesting to observe the failing cases */ 1111 if (!wakeup_event->success) 1112 return; 1113 | 1104 struct event *__event __used, 1105 int cpu __used, 1106 u64 timestamp, 1107 struct thread *thread __used) 1108{ 1109 struct work_atoms *atoms; 1110 struct work_atom *atom; 1111 struct thread *wakee; 1112 1113 /* Note for later, it may be interesting to observe the failing cases */ 1114 if (!wakeup_event->success) 1115 return; 1116 |
1114 wakee = perf_session__findnew(session, wakeup_event->pid); | 1117 wakee = machine__findnew_thread(machine, wakeup_event->pid); |
1115 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1116 if (!atoms) { 1117 thread_atoms_insert(wakee); 1118 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1119 if (!atoms) 1120 die("wakeup-event: Internal tree error"); 1121 add_sched_out_event(atoms, 'S', timestamp); 1122 } --- 17 unchanged lines hidden (view full) --- 1140 } 1141 1142 atom->state = THREAD_WAIT_CPU; 1143 atom->wake_up_time = timestamp; 1144} 1145 1146static void 1147latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, | 1118 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1119 if (!atoms) { 1120 thread_atoms_insert(wakee); 1121 atoms = thread_atoms_search(&atom_root, wakee, &cmp_pid); 1122 if (!atoms) 1123 die("wakeup-event: Internal tree error"); 1124 add_sched_out_event(atoms, 'S', timestamp); 1125 } --- 17 unchanged lines hidden (view full) --- 1143 } 1144 1145 atom->state = THREAD_WAIT_CPU; 1146 atom->wake_up_time = timestamp; 1147} 1148 1149static void 1150latency_migrate_task_event(struct trace_migrate_task_event *migrate_task_event, |
1148 struct perf_session *session, | 1151 struct machine *machine, |
1149 struct event *__event __used, 1150 int cpu __used, 1151 u64 timestamp, 1152 struct thread *thread __used) 1153{ 1154 struct work_atoms *atoms; 1155 struct work_atom *atom; 1156 struct thread *migrant; 1157 1158 /* 1159 * Only need to worry about migration when profiling one CPU. 1160 */ 1161 if (profile_cpu == -1) 1162 return; 1163 | 1152 struct event *__event __used, 1153 int cpu __used, 1154 u64 timestamp, 1155 struct thread *thread __used) 1156{ 1157 struct work_atoms *atoms; 1158 struct work_atom *atom; 1159 struct thread *migrant; 1160 1161 /* 1162 * Only need to worry about migration when profiling one CPU. 1163 */ 1164 if (profile_cpu == -1) 1165 return; 1166 |
1164 migrant = perf_session__findnew(session, migrate_task_event->pid); | 1167 migrant = machine__findnew_thread(machine, migrate_task_event->pid); |
1165 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1166 if (!atoms) { 1167 thread_atoms_insert(migrant); 1168 register_pid(migrant->pid, migrant->comm); 1169 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1170 if (!atoms) 1171 die("migration-event: Internal tree error"); 1172 add_sched_out_event(atoms, 'R', timestamp); --- 178 unchanged lines hidden (view full) --- 1351 data = rb_entry(node, struct work_atoms, node); 1352 __thread_latency_insert(&sorted_atom_root, data, &sort_list); 1353 } 1354} 1355 1356static struct trace_sched_handler *trace_handler; 1357 1358static void | 1168 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1169 if (!atoms) { 1170 thread_atoms_insert(migrant); 1171 register_pid(migrant->pid, migrant->comm); 1172 atoms = thread_atoms_search(&atom_root, migrant, &cmp_pid); 1173 if (!atoms) 1174 die("migration-event: Internal tree error"); 1175 add_sched_out_event(atoms, 'R', timestamp); --- 178 unchanged lines hidden (view full) --- 1354 data = rb_entry(node, struct work_atoms, node); 1355 __thread_latency_insert(&sorted_atom_root, data, &sort_list); 1356 } 1357} 1358 1359static struct trace_sched_handler *trace_handler; 1360 1361static void |
1359process_sched_wakeup_event(void *data, struct perf_session *session, | 1362process_sched_wakeup_event(struct perf_tool *tool __used, |
1360 struct event *event, | 1363 struct event *event, |
1361 int cpu __used, 1362 u64 timestamp __used, 1363 struct thread *thread __used) | 1364 struct perf_sample *sample, 1365 struct machine *machine, 1366 struct thread *thread) |
1364{ | 1367{ |
1368 void *data = sample->raw_data; |
|
1365 struct trace_wakeup_event wakeup_event; 1366 1367 FILL_COMMON_FIELDS(wakeup_event, event, data); 1368 1369 FILL_ARRAY(wakeup_event, comm, event, data); 1370 FILL_FIELD(wakeup_event, pid, event, data); 1371 FILL_FIELD(wakeup_event, prio, event, data); 1372 FILL_FIELD(wakeup_event, success, event, data); 1373 FILL_FIELD(wakeup_event, cpu, event, data); 1374 1375 if (trace_handler->wakeup_event) | 1369 struct trace_wakeup_event wakeup_event; 1370 1371 FILL_COMMON_FIELDS(wakeup_event, event, data); 1372 1373 FILL_ARRAY(wakeup_event, comm, event, data); 1374 FILL_FIELD(wakeup_event, pid, event, data); 1375 FILL_FIELD(wakeup_event, prio, event, data); 1376 FILL_FIELD(wakeup_event, success, event, data); 1377 FILL_FIELD(wakeup_event, cpu, event, data); 1378 1379 if (trace_handler->wakeup_event) |
1376 trace_handler->wakeup_event(&wakeup_event, session, event, 1377 cpu, timestamp, thread); | 1380 trace_handler->wakeup_event(&wakeup_event, machine, event, 1381 sample->cpu, sample->time, thread); |
1378} 1379 1380/* 1381 * Track the current task - that way we can know whether there's any 1382 * weird events, such as a task being switched away that is not current. 1383 */ 1384static int max_cpu; 1385 1386static u32 curr_pid[MAX_CPUS] = { [0 ... MAX_CPUS-1] = -1 }; 1387 1388static struct thread *curr_thread[MAX_CPUS]; 1389 1390static char next_shortname1 = 'A'; 1391static char next_shortname2 = '0'; 1392 1393static void 1394map_switch_event(struct trace_switch_event *switch_event, | 1382} 1383 1384/* 1385 * Track the current task - that way we can know whether there's any 1386 * weird events, such as a task being switched away that is not current. 1387 */ 1388static int max_cpu; 1389 1390static u32 curr_pid[MAX_CPUS] = { [0 ... MAX_CPUS-1] = -1 }; 1391 1392static struct thread *curr_thread[MAX_CPUS]; 1393 1394static char next_shortname1 = 'A'; 1395static char next_shortname2 = '0'; 1396 1397static void 1398map_switch_event(struct trace_switch_event *switch_event, |
1395 struct perf_session *session, | 1399 struct machine *machine, |
1396 struct event *event __used, 1397 int this_cpu, 1398 u64 timestamp, 1399 struct thread *thread __used) 1400{ 1401 struct thread *sched_out __used, *sched_in; 1402 int new_shortname; 1403 u64 timestamp0; --- 11 unchanged lines hidden (view full) --- 1415 delta = timestamp - timestamp0; 1416 else 1417 delta = 0; 1418 1419 if (delta < 0) 1420 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1421 1422 | 1400 struct event *event __used, 1401 int this_cpu, 1402 u64 timestamp, 1403 struct thread *thread __used) 1404{ 1405 struct thread *sched_out __used, *sched_in; 1406 int new_shortname; 1407 u64 timestamp0; --- 11 unchanged lines hidden (view full) --- 1419 delta = timestamp - timestamp0; 1420 else 1421 delta = 0; 1422 1423 if (delta < 0) 1424 die("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1425 1426 |
1423 sched_out = perf_session__findnew(session, switch_event->prev_pid); 1424 sched_in = perf_session__findnew(session, switch_event->next_pid); | 1427 sched_out = machine__findnew_thread(machine, switch_event->prev_pid); 1428 sched_in = machine__findnew_thread(machine, switch_event->next_pid); |
1425 1426 curr_thread[this_cpu] = sched_in; 1427 1428 printf(" "); 1429 1430 new_shortname = 0; 1431 if (!sched_in->shortname[0]) { 1432 sched_in->shortname[0] = next_shortname1; --- 31 unchanged lines hidden (view full) --- 1464 if (new_shortname) { 1465 printf("%s => %s:%d\n", 1466 sched_in->shortname, sched_in->comm, sched_in->pid); 1467 } else { 1468 printf("\n"); 1469 } 1470} 1471 | 1429 1430 curr_thread[this_cpu] = sched_in; 1431 1432 printf(" "); 1433 1434 new_shortname = 0; 1435 if (!sched_in->shortname[0]) { 1436 sched_in->shortname[0] = next_shortname1; --- 31 unchanged lines hidden (view full) --- 1468 if (new_shortname) { 1469 printf("%s => %s:%d\n", 1470 sched_in->shortname, sched_in->comm, sched_in->pid); 1471 } else { 1472 printf("\n"); 1473 } 1474} 1475 |
1472 | |
1473static void | 1476static void |
1474process_sched_switch_event(void *data, struct perf_session *session, | 1477process_sched_switch_event(struct perf_tool *tool __used, |
1475 struct event *event, | 1478 struct event *event, |
1476 int this_cpu, 1477 u64 timestamp __used, 1478 struct thread *thread __used) | 1479 struct perf_sample *sample, 1480 struct machine *machine, 1481 struct thread *thread) |
1479{ | 1482{ |
1483 int this_cpu = sample->cpu; 1484 void *data = sample->raw_data; |
|
1480 struct trace_switch_event switch_event; 1481 1482 FILL_COMMON_FIELDS(switch_event, event, data); 1483 1484 FILL_ARRAY(switch_event, prev_comm, event, data); 1485 FILL_FIELD(switch_event, prev_pid, event, data); 1486 FILL_FIELD(switch_event, prev_prio, event, data); 1487 FILL_FIELD(switch_event, prev_state, event, data); --- 5 unchanged lines hidden (view full) --- 1493 /* 1494 * Are we trying to switch away a PID that is 1495 * not current? 1496 */ 1497 if (curr_pid[this_cpu] != switch_event.prev_pid) 1498 nr_context_switch_bugs++; 1499 } 1500 if (trace_handler->switch_event) | 1485 struct trace_switch_event switch_event; 1486 1487 FILL_COMMON_FIELDS(switch_event, event, data); 1488 1489 FILL_ARRAY(switch_event, prev_comm, event, data); 1490 FILL_FIELD(switch_event, prev_pid, event, data); 1491 FILL_FIELD(switch_event, prev_prio, event, data); 1492 FILL_FIELD(switch_event, prev_state, event, data); --- 5 unchanged lines hidden (view full) --- 1498 /* 1499 * Are we trying to switch away a PID that is 1500 * not current? 1501 */ 1502 if (curr_pid[this_cpu] != switch_event.prev_pid) 1503 nr_context_switch_bugs++; 1504 } 1505 if (trace_handler->switch_event) |
1501 trace_handler->switch_event(&switch_event, session, event, 1502 this_cpu, timestamp, thread); | 1506 trace_handler->switch_event(&switch_event, machine, event, 1507 this_cpu, sample->time, thread); |
1503 1504 curr_pid[this_cpu] = switch_event.next_pid; 1505} 1506 1507static void | 1508 1509 curr_pid[this_cpu] = switch_event.next_pid; 1510} 1511 1512static void |
1508process_sched_runtime_event(void *data, struct perf_session *session, 1509 struct event *event, 1510 int cpu __used, 1511 u64 timestamp __used, 1512 struct thread *thread __used) | 1513process_sched_runtime_event(struct perf_tool *tool __used, 1514 struct event *event, 1515 struct perf_sample *sample, 1516 struct machine *machine, 1517 struct thread *thread) |
1513{ | 1518{ |
1519 void *data = sample->raw_data; |
|
1514 struct trace_runtime_event runtime_event; 1515 1516 FILL_ARRAY(runtime_event, comm, event, data); 1517 FILL_FIELD(runtime_event, pid, event, data); 1518 FILL_FIELD(runtime_event, runtime, event, data); 1519 FILL_FIELD(runtime_event, vruntime, event, data); 1520 1521 if (trace_handler->runtime_event) | 1520 struct trace_runtime_event runtime_event; 1521 1522 FILL_ARRAY(runtime_event, comm, event, data); 1523 FILL_FIELD(runtime_event, pid, event, data); 1524 FILL_FIELD(runtime_event, runtime, event, data); 1525 FILL_FIELD(runtime_event, vruntime, event, data); 1526 1527 if (trace_handler->runtime_event) |
1522 trace_handler->runtime_event(&runtime_event, session, event, cpu, timestamp, thread); | 1528 trace_handler->runtime_event(&runtime_event, machine, event, 1529 sample->cpu, sample->time, thread); |
1523} 1524 1525static void | 1530} 1531 1532static void |
1526process_sched_fork_event(void *data, | 1533process_sched_fork_event(struct perf_tool *tool __used, |
1527 struct event *event, | 1534 struct event *event, |
1528 int cpu __used, 1529 u64 timestamp __used, 1530 struct thread *thread __used) | 1535 struct perf_sample *sample, 1536 struct machine *machine __used, 1537 struct thread *thread) |
1531{ | 1538{ |
1539 void *data = sample->raw_data; |
|
1532 struct trace_fork_event fork_event; 1533 1534 FILL_COMMON_FIELDS(fork_event, event, data); 1535 1536 FILL_ARRAY(fork_event, parent_comm, event, data); 1537 FILL_FIELD(fork_event, parent_pid, event, data); 1538 FILL_ARRAY(fork_event, child_comm, event, data); 1539 FILL_FIELD(fork_event, child_pid, event, data); 1540 1541 if (trace_handler->fork_event) 1542 trace_handler->fork_event(&fork_event, event, | 1540 struct trace_fork_event fork_event; 1541 1542 FILL_COMMON_FIELDS(fork_event, event, data); 1543 1544 FILL_ARRAY(fork_event, parent_comm, event, data); 1545 FILL_FIELD(fork_event, parent_pid, event, data); 1546 FILL_ARRAY(fork_event, child_comm, event, data); 1547 FILL_FIELD(fork_event, child_pid, event, data); 1548 1549 if (trace_handler->fork_event) 1550 trace_handler->fork_event(&fork_event, event, |
1543 cpu, timestamp, thread); | 1551 sample->cpu, sample->time, thread); |
1544} 1545 1546static void | 1552} 1553 1554static void |
1547process_sched_exit_event(struct event *event, 1548 int cpu __used, 1549 u64 timestamp __used, | 1555process_sched_exit_event(struct perf_tool *tool __used, 1556 struct event *event, 1557 struct perf_sample *sample __used, 1558 struct machine *machine __used, |
1550 struct thread *thread __used) 1551{ 1552 if (verbose) 1553 printf("sched_exit event %p\n", event); 1554} 1555 1556static void | 1559 struct thread *thread __used) 1560{ 1561 if (verbose) 1562 printf("sched_exit event %p\n", event); 1563} 1564 1565static void |
1557process_sched_migrate_task_event(void *data, struct perf_session *session, 1558 struct event *event, 1559 int cpu __used, 1560 u64 timestamp __used, 1561 struct thread *thread __used) | 1566process_sched_migrate_task_event(struct perf_tool *tool __used, 1567 struct event *event, 1568 struct perf_sample *sample, 1569 struct machine *machine, 1570 struct thread *thread) |
1562{ | 1571{ |
1572 void *data = sample->raw_data; |
|
1563 struct trace_migrate_task_event migrate_task_event; 1564 1565 FILL_COMMON_FIELDS(migrate_task_event, event, data); 1566 1567 FILL_ARRAY(migrate_task_event, comm, event, data); 1568 FILL_FIELD(migrate_task_event, pid, event, data); 1569 FILL_FIELD(migrate_task_event, prio, event, data); 1570 FILL_FIELD(migrate_task_event, cpu, event, data); 1571 1572 if (trace_handler->migrate_task_event) | 1573 struct trace_migrate_task_event migrate_task_event; 1574 1575 FILL_COMMON_FIELDS(migrate_task_event, event, data); 1576 1577 FILL_ARRAY(migrate_task_event, comm, event, data); 1578 FILL_FIELD(migrate_task_event, pid, event, data); 1579 FILL_FIELD(migrate_task_event, prio, event, data); 1580 FILL_FIELD(migrate_task_event, cpu, event, data); 1581 1582 if (trace_handler->migrate_task_event) |
1573 trace_handler->migrate_task_event(&migrate_task_event, session, 1574 event, cpu, timestamp, thread); | 1583 trace_handler->migrate_task_event(&migrate_task_event, machine, 1584 event, sample->cpu, 1585 sample->time, thread); |
1575} 1576 | 1586} 1587 |
1577static void process_raw_event(union perf_event *raw_event __used, 1578 struct perf_session *session, void *data, int cpu, 1579 u64 timestamp, struct thread *thread) 1580{ 1581 struct event *event; 1582 int type; | 1588typedef void (*tracepoint_handler)(struct perf_tool *tool, struct event *event, 1589 struct perf_sample *sample, 1590 struct machine *machine, 1591 struct thread *thread); |
1583 | 1592 |
1584 1585 type = trace_parse_common_type(data); 1586 event = trace_find_event(type); 1587 1588 if (!strcmp(event->name, "sched_switch")) 1589 process_sched_switch_event(data, session, event, cpu, timestamp, thread); 1590 if (!strcmp(event->name, "sched_stat_runtime")) 1591 process_sched_runtime_event(data, session, event, cpu, timestamp, thread); 1592 if (!strcmp(event->name, "sched_wakeup")) 1593 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread); 1594 if (!strcmp(event->name, "sched_wakeup_new")) 1595 process_sched_wakeup_event(data, session, event, cpu, timestamp, thread); 1596 if (!strcmp(event->name, "sched_process_fork")) 1597 process_sched_fork_event(data, event, cpu, timestamp, thread); 1598 if (!strcmp(event->name, "sched_process_exit")) 1599 process_sched_exit_event(event, cpu, timestamp, thread); 1600 if (!strcmp(event->name, "sched_migrate_task")) 1601 process_sched_migrate_task_event(data, session, event, cpu, timestamp, thread); 1602} 1603 1604static int process_sample_event(union perf_event *event, 1605 struct perf_sample *sample, 1606 struct perf_evsel *evsel __used, 1607 struct perf_session *session) | 1593static int perf_sched__process_tracepoint_sample(struct perf_tool *tool, 1594 union perf_event *event __used, 1595 struct perf_sample *sample, 1596 struct perf_evsel *evsel, 1597 struct machine *machine) |
1608{ | 1598{ |
1609 struct thread *thread; | 1599 struct thread *thread = machine__findnew_thread(machine, sample->pid); |
1610 | 1600 |
1611 if (!(session->sample_type & PERF_SAMPLE_RAW)) 1612 return 0; 1613 1614 thread = perf_session__findnew(session, sample->pid); | |
1615 if (thread == NULL) { | 1601 if (thread == NULL) { |
1616 pr_debug("problem processing %d event, skipping it.\n", 1617 event->header.type); | 1602 pr_debug("problem processing %s event, skipping it.\n", 1603 evsel->name); |
1618 return -1; 1619 } 1620 | 1604 return -1; 1605 } 1606 |
1621 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); | 1607 evsel->hists.stats.total_period += sample->period; 1608 hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); |
1622 | 1609 |
1623 if (profile_cpu != -1 && profile_cpu != (int)sample->cpu) 1624 return 0; | 1610 if (evsel->handler.func != NULL) { 1611 tracepoint_handler f = evsel->handler.func; |
1625 | 1612 |
1626 process_raw_event(event, session, sample->raw_data, sample->cpu, 1627 sample->time, thread); | 1613 if (evsel->handler.data == NULL) 1614 evsel->handler.data = trace_find_event(evsel->attr.config); |
1628 | 1615 |
1616 f(tool, evsel->handler.data, sample, machine, thread); 1617 } 1618 |
|
1629 return 0; 1630} 1631 | 1619 return 0; 1620} 1621 |
1632static struct perf_event_ops event_ops = { 1633 .sample = process_sample_event, | 1622static struct perf_tool perf_sched = { 1623 .sample = perf_sched__process_tracepoint_sample, |
1634 .comm = perf_event__process_comm, 1635 .lost = perf_event__process_lost, 1636 .fork = perf_event__process_task, 1637 .ordered_samples = true, 1638}; 1639 1640static void read_events(bool destroy, struct perf_session **psession) 1641{ 1642 int err = -EINVAL; | 1624 .comm = perf_event__process_comm, 1625 .lost = perf_event__process_lost, 1626 .fork = perf_event__process_task, 1627 .ordered_samples = true, 1628}; 1629 1630static void read_events(bool destroy, struct perf_session **psession) 1631{ 1632 int err = -EINVAL; |
1633 const struct perf_evsel_str_handler handlers[] = { 1634 { "sched:sched_switch", process_sched_switch_event, }, 1635 { "sched:sched_stat_runtime", process_sched_runtime_event, }, 1636 { "sched:sched_wakeup", process_sched_wakeup_event, }, 1637 { "sched:sched_wakeup_new", process_sched_wakeup_event, }, 1638 { "sched:sched_process_fork", process_sched_fork_event, }, 1639 { "sched:sched_process_exit", process_sched_exit_event, }, 1640 { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1641 }; |
|
1643 struct perf_session *session = perf_session__new(input_name, O_RDONLY, | 1642 struct perf_session *session = perf_session__new(input_name, O_RDONLY, |
1644 0, false, &event_ops); | 1643 0, false, &perf_sched); |
1645 if (session == NULL) 1646 die("No Memory"); 1647 | 1644 if (session == NULL) 1645 die("No Memory"); 1646 |
1647 err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers); 1648 assert(err == 0); 1649 |
|
1648 if (perf_session__has_traces(session, "record -R")) { | 1650 if (perf_session__has_traces(session, "record -R")) { |
1649 err = perf_session__process_events(session, &event_ops); | 1651 err = perf_session__process_events(session, &perf_sched); |
1650 if (err) 1651 die("Failed to process events, error %d", err); 1652 1653 nr_events = session->hists.stats.nr_events[0]; 1654 nr_lost_events = session->hists.stats.total_lost; 1655 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; 1656 } 1657 --- 268 unchanged lines hidden --- | 1652 if (err) 1653 die("Failed to process events, error %d", err); 1654 1655 nr_events = session->hists.stats.nr_events[0]; 1656 nr_lost_events = session->hists.stats.total_lost; 1657 nr_lost_chunks = session->hists.stats.nr_events[PERF_RECORD_LOST]; 1658 } 1659 --- 268 unchanged lines hidden --- |