trace_sched_switch.c (3180B)
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 19static int sched_cmdline_ref; 20static int sched_tgid_ref; 21static DEFINE_MUTEX(sched_register_mutex); 22 23static void 24probe_sched_switch(void *ignore, bool preempt, 25 struct task_struct *prev, struct task_struct *next, 26 unsigned int prev_state) 27{ 28 int flags; 29 30 flags = (RECORD_TGID * !!sched_tgid_ref) + 31 (RECORD_CMDLINE * !!sched_cmdline_ref); 32 33 if (!flags) 34 return; 35 tracing_record_taskinfo_sched_switch(prev, next, flags); 36} 37 38static void 39probe_sched_wakeup(void *ignore, struct task_struct *wakee) 40{ 41 int flags; 42 43 flags = (RECORD_TGID * !!sched_tgid_ref) + 44 (RECORD_CMDLINE * !!sched_cmdline_ref); 45 46 if (!flags) 47 return; 48 tracing_record_taskinfo_sched_switch(current, wakee, flags); 49} 50 51static int tracing_sched_register(void) 52{ 53 int ret; 54 55 ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL); 56 if (ret) { 57 pr_info("wakeup trace: Couldn't activate tracepoint" 58 " probe to kernel_sched_wakeup\n"); 59 return ret; 60 } 61 62 ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 63 if (ret) { 64 pr_info("wakeup trace: Couldn't activate tracepoint" 65 " probe to kernel_sched_wakeup_new\n"); 66 goto fail_deprobe; 67 } 68 69 ret = register_trace_sched_switch(probe_sched_switch, NULL); 70 if (ret) { 71 pr_info("sched trace: Couldn't activate tracepoint" 72 " probe to kernel_sched_switch\n"); 73 goto fail_deprobe_wake_new; 74 } 75 76 return ret; 77fail_deprobe_wake_new: 78 unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 79fail_deprobe: 80 unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 81 return ret; 82} 83 84static void tracing_sched_unregister(void) 85{ 86 unregister_trace_sched_switch(probe_sched_switch, NULL); 87 unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); 88 unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); 89} 90 91static void tracing_start_sched_switch(int ops) 92{ 93 bool sched_register; 94 95 mutex_lock(&sched_register_mutex); 96 sched_register = (!sched_cmdline_ref && !sched_tgid_ref); 97 98 switch (ops) { 99 case RECORD_CMDLINE: 100 sched_cmdline_ref++; 101 break; 102 103 case RECORD_TGID: 104 sched_tgid_ref++; 105 break; 106 } 107 108 if (sched_register && (sched_cmdline_ref || sched_tgid_ref)) 109 tracing_sched_register(); 110 mutex_unlock(&sched_register_mutex); 111} 112 113static void tracing_stop_sched_switch(int ops) 114{ 115 mutex_lock(&sched_register_mutex); 116 117 switch (ops) { 118 case RECORD_CMDLINE: 119 sched_cmdline_ref--; 120 break; 121 122 case RECORD_TGID: 123 sched_tgid_ref--; 124 break; 125 } 126 127 if (!sched_cmdline_ref && !sched_tgid_ref) 128 tracing_sched_unregister(); 129 mutex_unlock(&sched_register_mutex); 130} 131 132void tracing_start_cmdline_record(void) 133{ 134 tracing_start_sched_switch(RECORD_CMDLINE); 135} 136 137void tracing_stop_cmdline_record(void) 138{ 139 tracing_stop_sched_switch(RECORD_CMDLINE); 140} 141 142void tracing_start_tgid_record(void) 143{ 144 tracing_start_sched_switch(RECORD_TGID); 145} 146 147void tracing_stop_tgid_record(void) 148{ 149 tracing_stop_sched_switch(RECORD_TGID); 150}