Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 2 : : /* 3 : : * trace context switch 4 : : * 5 : : * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com> 6 : : * 7 : : */ 8 : : #include <linux/module.h> 9 : : #include <linux/kallsyms.h> 10 : : #include <linux/uaccess.h> 11 : : #include <linux/ftrace.h> 12 : : #include <trace/events/sched.h> 13 : : 14 : : #include "trace.h" 15 : : 16 : : #define RECORD_CMDLINE 1 17 : : #define RECORD_TGID 2 18 : : 19 : : static int sched_cmdline_ref; 20 : : static int sched_tgid_ref; 21 : : static DEFINE_MUTEX(sched_register_mutex); 22 : : 23 : : static void 24 : 0 : probe_sched_switch(void *ignore, bool preempt, 25 : : struct task_struct *prev, struct task_struct *next) 26 : : { 27 : : int flags; 28 : : 29 : 0 : flags = (RECORD_TGID * !!sched_tgid_ref) + 30 : 0 : (RECORD_CMDLINE * !!sched_cmdline_ref); 31 : : 32 : 0 : if (!flags) 33 : 0 : return; 34 : 0 : tracing_record_taskinfo_sched_switch(prev, next, flags); 35 : : } 36 : : 37 : : static void 38 : 0 : probe_sched_wakeup(void *ignore, struct task_struct *wakee) 39 : : { 40 : : int flags; 41 : : 42 : 0 : flags = (RECORD_TGID * !!sched_tgid_ref) + 43 : 0 : (RECORD_CMDLINE * !!sched_cmdline_ref); 44 : : 45 : 0 : if (!flags) 46 : 0 : return; 47 : 0 : tracing_record_taskinfo(current, flags); 48 : : } 49 : : 50 : 0 : static int tracing_sched_register(void) 51 : : { 52 : : int ret; 53 : : 54 : : ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL); 55 : 0 : if (ret) { 56 : 0 : pr_info("wakeup trace: Couldn't activate tracepoint" 57 : : " probe to kernel_sched_wakeup\n"); 58 : 0 : return ret; 59 : : } 60 : : 61 : : ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 62 : 0 : if (ret) { 63 : 0 : pr_info("wakeup trace: Couldn't activate tracepoint" 64 : : " probe to kernel_sched_wakeup_new\n"); 65 : 0 : goto fail_deprobe; 66 : : } 67 : : 68 : : ret = register_trace_sched_switch(probe_sched_switch, NULL); 69 : 0 : if (ret) { 70 : 0 : pr_info("sched trace: Couldn't activate tracepoint" 71 : : " probe to kernel_sched_switch\n"); 72 : : goto fail_deprobe_wake_new; 73 : : } 74 : : 75 : : return ret; 76 : : fail_deprobe_wake_new: 77 : : unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 78 : : fail_deprobe: 79 : : unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 80 : 0 : return ret; 81 : : } 82 : : 83 : 0 : static void tracing_sched_unregister(void) 84 : : { 85 : : unregister_trace_sched_switch(probe_sched_switch, NULL); 86 : : unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 87 : : unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 88 : 0 : } 89 : : 90 : 0 : static void tracing_start_sched_switch(int ops) 91 : : { 92 : : bool sched_register; 93 : : 94 : 0 : mutex_lock(&sched_register_mutex); 95 : 0 : sched_register = (!sched_cmdline_ref && !sched_tgid_ref); 96 : : 97 : 0 : switch (ops) { 98 : : case RECORD_CMDLINE: 99 : 0 : sched_cmdline_ref++; 100 : 0 : break; 101 : : 102 : : case RECORD_TGID: 103 : 0 : sched_tgid_ref++; 104 : 0 : break; 105 : : } 106 : : 107 : 0 : if (sched_register && (sched_cmdline_ref || sched_tgid_ref)) 108 : 0 : tracing_sched_register(); 109 : 0 : mutex_unlock(&sched_register_mutex); 110 : 0 : } 111 : : 112 : 0 : static void tracing_stop_sched_switch(int ops) 113 : : { 114 : 0 : mutex_lock(&sched_register_mutex); 115 : : 116 : 0 : switch (ops) { 117 : : case RECORD_CMDLINE: 118 : 0 : sched_cmdline_ref--; 119 : 0 : break; 120 : : 121 : : case RECORD_TGID: 122 : 0 : sched_tgid_ref--; 123 : 0 : break; 124 : : } 125 : : 126 : 0 : if (!sched_cmdline_ref && !sched_tgid_ref) 127 : 0 : tracing_sched_unregister(); 128 : 0 : mutex_unlock(&sched_register_mutex); 129 : 0 : } 130 : : 131 : 0 : void tracing_start_cmdline_record(void) 132 : : { 133 : 0 : tracing_start_sched_switch(RECORD_CMDLINE); 134 : 0 : } 135 : : 136 : 0 : void tracing_stop_cmdline_record(void) 137 : : { 138 : 0 : tracing_stop_sched_switch(RECORD_CMDLINE); 139 : 0 : } 140 : : 141 : 0 : void tracing_start_tgid_record(void) 142 : : { 143 : 0 : tracing_start_sched_switch(RECORD_TGID); 144 : 0 : } 145 : : 146 : 0 : void tracing_stop_tgid_record(void) 147 : : { 148 : 0 : tracing_stop_sched_switch(RECORD_TGID); 149 : 0 : }