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 ---