135e8e302SSteven Rostedt /* 235e8e302SSteven Rostedt * trace context switch 335e8e302SSteven Rostedt * 435e8e302SSteven Rostedt * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com> 535e8e302SSteven Rostedt * 635e8e302SSteven Rostedt */ 735e8e302SSteven Rostedt #include <linux/module.h> 835e8e302SSteven Rostedt #include <linux/kallsyms.h> 935e8e302SSteven Rostedt #include <linux/uaccess.h> 1035e8e302SSteven Rostedt #include <linux/ftrace.h> 11ad8d75ffSSteven Rostedt #include <trace/events/sched.h> 1235e8e302SSteven Rostedt 1335e8e302SSteven Rostedt #include "trace.h" 1435e8e302SSteven Rostedt 15d914ba37SJoel Fernandes #define RECORD_CMDLINE 1 16d914ba37SJoel Fernandes #define RECORD_TGID 2 17d914ba37SJoel Fernandes 18d914ba37SJoel Fernandes static int sched_cmdline_ref; 19d914ba37SJoel Fernandes static int sched_tgid_ref; 20efade6e7SFrederic Weisbecker static DEFINE_MUTEX(sched_register_mutex); 2182e04af4SFrederic Weisbecker 22e309b41dSIngo Molnar static void 23c73464b1SPeter Zijlstra probe_sched_switch(void *ignore, bool preempt, 24c73464b1SPeter Zijlstra struct task_struct *prev, struct task_struct *next) 2535e8e302SSteven Rostedt { 26d914ba37SJoel Fernandes int flags; 27b07c3f19SMathieu Desnoyers 28d914ba37SJoel Fernandes flags = (RECORD_TGID * !!sched_tgid_ref) + 29d914ba37SJoel Fernandes (RECORD_CMDLINE * !!sched_cmdline_ref); 30d914ba37SJoel Fernandes 31d914ba37SJoel Fernandes if (!flags) 32d914ba37SJoel Fernandes return; 33d914ba37SJoel Fernandes tracing_record_taskinfo_sched_switch(prev, next, flags); 3435e8e302SSteven Rostedt } 3535e8e302SSteven Rostedt 365b82a1b0SMathieu Desnoyers static void 37fbd705a0SPeter Zijlstra probe_sched_wakeup(void *ignore, struct task_struct *wakee) 385b82a1b0SMathieu Desnoyers { 39d914ba37SJoel Fernandes int flags; 40dcef788eSZhaolei 41d914ba37SJoel Fernandes flags = (RECORD_TGID * !!sched_tgid_ref) + 42d914ba37SJoel Fernandes (RECORD_CMDLINE * !!sched_cmdline_ref); 43d914ba37SJoel Fernandes 44d914ba37SJoel Fernandes if (!flags) 45d914ba37SJoel Fernandes return; 46d914ba37SJoel Fernandes tracing_record_taskinfo(current, flags); 4757422797SIngo Molnar } 4857422797SIngo Molnar 495b82a1b0SMathieu Desnoyers static int tracing_sched_register(void) 505b82a1b0SMathieu Desnoyers { 515b82a1b0SMathieu Desnoyers int ret; 525b82a1b0SMathieu Desnoyers 5338516ab5SSteven Rostedt ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL); 545b82a1b0SMathieu Desnoyers if (ret) { 55b07c3f19SMathieu Desnoyers pr_info("wakeup trace: Couldn't activate tracepoint" 565b82a1b0SMathieu Desnoyers " probe to kernel_sched_wakeup\n"); 575b82a1b0SMathieu Desnoyers return ret; 585b82a1b0SMathieu Desnoyers } 595b82a1b0SMathieu Desnoyers 6038516ab5SSteven Rostedt ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 615b82a1b0SMathieu Desnoyers if (ret) { 62b07c3f19SMathieu Desnoyers pr_info("wakeup trace: Couldn't activate tracepoint" 635b82a1b0SMathieu Desnoyers " probe to kernel_sched_wakeup_new\n"); 645b82a1b0SMathieu Desnoyers goto fail_deprobe; 655b82a1b0SMathieu Desnoyers } 665b82a1b0SMathieu Desnoyers 6738516ab5SSteven Rostedt ret = register_trace_sched_switch(probe_sched_switch, NULL); 685b82a1b0SMathieu Desnoyers if (ret) { 69b07c3f19SMathieu Desnoyers pr_info("sched trace: Couldn't activate tracepoint" 7073d8b8bcSWenji Huang " probe to kernel_sched_switch\n"); 715b82a1b0SMathieu Desnoyers goto fail_deprobe_wake_new; 725b82a1b0SMathieu Desnoyers } 735b82a1b0SMathieu Desnoyers 745b82a1b0SMathieu Desnoyers return ret; 755b82a1b0SMathieu Desnoyers fail_deprobe_wake_new: 7638516ab5SSteven Rostedt unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 775b82a1b0SMathieu Desnoyers fail_deprobe: 7838516ab5SSteven Rostedt unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 795b82a1b0SMathieu Desnoyers return ret; 805b82a1b0SMathieu Desnoyers } 815b82a1b0SMathieu Desnoyers 825b82a1b0SMathieu Desnoyers static void tracing_sched_unregister(void) 835b82a1b0SMathieu Desnoyers { 8438516ab5SSteven Rostedt unregister_trace_sched_switch(probe_sched_switch, NULL); 8538516ab5SSteven Rostedt unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 8638516ab5SSteven Rostedt unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 875b82a1b0SMathieu Desnoyers } 885b82a1b0SMathieu Desnoyers 89d914ba37SJoel Fernandes static void tracing_start_sched_switch(int ops) 905b82a1b0SMathieu Desnoyers { 91d914ba37SJoel Fernandes bool sched_register = (!sched_cmdline_ref && !sched_tgid_ref); 92efade6e7SFrederic Weisbecker mutex_lock(&sched_register_mutex); 93d914ba37SJoel Fernandes 94d914ba37SJoel Fernandes switch (ops) { 95d914ba37SJoel Fernandes case RECORD_CMDLINE: 96d914ba37SJoel Fernandes sched_cmdline_ref++; 97d914ba37SJoel Fernandes break; 98d914ba37SJoel Fernandes 99d914ba37SJoel Fernandes case RECORD_TGID: 100d914ba37SJoel Fernandes sched_tgid_ref++; 101d914ba37SJoel Fernandes break; 102d914ba37SJoel Fernandes } 103d914ba37SJoel Fernandes 104d914ba37SJoel Fernandes if (sched_register && (sched_cmdline_ref || sched_tgid_ref)) 1055b82a1b0SMathieu Desnoyers tracing_sched_register(); 106efade6e7SFrederic Weisbecker mutex_unlock(&sched_register_mutex); 1075b82a1b0SMathieu Desnoyers } 1085b82a1b0SMathieu Desnoyers 109d914ba37SJoel Fernandes static void tracing_stop_sched_switch(int ops) 1105b82a1b0SMathieu Desnoyers { 111efade6e7SFrederic Weisbecker mutex_lock(&sched_register_mutex); 112d914ba37SJoel Fernandes 113d914ba37SJoel Fernandes switch (ops) { 114d914ba37SJoel Fernandes case RECORD_CMDLINE: 115d914ba37SJoel Fernandes sched_cmdline_ref--; 116d914ba37SJoel Fernandes break; 117d914ba37SJoel Fernandes 118d914ba37SJoel Fernandes case RECORD_TGID: 119d914ba37SJoel Fernandes sched_tgid_ref--; 120d914ba37SJoel Fernandes break; 121d914ba37SJoel Fernandes } 122d914ba37SJoel Fernandes 123d914ba37SJoel Fernandes if (!sched_cmdline_ref && !sched_tgid_ref) 1245b82a1b0SMathieu Desnoyers tracing_sched_unregister(); 125efade6e7SFrederic Weisbecker mutex_unlock(&sched_register_mutex); 1265b82a1b0SMathieu Desnoyers } 1275b82a1b0SMathieu Desnoyers 12841bc8144SSteven Rostedt void tracing_start_cmdline_record(void) 12941bc8144SSteven Rostedt { 130d914ba37SJoel Fernandes tracing_start_sched_switch(RECORD_CMDLINE); 13141bc8144SSteven Rostedt } 13241bc8144SSteven Rostedt 13341bc8144SSteven Rostedt void tracing_stop_cmdline_record(void) 13441bc8144SSteven Rostedt { 135d914ba37SJoel Fernandes tracing_stop_sched_switch(RECORD_CMDLINE); 136d914ba37SJoel Fernandes } 137d914ba37SJoel Fernandes 138d914ba37SJoel Fernandes void tracing_start_tgid_record(void) 139d914ba37SJoel Fernandes { 140d914ba37SJoel Fernandes tracing_start_sched_switch(RECORD_TGID); 141d914ba37SJoel Fernandes } 142d914ba37SJoel Fernandes 143d914ba37SJoel Fernandes void tracing_stop_tgid_record(void) 144d914ba37SJoel Fernandes { 145d914ba37SJoel Fernandes tracing_stop_sched_switch(RECORD_TGID); 14641bc8144SSteven Rostedt } 147