1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "builtin.h" 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "perf.h" 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/util.h" 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/evlist.h" 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/cache.h" 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/evsel.h" 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/symbol.h" 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/thread.h" 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/header.h" 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/session.h" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/tool.h" 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/parse-options.h" 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/trace-event.h" 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "util/debug.h" 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/prctl.h> 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/resource.h> 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <semaphore.h> 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <pthread.h> 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <math.h> 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define PR_SET_NAME 15 /* Set process name */ 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define MAX_CPUS 4096 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define COMM_LEN 20 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define SYM_LEN 129 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define MAX_PID 65536 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct sched_atom; 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct task_desc { 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr; 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long pid; 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char comm[COMM_LEN]; 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_events; 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long curr_event; 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom **atoms; 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_t thread; 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_t sleep_sem; 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_t ready_for_work; 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_t work_done_sem; 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cpu_usage; 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum sched_event_type { 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SCHED_EVENT_RUN, 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SCHED_EVENT_SLEEP, 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SCHED_EVENT_WAKEUP, 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng SCHED_EVENT_MIGRATION, 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct sched_atom { 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum sched_event_type type; 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int specific_wait; 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp; 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 duration; 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr; 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_t *wait_sem; 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *wakee; 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define TASK_STATE_TO_CHAR_STR "RSDTtZX" 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum thread_state { 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng THREAD_SLEEPING = 0, 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng THREAD_WAIT_CPU, 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng THREAD_SCHED_IN, 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng THREAD_IGNORE 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct work_atom { 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head list; 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng enum thread_state state; 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sched_out_time; 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 wake_up_time; 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sched_in_time; 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 runtime; 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct work_atoms { 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head work_list; 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *thread; 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node node; 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 max_lat; 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 max_lat_at; 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_lat; 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 nb_atoms; 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 total_runtime; 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengtypedef int (*sort_fn_t)(struct work_atoms *, struct work_atoms *); 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct perf_sched; 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct trace_sched_handler { 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int (*switch_event)(struct perf_sched *sched, struct perf_evsel *evsel, 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, struct machine *machine); 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int (*runtime_event)(struct perf_sched *sched, struct perf_evsel *evsel, 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, struct machine *machine); 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int (*wakeup_event)(struct perf_sched *sched, struct perf_evsel *evsel, 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, struct machine *machine); 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* PERF_RECORD_FORK event, not sched_process_fork tracepoint */ 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int (*fork_event)(struct perf_sched *sched, union perf_event *event, 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine); 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int (*migrate_task_event)(struct perf_sched *sched, 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine); 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct perf_sched { 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_tool tool; 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *sort_order; 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_tasks; 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *pid_to_task[MAX_PID]; 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc **tasks; 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct trace_sched_handler *tp_handler; 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_t start_work_mutex; 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_t work_done_wait_mutex; 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int profile_cpu; 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Track the current task - that way we can know whether there's any 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * weird events, such as a task being switched away that is not current. 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int max_cpu; 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 curr_pid[MAX_CPUS]; 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *curr_thread[MAX_CPUS]; 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char next_shortname1; 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char next_shortname2; 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int replay_repeat; 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_run_events; 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_sleep_events; 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_wakeup_events; 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_sleep_corrections; 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_run_events_optimized; 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long targetless_wakeups; 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long multitarget_wakeups; 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_runs; 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_timestamps; 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_unordered_timestamps; 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_state_machine_bugs; 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_context_switch_bugs; 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_events; 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_lost_chunks; 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long nr_lost_events; 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 run_measurement_overhead; 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sleep_measurement_overhead; 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 start_time; 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cpu_usage; 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 runavg_cpu_usage; 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 parent_cpu_usage; 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 runavg_parent_cpu_usage; 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sum_runtime; 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sum_fluct; 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 run_avg; 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 all_runtime; 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 all_count; 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cpu_last_switched[MAX_CPUS]; 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_root atom_root, sorted_atom_root; 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head sort_list, cmp_pid; 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic u64 get_nsecs(void) 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1760da480317e158a520d3128d45ed070c048a07187Ben Cheng#ifndef __APPLE__ 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct timespec ts; 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng clock_gettime(CLOCK_MONOTONIC, &ts); 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ts.tv_sec * 1000000000ULL + ts.tv_nsec; 1820da480317e158a520d3128d45ed070c048a07187Ben Cheng#else 1830da480317e158a520d3128d45ed070c048a07187Ben Cheng perror("get_nsecs not supported on MacOS"); 1840da480317e158a520d3128d45ed070c048a07187Ben Cheng return 0; 1850da480317e158a520d3128d45ed070c048a07187Ben Cheng#endif 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void burn_nsecs(struct perf_sched *sched, u64 nsecs) 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 T0 = get_nsecs(), T1; 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng do { 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } while (T1 + sched->run_measurement_overhead < T0 + nsecs); 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void sleep_nsecs(u64 nsecs) 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct timespec ts; 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ts.tv_nsec = nsecs % 999999999; 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ts.tv_sec = nsecs / 999999999; 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nanosleep(&ts, NULL); 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void calibrate_run_measurement_overhead(struct perf_sched *sched) 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 T0, T1, delta, min_delta = 1000000000ULL; 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 10; i++) { 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T0 = get_nsecs(); 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng burn_nsecs(sched, 0); 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = T1-T0; 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng min_delta = min(min_delta, delta); 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->run_measurement_overhead = min_delta; 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("run measurement overhead: %" PRIu64 " nsecs\n", min_delta); 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void calibrate_sleep_measurement_overhead(struct perf_sched *sched) 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 T0, T1, delta, min_delta = 1000000000ULL; 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 10; i++) { 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T0 = get_nsecs(); 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sleep_nsecs(10000); 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = T1-T0; 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng min_delta = min(min_delta, delta); 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng min_delta -= 10000; 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->sleep_measurement_overhead = min_delta; 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("sleep measurement overhead: %" PRIu64 " nsecs\n", min_delta); 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct sched_atom * 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengget_new_event(struct task_desc *task, u64 timestamp) 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom *event = zalloc(sizeof(*event)); 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long idx = task->nr_events; 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t size; 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->timestamp = timestamp; 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->nr = idx; 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->nr_events++; 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size = sizeof(struct sched_atom *) * task->nr_events; 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->atoms = realloc(task->atoms, size); 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(!task->atoms); 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->atoms[idx] = event; 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return event; 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct sched_atom *last_event(struct task_desc *task) 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!task->nr_events) 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return task->atoms[task->nr_events - 1]; 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void add_sched_event_run(struct perf_sched *sched, struct task_desc *task, 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp, u64 duration) 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom *event, *curr_event = last_event(task); 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * optimize an existing RUN event by merging this one 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * to it: 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (curr_event && curr_event->type == SCHED_EVENT_RUN) { 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_run_events_optimized++; 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng curr_event->duration += duration; 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event = get_new_event(task, timestamp); 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->type = SCHED_EVENT_RUN; 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->duration = duration; 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_run_events++; 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void add_sched_event_wakeup(struct perf_sched *sched, struct task_desc *task, 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp, struct task_desc *wakee) 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom *event, *wakee_event; 297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event = get_new_event(task, timestamp); 299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->type = SCHED_EVENT_WAKEUP; 300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->wakee = wakee; 301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wakee_event = last_event(wakee); 303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!wakee_event || wakee_event->type != SCHED_EVENT_SLEEP) { 304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->targetless_wakeups++; 305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (wakee_event->wait_sem) { 308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->multitarget_wakeups++; 309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wakee_event->wait_sem = zalloc(sizeof(*wakee_event->wait_sem)); 313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(wakee_event->wait_sem, 0, 0); 314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wakee_event->specific_wait = 1; 315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->wait_sem = wakee_event->wait_sem; 316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_wakeup_events++; 318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void add_sched_event_sleep(struct perf_sched *sched, struct task_desc *task, 321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp, u64 task_state __maybe_unused) 322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom *event = get_new_event(task, timestamp); 324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->type = SCHED_EVENT_SLEEP; 326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_sleep_events++; 328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct task_desc *register_pid(struct perf_sched *sched, 331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long pid, const char *comm) 332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task; 334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(pid >= MAX_PID); 336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = sched->pid_to_task[pid]; 338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (task) 340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return task; 341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = zalloc(sizeof(*task)); 343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->pid = pid; 344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->nr = sched->nr_tasks; 345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strcpy(task->comm, comm); 346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * every task starts in sleeping state - this gets ignored 348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * if there's no wakeup pointing to this sleep state: 349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_event_sleep(sched, task, 0, 0); 351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->pid_to_task[pid] = task; 353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_tasks++; 354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->tasks = realloc(sched->tasks, sched->nr_tasks * sizeof(struct task_task *)); 355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(!sched->tasks); 356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->tasks[task->nr] = task; 357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose) 359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("registered task #%ld, PID %ld (%s)\n", sched->nr_tasks, pid, comm); 360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return task; 362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void print_task_traces(struct perf_sched *sched) 366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task; 368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i; 369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = sched->tasks[i]; 372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("task %6ld (%20s:%10ld), nr_events: %ld\n", 373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->nr, task->comm, task->pid, task->nr_events); 374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void add_cross_task_wakeups(struct perf_sched *sched) 378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task1, *task2; 380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i, j; 381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task1 = sched->tasks[i]; 384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng j = i + 1; 385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (j == sched->nr_tasks) 386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng j = 0; 387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task2 = sched->tasks[j]; 388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_event_wakeup(sched, task1, 0, task2); 389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void perf_sched__process_event(struct perf_sched *sched, 393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_atom *atom) 394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = 0; 396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng switch (atom->type) { 398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case SCHED_EVENT_RUN: 399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng burn_nsecs(sched, atom->duration); 400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case SCHED_EVENT_SLEEP: 402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (atom->wait_sem) 403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_wait(atom->wait_sem); 404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case SCHED_EVENT_WAKEUP: 407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (atom->wait_sem) 408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_post(atom->wait_sem); 409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng case SCHED_EVENT_MIGRATION: 412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng default: 414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(1); 415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic u64 get_cpu_usage_nsec_parent(void) 419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rusage ru; 421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 sum; 422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err; 423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = getrusage(RUSAGE_SELF, &ru); 425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sum = ru.ru_utime.tv_sec*1e9 + ru.ru_utime.tv_usec*1e3; 428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sum += ru.ru_stime.tv_sec*1e9 + ru.ru_stime.tv_usec*1e3; 429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sum; 431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int self_open_counters(void) 434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_event_attr attr; 436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int fd; 437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng memset(&attr, 0, sizeof(attr)); 439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng attr.type = PERF_TYPE_SOFTWARE; 441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng attr.config = PERF_COUNT_SW_TASK_CLOCK; 442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fd < 0) 446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("Error: sys_perf_event_open() syscall returned " 447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "with %d (%s)\n", fd, strerror(errno)); 448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return fd; 449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic u64 get_cpu_usage_nsec_self(int fd) 452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 runtime; 454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = read(fd, &runtime, sizeof(runtime)); 457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret != sizeof(runtime)); 458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return runtime; 460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct sched_thread_parms { 463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task; 464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched; 465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void *thread_func(void *ctx) 468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 4690da480317e158a520d3128d45ed070c048a07187Ben Cheng#ifndef __APPLE__ 470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_thread_parms *parms = ctx; 471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *this_task = parms->task; 472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = parms->sched; 473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cpu_usage_0, cpu_usage_1; 474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i, ret; 475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char comm2[22]; 476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int fd; 477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(parms); 479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sprintf(comm2, ":%s", this_task->comm); 481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng prctl(PR_SET_NAME, comm2); 482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fd = self_open_counters(); 483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (fd < 0) 484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengagain: 486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_post(&this_task->ready_for_work); 487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_lock(&sched->start_work_mutex); 489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_unlock(&sched->start_work_mutex); 491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpu_usage_0 = get_cpu_usage_nsec_self(fd); 494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < this_task->nr_events; i++) { 496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng this_task->curr_event = i; 497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_sched__process_event(sched, this_task->atoms[i]); 498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpu_usage_1 = get_cpu_usage_nsec_self(fd); 501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng this_task->cpu_usage = cpu_usage_1 - cpu_usage_0; 502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_post(&this_task->work_done_sem); 503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_lock(&sched->work_done_wait_mutex); 506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_unlock(&sched->work_done_wait_mutex); 508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto again; 5110da480317e158a520d3128d45ed070c048a07187Ben Cheng#else 5120da480317e158a520d3128d45ed070c048a07187Ben Cheng perror("thread_func not supported on MacOS"); 5130da480317e158a520d3128d45ed070c048a07187Ben Cheng return NULL; 5140da480317e158a520d3128d45ed070c048a07187Ben Cheng#endif 515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void create_tasks(struct perf_sched *sched) 518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task; 520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_attr_t attr; 521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i; 522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err; 523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = pthread_attr_init(&attr); 525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = pthread_attr_setstacksize(&attr, 527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (size_t) max(16 * 1024, PTHREAD_STACK_MIN)); 528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = pthread_mutex_lock(&sched->start_work_mutex); 530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = pthread_mutex_lock(&sched->work_done_wait_mutex); 532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sched_thread_parms *parms = malloc(sizeof(*parms)); 535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(parms == NULL); 536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parms->task = task = sched->tasks[i]; 537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parms->sched = sched; 538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->sleep_sem, 0, 0); 539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->ready_for_work, 0, 0); 540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->work_done_sem, 0, 0); 541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->curr_event = 0; 542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = pthread_create(&task->thread, &attr, thread_func, parms); 543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(err); 544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void wait_for_tasks(struct perf_sched *sched) 548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 cpu_usage_0, cpu_usage_1; 550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *task; 551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i, ret; 552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->start_time = get_nsecs(); 554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->cpu_usage = 0; 555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_unlock(&sched->work_done_wait_mutex); 556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = sched->tasks[i]; 559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_wait(&task->ready_for_work); 560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->ready_for_work, 0, 0); 562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_lock(&sched->work_done_wait_mutex); 564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpu_usage_0 = get_cpu_usage_nsec_parent(); 567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pthread_mutex_unlock(&sched->start_work_mutex); 569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = sched->tasks[i]; 572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sem_wait(&task->work_done_sem); 573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->work_done_sem, 0, 0); 575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->cpu_usage += task->cpu_usage; 576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->cpu_usage = 0; 577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cpu_usage_1 = get_cpu_usage_nsec_parent(); 580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!sched->runavg_cpu_usage) 581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->runavg_cpu_usage = sched->cpu_usage; 582e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->runavg_cpu_usage = (sched->runavg_cpu_usage * 9 + sched->cpu_usage) / 10; 583e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 584e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->parent_cpu_usage = cpu_usage_1 - cpu_usage_0; 585e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!sched->runavg_parent_cpu_usage) 586e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->runavg_parent_cpu_usage = sched->parent_cpu_usage; 587e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->runavg_parent_cpu_usage = (sched->runavg_parent_cpu_usage * 9 + 588e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->parent_cpu_usage)/10; 589e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 590e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = pthread_mutex_lock(&sched->start_work_mutex); 591e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(ret); 592e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 593e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->nr_tasks; i++) { 594e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task = sched->tasks[i]; 595e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sem_init(&task->sleep_sem, 0, 0); 596e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng task->curr_event = 0; 597e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 598e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 599e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 600e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void run_one_test(struct perf_sched *sched) 601e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 602e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 T0, T1, delta, avg_delta, fluct; 603e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 604e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T0 = get_nsecs(); 605e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wait_for_tasks(sched); 606e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 607e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 608e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = T1 - T0; 609e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->sum_runtime += delta; 610e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_runs++; 611e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 612e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng avg_delta = sched->sum_runtime / sched->nr_runs; 613e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delta < avg_delta) 614e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fluct = avg_delta - delta; 615e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 616e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng fluct = delta - avg_delta; 617e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->sum_fluct += fluct; 618e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!sched->run_avg) 619e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->run_avg = delta; 620e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->run_avg = (sched->run_avg * 9 + delta) / 10; 621e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 622e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); 623e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 624e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6); 625e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 626e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("cpu: %0.2f / %0.2f", 627e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6); 628e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 629e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#if 0 630e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 631e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * rusage statistics done by the parent, these are less 632e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * accurate than the sched->sum_exec_runtime based statistics: 633e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 634e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" [%0.2f / %0.2f]", 635e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->parent_cpu_usage/1e6, 636e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->runavg_parent_cpu_usage/1e6); 637e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#endif 638e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 639e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n"); 640e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 641e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_sleep_corrections) 642e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" (%ld sleep corrections)\n", sched->nr_sleep_corrections); 643e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_sleep_corrections = 0; 644e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 645e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 646e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void test_calibrations(struct perf_sched *sched) 647e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 648e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 T0, T1; 649e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 650e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T0 = get_nsecs(); 651e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng burn_nsecs(sched, 1e6); 652e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 653e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 654e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("the run test took %" PRIu64 " nsecs\n", T1 - T0); 655e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 656e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T0 = get_nsecs(); 657e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sleep_nsecs(1e6); 658e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng T1 = get_nsecs(); 659e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 660e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0); 661e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 662e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 663e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int 664e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengreplay_wakeup_event(struct perf_sched *sched, 665e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, struct perf_sample *sample, 666e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine __maybe_unused) 667e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 668e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *comm = perf_evsel__strval(evsel, sample, "comm"); 669e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 670e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *waker, *wakee; 671e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 672e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose) { 673e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("sched_wakeup event %p\n", evsel); 674e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 675e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" ... pid %d woke up %s/%d\n", sample->tid, comm, pid); 676e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 677e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 678e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng waker = register_pid(sched, sample->tid, "<unknown>"); 679e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wakee = register_pid(sched, pid, comm); 680e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 681e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_event_wakeup(sched, waker, sample->time, wakee); 682e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 683e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 684e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 685e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int replay_switch_event(struct perf_sched *sched, 686e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 687e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 688e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine __maybe_unused) 689e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 690e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *prev_comm = perf_evsel__strval(evsel, sample, "prev_comm"), 691e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *next_comm = perf_evsel__strval(evsel, sample, "next_comm"); 692e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), 693e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 694e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); 695e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct task_desc *prev, __maybe_unused *next; 696e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp0, timestamp = sample->time; 697e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cpu = sample->cpu; 698e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 delta; 699e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 700e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose) 701e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("sched_switch event %p\n", evsel); 702e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 703e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cpu >= MAX_CPUS || cpu < 0) 704e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 705e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 706e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng timestamp0 = sched->cpu_last_switched[cpu]; 707e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (timestamp0) 708e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = timestamp - timestamp0; 709e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 710e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = 0; 711e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 712e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delta < 0) { 713e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); 714e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 715e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 716e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 717e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug(" ... switch from %s/%d to %s/%d [ran %" PRIu64 " nsecs]\n", 718e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng prev_comm, prev_pid, next_comm, next_pid, delta); 719e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 720e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng prev = register_pid(sched, prev_pid, prev_comm); 721e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = register_pid(sched, next_pid, next_comm); 722e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 723e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->cpu_last_switched[cpu] = timestamp; 724e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 725e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_event_run(sched, prev, timestamp, delta); 726e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_event_sleep(sched, prev, timestamp, prev_state); 727e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 728e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 729e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 730e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 731e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int replay_fork_event(struct perf_sched *sched, 732e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event, 733e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 734e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 735e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *child, *parent; 736e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 737e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng child = machine__findnew_thread(machine, event->fork.pid, 738e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->fork.tid); 739e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parent = machine__findnew_thread(machine, event->fork.ppid, 740e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng event->fork.ptid); 741e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 742e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (child == NULL || parent == NULL) { 743e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("thread does not exist on fork event: child %p, parent %p\n", 744e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng child, parent); 745e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 746e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 747e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 748e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (verbose) { 749e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("fork event\n"); 750e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("... parent: %s/%d\n", parent->comm, parent->tid); 751e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("... child: %s/%d\n", child->comm, child->tid); 752e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 753e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 754e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng register_pid(sched, parent->tid, parent->comm); 755e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng register_pid(sched, child->tid, child->comm); 756e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 757e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 758e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 759e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct sort_dimension { 760e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *name; 761e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sort_fn_t cmp; 762e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head list; 763e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 764e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 765e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int 766e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengthread_lat_cmp(struct list_head *list, struct work_atoms *l, struct work_atoms *r) 767e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 768e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sort_dimension *sort; 769e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret = 0; 770e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 771e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(list_empty(list)); 772e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 773e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_for_each_entry(sort, list, list) { 774e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = sort->cmp(l, r); 775e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (ret) 776e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 777e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 778e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 779e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return ret; 780e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 781e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 782e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct work_atoms * 783e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengthread_atoms_search(struct rb_root *root, struct thread *thread, 784e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head *sort_list) 785e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 786e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *node = root->rb_node; 787e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms key = { .thread = thread }; 788e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 789e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (node) { 790e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *atoms; 791e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cmp; 792e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 793e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = container_of(node, struct work_atoms, node); 794e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 795e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cmp = thread_lat_cmp(sort_list, &key, atoms); 796e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cmp > 0) 797e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = node->rb_left; 798e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else if (cmp < 0) 799e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = node->rb_right; 800e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else { 801e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(thread != atoms->thread); 802e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return atoms; 803e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 804e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 805e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 806e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 807e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 808e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void 809e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng__thread_latency_insert(struct rb_root *root, struct work_atoms *data, 810e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct list_head *sort_list) 811e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 812e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node **new = &(root->rb_node), *parent = NULL; 813e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 814e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (*new) { 815e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *this; 816e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cmp; 817e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 818e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng this = container_of(*new, struct work_atoms, node); 819e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng parent = *new; 820e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 821e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng cmp = thread_lat_cmp(sort_list, data, this); 822e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 823e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cmp > 0) 824e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new = &((*new)->rb_left); 825e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 826e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new = &((*new)->rb_right); 827e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 828e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 829e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_link_node(&data->node, parent, new); 830e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_insert_color(&data->node, root); 831e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 832e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 833e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int thread_atoms_insert(struct perf_sched *sched, struct thread *thread) 834e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 835e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *atoms = zalloc(sizeof(*atoms)); 836e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 837e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("No memory at %s\n", __func__); 838e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 839e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 840e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 841e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->thread = thread; 842e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng INIT_LIST_HEAD(&atoms->work_list); 843e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng __thread_latency_insert(&sched->atom_root, atoms, &sched->cmp_pid); 844e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 845e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 846e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 847e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic char sched_out_state(u64 prev_state) 848e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 849e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char *str = TASK_STATE_TO_CHAR_STR; 850e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 851e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return str[prev_state]; 852e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 853e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 854e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int 855e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengadd_sched_out_event(struct work_atoms *atoms, 856e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char run_state, 857e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp) 858e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 859e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atom *atom = zalloc(sizeof(*atom)); 860e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atom) { 861e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("Non memory at %s", __func__); 862e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 863e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 864e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 865e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->sched_out_time = timestamp; 866e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 867e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (run_state == 'R') { 868e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->state = THREAD_WAIT_CPU; 869e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->wake_up_time = atom->sched_out_time; 870e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 871e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 872e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_add_tail(&atom->list, &atoms->work_list); 873e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 874e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 875e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 876e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void 877e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengadd_runtime_event(struct work_atoms *atoms, u64 delta, 878e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp __maybe_unused) 879e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 880e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atom *atom; 881e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 882e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(list_empty(&atoms->work_list)); 883e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 884e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom = list_entry(atoms->work_list.prev, struct work_atom, list); 885e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 886e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->runtime += delta; 887e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->total_runtime += delta; 888e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 889e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 890e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void 891e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengadd_sched_in_event(struct work_atoms *atoms, u64 timestamp) 892e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 893e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atom *atom; 894e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 delta; 895e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 896e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (list_empty(&atoms->work_list)) 897e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 898e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 899e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom = list_entry(atoms->work_list.prev, struct work_atom, list); 900e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 901e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (atom->state != THREAD_WAIT_CPU) 902e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 903e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 904e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (timestamp < atom->wake_up_time) { 905e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->state = THREAD_IGNORE; 906e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 907e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 908e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 909e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->state = THREAD_SCHED_IN; 910e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->sched_in_time = timestamp; 911e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 912e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = atom->sched_in_time - atom->wake_up_time; 913e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->total_lat += delta; 914e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delta > atoms->max_lat) { 915e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->max_lat = delta; 916e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->max_lat_at = timestamp; 917e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 918e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms->nb_atoms++; 919e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 920e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 921e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int latency_switch_event(struct perf_sched *sched, 922e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 923e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 924e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 925e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 926e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), 927e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 928e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); 929e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *out_events, *in_events; 930e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *sched_out, *sched_in; 931e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp0, timestamp = sample->time; 932e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cpu = sample->cpu; 933e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 delta; 934e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 935e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(cpu >= MAX_CPUS || cpu < 0); 936e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 937e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng timestamp0 = sched->cpu_last_switched[cpu]; 938e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->cpu_last_switched[cpu] = timestamp; 939e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (timestamp0) 940e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = timestamp - timestamp0; 941e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 942e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = 0; 943e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 944e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delta < 0) { 945e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); 946e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 947e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 948e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 949e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_out = machine__findnew_thread(machine, 0, prev_pid); 950e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_in = machine__findnew_thread(machine, 0, next_pid); 951e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 952e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 953e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!out_events) { 954e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (thread_atoms_insert(sched, sched_out)) 955e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 956e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid); 957e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!out_events) { 958e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("out-event: Internal tree error"); 959e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 960e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 961e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 962e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (add_sched_out_event(out_events, sched_out_state(prev_state), timestamp)) 963e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 964e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 965e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); 966e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!in_events) { 967e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (thread_atoms_insert(sched, sched_in)) 968e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 969e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng in_events = thread_atoms_search(&sched->atom_root, sched_in, &sched->cmp_pid); 970e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!in_events) { 971e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("in-event: Internal tree error"); 972e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 973e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 974e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 975e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Take came in we have not heard about yet, 976e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * add in an initial atom in runnable state: 977e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 978e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (add_sched_out_event(in_events, 'R', timestamp)) 979e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 980e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 981e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_sched_in_event(in_events, timestamp); 982e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 983e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 984e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 985e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 986e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int latency_runtime_event(struct perf_sched *sched, 987e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 988e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 989e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 990e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 991e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 992e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u64 runtime = perf_evsel__intval(evsel, sample, "runtime"); 993e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *thread = machine__findnew_thread(machine, 0, pid); 994e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 995e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp = sample->time; 996e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cpu = sample->cpu; 997e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 998e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(cpu >= MAX_CPUS || cpu < 0); 999e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1000e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (thread_atoms_insert(sched, thread)) 1001e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1002e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid); 1003e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1004e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("in-event: Internal tree error"); 1005e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1006e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1007e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (add_sched_out_event(atoms, 'R', timestamp)) 1008e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1009e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1010e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1011e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_runtime_event(atoms, runtime, timestamp); 1012e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1013e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1014e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1015e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int latency_wakeup_event(struct perf_sched *sched, 1016e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1017e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1018e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1019e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1020e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 pid = perf_evsel__intval(evsel, sample, "pid"), 1021e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng success = perf_evsel__intval(evsel, sample, "success"); 1022e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *atoms; 1023e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atom *atom; 1024e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *wakee; 1025e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp = sample->time; 1026e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1027e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* Note for later, it may be interesting to observe the failing cases */ 1028e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!success) 1029e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1030e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1031e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng wakee = machine__findnew_thread(machine, 0, pid); 1032e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1033e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1034e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (thread_atoms_insert(sched, wakee)) 1035e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1036e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid); 1037e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1038e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("wakeup-event: Internal tree error"); 1039e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1040e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1041e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (add_sched_out_event(atoms, 'S', timestamp)) 1042e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1043e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1044e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1045e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(list_empty(&atoms->work_list)); 1046e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1047e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom = list_entry(atoms->work_list.prev, struct work_atom, list); 1048e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1049e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 1050e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * You WILL be missing events if you've recorded only 1051e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * one CPU, or are only looking at only one, so don't 1052e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * make useless noise. 1053e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 1054e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->profile_cpu == -1 && atom->state != THREAD_SLEEPING) 1055e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_state_machine_bugs++; 1056e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1057e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_timestamps++; 1058e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (atom->sched_out_time > timestamp) { 1059e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_unordered_timestamps++; 1060e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1061e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1062e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1063e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->state = THREAD_WAIT_CPU; 1064e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->wake_up_time = timestamp; 1065e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1066e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1067e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1068e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int latency_migrate_task_event(struct perf_sched *sched, 1069e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1070e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1071e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1072e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1073e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 pid = perf_evsel__intval(evsel, sample, "pid"); 1074e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp = sample->time; 1075e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *atoms; 1076e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atom *atom; 1077e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *migrant; 1078e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1079e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 1080e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Only need to worry about migration when profiling one CPU. 1081e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 1082e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->profile_cpu == -1) 1083e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1084e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1085e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng migrant = machine__findnew_thread(machine, 0, pid); 1086e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1087e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1088e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (thread_atoms_insert(sched, migrant)) 1089e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1090e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng register_pid(sched, migrant->tid, migrant->comm); 1091e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid); 1092e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!atoms) { 1093e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("migration-event: Internal tree error"); 1094e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1095e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1096e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (add_sched_out_event(atoms, 'R', timestamp)) 1097e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1098e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1099e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(list_empty(&atoms->work_list)); 1101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom = list_entry(atoms->work_list.prev, struct work_atom, list); 1103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng atom->sched_in_time = atom->sched_out_time = atom->wake_up_time = timestamp; 1104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_timestamps++; 1106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (atom->sched_out_time > timestamp) 1108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_unordered_timestamps++; 1109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_list) 1114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 1116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ret; 1117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 avg; 1118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!work_list->nb_atoms) 1120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 1121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 1122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Ignore idle threads: 1123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 1124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcmp(work_list->thread->comm, "swapper")) 1125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return; 1126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->all_runtime += work_list->total_runtime; 1128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->all_count += work_list->nb_atoms; 1129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ret = printf(" %s:%d ", work_list->thread->comm, work_list->thread->tid); 1131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < 24 - ret; i++) 1133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" "); 1134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng avg = work_list->total_lat / work_list->nb_atoms; 1136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %9.6f s\n", 1138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)work_list->total_runtime / 1e6, 1139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng work_list->nb_atoms, (double)avg / 1e6, 1140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)work_list->max_lat / 1e6, 1141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)work_list->max_lat_at / 1e9); 1142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->thread->tid < r->thread->tid) 1147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->thread->tid > r->thread->tid) 1149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int avg_cmp(struct work_atoms *l, struct work_atoms *r) 1155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 avgl, avgr; 1157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!l->nb_atoms) 1159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!r->nb_atoms) 1162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng avgl = l->total_lat / l->nb_atoms; 1165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng avgr = r->total_lat / r->nb_atoms; 1166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (avgl < avgr) 1168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (avgl > avgr) 1170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int max_cmp(struct work_atoms *l, struct work_atoms *r) 1176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->max_lat < r->max_lat) 1178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->max_lat > r->max_lat) 1180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int switch_cmp(struct work_atoms *l, struct work_atoms *r) 1186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->nb_atoms < r->nb_atoms) 1188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->nb_atoms > r->nb_atoms) 1190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int runtime_cmp(struct work_atoms *l, struct work_atoms *r) 1196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->total_runtime < r->total_runtime) 1198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (l->total_runtime > r->total_runtime) 1200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 1201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int sort_dimension__add(const char *tok, struct list_head *list) 1206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t i; 1208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static struct sort_dimension avg_sort_dimension = { 1209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .name = "avg", 1210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp = avg_cmp, 1211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static struct sort_dimension max_sort_dimension = { 1213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .name = "max", 1214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp = max_cmp, 1215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static struct sort_dimension pid_sort_dimension = { 1217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .name = "pid", 1218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp = pid_cmp, 1219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static struct sort_dimension runtime_sort_dimension = { 1221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .name = "runtime", 1222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp = runtime_cmp, 1223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng static struct sort_dimension switch_sort_dimension = { 1225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .name = "switch", 1226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp = switch_cmp, 1227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct sort_dimension *available_sorts[] = { 1229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &pid_sort_dimension, 1230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &avg_sort_dimension, 1231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &max_sort_dimension, 1232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &switch_sort_dimension, 1233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng &runtime_sort_dimension, 1234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < ARRAY_SIZE(available_sorts); i++) { 1237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcmp(available_sorts[i]->name, tok)) { 1238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng list_add_tail(&available_sorts[i]->list, list); 1239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void perf_sched__sort_lat(struct perf_sched *sched) 1248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *node; 1250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (;;) { 1252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *data; 1253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng node = rb_first(&sched->atom_root); 1254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!node) 1255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng break; 1256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rb_erase(node, &sched->atom_root); 1258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng data = rb_entry(node, struct work_atoms, node); 1259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng __thread_latency_insert(&sched->sorted_atom_root, data, &sched->sort_list); 1260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sched_wakeup_event(struct perf_tool *tool, 1264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->tp_handler->wakeup_event) 1271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sched->tp_handler->wakeup_event(sched, evsel, sample, machine); 1272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, 1277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, struct machine *machine) 1278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), 1280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 1281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread *sched_out __maybe_unused, *sched_in; 1282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int new_shortname; 1283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u64 timestamp0, timestamp = sample->time; 1284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng s64 delta; 1285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int cpu, this_cpu = sample->cpu; 1286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0); 1288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (this_cpu > sched->max_cpu) 1290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->max_cpu = this_cpu; 1291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng timestamp0 = sched->cpu_last_switched[this_cpu]; 1293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->cpu_last_switched[this_cpu] = timestamp; 1294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (timestamp0) 1295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = timestamp - timestamp0; 1296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 1297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng delta = 0; 1298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (delta < 0) { 1300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("hm, delta: %" PRIu64 " < 0 ?\n", delta); 1301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_out = machine__findnew_thread(machine, 0, prev_pid); 1305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_in = machine__findnew_thread(machine, 0, next_pid); 1306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->curr_thread[this_cpu] = sched_in; 1308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" "); 1310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_shortname = 0; 1312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!sched_in->shortname[0]) { 1313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_in->shortname[0] = sched->next_shortname1; 1314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_in->shortname[1] = sched->next_shortname2; 1315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->next_shortname1 < 'Z') { 1317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->next_shortname1++; 1318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 1319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->next_shortname1='A'; 1320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->next_shortname2 < '9') { 1321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->next_shortname2++; 1322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 1323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->next_shortname2='0'; 1324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng new_shortname = 1; 1327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (cpu = 0; cpu <= sched->max_cpu; cpu++) { 1330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (cpu != this_cpu) 1331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" "); 1332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 1333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("*"); 1334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->curr_thread[cpu]) { 1336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->curr_thread[cpu]->tid) 1337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("%2s ", sched->curr_thread[cpu]->shortname); 1338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 1339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(". "); 1340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else 1341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" "); 1342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" %12.6f secs ", (double)timestamp/1e9); 1345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (new_shortname) { 1346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("%s => %s:%d\n", 1347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched_in->shortname, sched_in->comm, sched_in->tid); 1348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 1349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n"); 1350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sched_switch_event(struct perf_tool *tool, 1356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int this_cpu = sample->cpu, err = 0; 1362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng u32 prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"), 1363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next_pid = perf_evsel__intval(evsel, sample, "next_pid"); 1364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->curr_pid[this_cpu] != (u32)-1) { 1366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 1367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Are we trying to switch away a PID that is 1368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * not current? 1369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 1370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->curr_pid[this_cpu] != prev_pid) 1371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_context_switch_bugs++; 1372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->tp_handler->switch_event) 1375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = sched->tp_handler->switch_event(sched, evsel, sample, machine); 1376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->curr_pid[this_cpu] = next_pid; 1378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return err; 1379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sched_runtime_event(struct perf_tool *tool, 1382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->tp_handler->runtime_event) 1389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sched->tp_handler->runtime_event(sched, evsel, sample, machine); 1390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__process_fork_event(struct perf_tool *tool, 1395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event, 1396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* run the fork event through the perf machineruy */ 1402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_event__process_fork(tool, event, sample, machine); 1403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* and then run additional processing needed for this command */ 1405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->tp_handler->fork_event) 1406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sched->tp_handler->fork_event(sched, event, machine); 1407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sched_migrate_task_event(struct perf_tool *tool, 1412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sched *sched = container_of(tool, struct perf_sched, tool); 1417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->tp_handler->migrate_task_event) 1419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return sched->tp_handler->migrate_task_event(sched, evsel, sample, machine); 1420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengtypedef int (*tracepoint_handler)(struct perf_tool *tool, 1425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine); 1428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_unused, 1430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng union perf_event *event __maybe_unused, 1431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_sample *sample, 1432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_evsel *evsel, 1433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct machine *machine) 1434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err = 0; 1436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng evsel->hists.stats.total_period += sample->period; 1438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); 1439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (evsel->handler.func != NULL) { 1441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng tracepoint_handler f = evsel->handler.func; 1442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng err = f(tool, evsel, sample, machine); 1443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return err; 1446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__read_events(struct perf_sched *sched, 1449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_session **psession) 1450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct perf_evsel_str_handler handlers[] = { 1452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { "sched:sched_switch", process_sched_switch_event, }, 1453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { "sched:sched_stat_runtime", process_sched_runtime_event, }, 1454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { "sched:sched_wakeup", process_sched_wakeup_event, }, 1455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { "sched:sched_wakeup_new", process_sched_wakeup_event, }, 1456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng { "sched:sched_migrate_task", process_sched_migrate_task_event, }, 1457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_session *session; 1459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng session = perf_session__new(input_name, O_RDONLY, 0, false, &sched->tool); 1461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (session == NULL) { 1462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_debug("No Memory for session\n"); 1463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_session__set_tracepoints_handlers(session, handlers)) 1467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_delete; 1468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_session__has_traces(session, "record -R")) { 1470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int err = perf_session__process_events(session, &sched->tool); 1471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (err) { 1472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pr_err("Failed to process events, error %d", err); 1473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_delete; 1474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_events = session->stats.nr_events[0]; 1477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_lost_events = session->stats.total_lost; 1478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; 1479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (psession) 1482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng *psession = session; 1483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 1484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_session__delete(session); 1485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_delete: 1489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_session__delete(session); 1490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void print_bad_events(struct perf_sched *sched) 1494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_unordered_timestamps && sched->nr_timestamps) { 1496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" INFO: %.3f%% unordered timestamps (%ld out of %ld)\n", 1497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->nr_unordered_timestamps/(double)sched->nr_timestamps*100.0, 1498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_unordered_timestamps, sched->nr_timestamps); 1499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_lost_events && sched->nr_events) { 1501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" INFO: %.3f%% lost events (%ld out of %ld, in %ld chunks)\n", 1502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->nr_lost_events/(double)sched->nr_events * 100.0, 1503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_lost_events, sched->nr_events, sched->nr_lost_chunks); 1504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_state_machine_bugs && sched->nr_timestamps) { 1506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" INFO: %.3f%% state machine bugs (%ld out of %ld)", 1507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->nr_state_machine_bugs/(double)sched->nr_timestamps*100.0, 1508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_state_machine_bugs, sched->nr_timestamps); 1509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_lost_events) 1510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" (due to lost events?)"); 1511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n"); 1512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_context_switch_bugs && sched->nr_timestamps) { 1514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" INFO: %.3f%% context switch bugs (%ld out of %ld)", 1515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->nr_context_switch_bugs/(double)sched->nr_timestamps*100.0, 1516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_context_switch_bugs, sched->nr_timestamps); 1517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_lost_events) 1518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" (due to lost events?)"); 1519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n"); 1520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__lat(struct perf_sched *sched) 1524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct rb_node *next; 1526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct perf_session *session; 1527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng setup_pager(); 1529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* save session -- references to threads are held in work_list */ 1531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_sched__read_events(sched, &session)) 1532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_sched__sort_lat(sched); 1535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n ---------------------------------------------------------------------------------------------------------------\n"); 1537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" Task | Runtime ms | Switches | Average delay ms | Maximum delay ms | Maximum delay at |\n"); 1538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" ---------------------------------------------------------------------------------------------------------------\n"); 1539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_first(&sched->sorted_atom_root); 1541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (next) { 1543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct work_atoms *work_list; 1544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng work_list = rb_entry(next, struct work_atoms, node); 1546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng output_lat_thread(sched, work_list); 1547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng next = rb_next(next); 1548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" -----------------------------------------------------------------------------------------\n"); 1551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", 1552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (double)sched->all_runtime / 1e6, sched->all_count); 1553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf(" ---------------------------------------------------\n"); 1555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng print_bad_events(sched); 1557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("\n"); 1558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng perf_session__delete(session); 1560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__map(struct perf_sched *sched) 1564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF); 1566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng setup_pager(); 1568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_sched__read_events(sched, NULL)) 1569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng print_bad_events(sched); 1571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1574e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int perf_sched__replay(struct perf_sched *sched) 1575e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1576e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned long i; 1577e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1578e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng calibrate_run_measurement_overhead(sched); 1579e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng calibrate_sleep_measurement_overhead(sched); 1580e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1581e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng test_calibrations(sched); 1582e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1583e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (perf_sched__read_events(sched, NULL)) 1584e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -1; 1585e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1586e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("nr_run_events: %ld\n", sched->nr_run_events); 1587e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("nr_sleep_events: %ld\n", sched->nr_sleep_events); 1588e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("nr_wakeup_events: %ld\n", sched->nr_wakeup_events); 1589e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1590e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->targetless_wakeups) 1591e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("target-less wakeups: %ld\n", sched->targetless_wakeups); 1592e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->multitarget_wakeups) 1593e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("multi-target wakeups: %ld\n", sched->multitarget_wakeups); 1594e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sched->nr_run_events_optimized) 1595e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("run atoms optimized: %ld\n", 1596e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched->nr_run_events_optimized); 1597e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1598e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng print_task_traces(sched); 1599e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng add_cross_task_wakeups(sched); 1600e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1601e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng create_tasks(sched); 1602e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printf("------------------------------------------------------------\n"); 1603e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < sched->replay_repeat; i++) 1604e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng run_one_test(sched); 1605e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1606e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1607e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1608e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1609e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void setup_sorting(struct perf_sched *sched, const struct option *options, 1610e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char * const usage_msg[]) 1611e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1612e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *tmp, *tok, *str = strdup(sched->sort_order); 1613e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1614e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (tok = strtok_r(str, ", ", &tmp); 1615e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng tok; tok = strtok_r(NULL, ", ", &tmp)) { 1616e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (sort_dimension__add(tok, &sched->sort_list) < 0) { 1617e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng error("Unknown --sort key: `%s'", tok); 1618e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng usage_with_options(usage_msg, options); 1619e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1620e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1621e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1622e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(str); 1623e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1624e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sort_dimension__add("pid", &sched->cmp_pid); 1625e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1626e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1627e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int __cmd_record(int argc, const char **argv) 1628e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1629e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng unsigned int rec_argc, i, j; 1630e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char **rec_argv; 1631e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char * const record_args[] = { 1632e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "record", 1633e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-a", 1634e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-R", 1635e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-m", "1024", 1636e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-c", "1", 1637e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_switch", 1638e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_stat_wait", 1639e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_stat_sleep", 1640e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_stat_iowait", 1641e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_stat_runtime", 1642e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_process_fork", 1643e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_wakeup", 1644e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "-e", "sched:sched_migrate_task", 1645e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1646e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1647e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rec_argc = ARRAY_SIZE(record_args) + argc - 1; 1648e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1649e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1650e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (rec_argv == NULL) 1651e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return -ENOMEM; 1652e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1653e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < ARRAY_SIZE(record_args); i++) 1654e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rec_argv[i] = strdup(record_args[i]); 1655e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1656e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (j = 1; j < (unsigned int)argc; j++, i++) 1657e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng rec_argv[i] = argv[j]; 1658e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1659e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng BUG_ON(i != rec_argc); 1660e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1661e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return cmd_record(i, rec_argv, NULL); 1662e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1663e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1664e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic const char default_sort_order[] = "avg, max, switch, runtime"; 1665e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct perf_sched sched = { 1666e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .tool = { 1667e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .sample = perf_sched__process_tracepoint_sample, 1668e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .comm = perf_event__process_comm, 1669e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .lost = perf_event__process_lost, 1670e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .fork = perf_sched__process_fork_event, 1671e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .ordered_samples = true, 1672e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }, 1673e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .cmp_pid = LIST_HEAD_INIT(sched.cmp_pid), 1674e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .sort_list = LIST_HEAD_INIT(sched.sort_list), 1675e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .start_work_mutex = PTHREAD_MUTEX_INITIALIZER, 1676e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .work_done_wait_mutex = PTHREAD_MUTEX_INITIALIZER, 1677e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .curr_pid = { [0 ... MAX_CPUS - 1] = -1 }, 1678e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .sort_order = default_sort_order, 1679e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .replay_repeat = 10, 1680e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .profile_cpu = -1, 1681e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .next_shortname1 = 'A', 1682e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .next_shortname2 = '0', 1683e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}; 1684e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1685e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) 1686e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 1687e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct option latency_options[] = { 1688e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_STRING('s', "sort", &sched.sort_order, "key[,key2...]", 1689e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "sort by key(s): runtime, switch, avg, max"), 1690e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_INCR('v', "verbose", &verbose, 1691e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "be more verbose (show symbol address, etc)"), 1692e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_INTEGER('C', "CPU", &sched.profile_cpu, 1693e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "CPU to profile on"), 1694e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1695e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "dump raw trace in ASCII"), 1696e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_END() 1697e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1698e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct option replay_options[] = { 1699e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_UINTEGER('r', "repeat", &sched.replay_repeat, 1700e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "repeat the workload replay N times (-1: infinite)"), 1701e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_INCR('v', "verbose", &verbose, 1702e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "be more verbose (show symbol address, etc)"), 1703e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1704e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "dump raw trace in ASCII"), 1705e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_END() 1706e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1707e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const struct option sched_options[] = { 1708e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_STRING('i', "input", &input_name, "file", 1709e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "input file name"), 1710e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_INCR('v', "verbose", &verbose, 1711e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "be more verbose (show symbol address, etc)"), 1712e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1713e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "dump raw trace in ASCII"), 1714e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng OPT_END() 1715e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1716e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char * const latency_usage[] = { 1717e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "perf sched latency [<options>]", 1718e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng NULL 1719e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1720e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char * const replay_usage[] = { 1721e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "perf sched replay [<options>]", 1722e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng NULL 1723e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1724e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng const char * const sched_usage[] = { 1725e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng "perf sched [<options>] {record|latency|map|replay|script}", 1726e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng NULL 1727e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1728e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct trace_sched_handler lat_ops = { 1729e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .wakeup_event = latency_wakeup_event, 1730e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .switch_event = latency_switch_event, 1731e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .runtime_event = latency_runtime_event, 1732e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .migrate_task_event = latency_migrate_task_event, 1733e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1734e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct trace_sched_handler map_ops = { 1735e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .switch_event = map_switch_event, 1736e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1737e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct trace_sched_handler replay_ops = { 1738e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .wakeup_event = replay_wakeup_event, 1739e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .switch_event = replay_switch_event, 1740e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng .fork_event = replay_fork_event, 1741e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng }; 1742e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1743e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng argc = parse_options(argc, argv, sched_options, sched_usage, 1744e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng PARSE_OPT_STOP_AT_NON_OPTION); 1745e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!argc) 1746e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng usage_with_options(sched_usage, sched_options); 1747e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1748e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* 1749e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng * Aliased to 'perf script' for now: 1750e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng */ 1751e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strcmp(argv[0], "script")) 1752e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return cmd_script(argc, argv, prefix); 1753e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1754e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng symbol__init(); 1755e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!strncmp(argv[0], "rec", 3)) { 1756e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return __cmd_record(argc, argv); 1757e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (!strncmp(argv[0], "lat", 3)) { 1758e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched.tp_handler = &lat_ops; 1759e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (argc > 1) { 1760e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng argc = parse_options(argc, argv, latency_options, latency_usage, 0); 1761e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (argc) 1762e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng usage_with_options(latency_usage, latency_options); 1763e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1764e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng setup_sorting(&sched, latency_options, latency_usage); 1765e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return perf_sched__lat(&sched); 1766e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (!strcmp(argv[0], "map")) { 1767e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched.tp_handler = &map_ops; 1768e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng setup_sorting(&sched, latency_options, latency_usage); 1769e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return perf_sched__map(&sched); 1770e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else if (!strncmp(argv[0], "rep", 3)) { 1771e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sched.tp_handler = &replay_ops; 1772e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (argc) { 1773e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng argc = parse_options(argc, argv, replay_options, replay_usage, 0); 1774e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (argc) 1775e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng usage_with_options(replay_usage, replay_options); 1776e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1777e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return perf_sched__replay(&sched); 1778e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } else { 1779e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng usage_with_options(sched_usage, sched_options); 1780e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 1781e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 1782e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 1783e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 1784