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