1 /*
2  * trace context switch
3  *
4  * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
5  *
6  */
7 #include <linux/module.h>
8 #include <linux/fs.h>
9 #include <linux/debugfs.h>
10 #include <linux/kallsyms.h>
11 #include <linux/uaccess.h>
12 #include <linux/ftrace.h>
13 #include <trace/events/sched.h>
14 
15 #include "trace.h"
16 
17 static int			sched_ref;
18 static DEFINE_MUTEX(sched_register_mutex);
19 
20 static void
21 probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *next)
22 {
23 	if (unlikely(!sched_ref))
24 		return;
25 
26 	tracing_record_cmdline(prev);
27 	tracing_record_cmdline(next);
28 }
29 
30 static void
31 probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success)
32 {
33 	if (unlikely(!sched_ref))
34 		return;
35 
36 	tracing_record_cmdline(current);
37 }
38 
39 static int tracing_sched_register(void)
40 {
41 	int ret;
42 
43 	ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
44 	if (ret) {
45 		pr_info("wakeup trace: Couldn't activate tracepoint"
46 			" probe to kernel_sched_wakeup\n");
47 		return ret;
48 	}
49 
50 	ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
51 	if (ret) {
52 		pr_info("wakeup trace: Couldn't activate tracepoint"
53 			" probe to kernel_sched_wakeup_new\n");
54 		goto fail_deprobe;
55 	}
56 
57 	ret = register_trace_sched_switch(probe_sched_switch, NULL);
58 	if (ret) {
59 		pr_info("sched trace: Couldn't activate tracepoint"
60 			" probe to kernel_sched_switch\n");
61 		goto fail_deprobe_wake_new;
62 	}
63 
64 	return ret;
65 fail_deprobe_wake_new:
66 	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
67 fail_deprobe:
68 	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
69 	return ret;
70 }
71 
72 static void tracing_sched_unregister(void)
73 {
74 	unregister_trace_sched_switch(probe_sched_switch, NULL);
75 	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
76 	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
77 }
78 
79 static void tracing_start_sched_switch(void)
80 {
81 	mutex_lock(&sched_register_mutex);
82 	if (!(sched_ref++))
83 		tracing_sched_register();
84 	mutex_unlock(&sched_register_mutex);
85 }
86 
87 static void tracing_stop_sched_switch(void)
88 {
89 	mutex_lock(&sched_register_mutex);
90 	if (!(--sched_ref))
91 		tracing_sched_unregister();
92 	mutex_unlock(&sched_register_mutex);
93 }
94 
95 void tracing_start_cmdline_record(void)
96 {
97 	tracing_start_sched_switch();
98 }
99 
100 void tracing_stop_cmdline_record(void)
101 {
102 	tracing_stop_sched_switch();
103 }
104