1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
235e8e302SSteven Rostedt /*
335e8e302SSteven Rostedt  * trace context switch
435e8e302SSteven Rostedt  *
535e8e302SSteven Rostedt  * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
635e8e302SSteven Rostedt  *
735e8e302SSteven Rostedt  */
835e8e302SSteven Rostedt #include <linux/module.h>
935e8e302SSteven Rostedt #include <linux/kallsyms.h>
1035e8e302SSteven Rostedt #include <linux/uaccess.h>
1135e8e302SSteven Rostedt #include <linux/ftrace.h>
12ad8d75ffSSteven Rostedt #include <trace/events/sched.h>
1335e8e302SSteven Rostedt 
1435e8e302SSteven Rostedt #include "trace.h"
1535e8e302SSteven Rostedt 
16d914ba37SJoel Fernandes #define RECORD_CMDLINE	1
17d914ba37SJoel Fernandes #define RECORD_TGID	2
18d914ba37SJoel Fernandes 
19d914ba37SJoel Fernandes static int		sched_cmdline_ref;
20d914ba37SJoel Fernandes static int		sched_tgid_ref;
21efade6e7SFrederic Weisbecker static DEFINE_MUTEX(sched_register_mutex);
2282e04af4SFrederic Weisbecker 
23e309b41dSIngo Molnar static void
24c73464b1SPeter Zijlstra probe_sched_switch(void *ignore, bool preempt,
25c73464b1SPeter Zijlstra 		   struct task_struct *prev, struct task_struct *next)
2635e8e302SSteven Rostedt {
27d914ba37SJoel Fernandes 	int flags;
28b07c3f19SMathieu Desnoyers 
29d914ba37SJoel Fernandes 	flags = (RECORD_TGID * !!sched_tgid_ref) +
30d914ba37SJoel Fernandes 		(RECORD_CMDLINE * !!sched_cmdline_ref);
31d914ba37SJoel Fernandes 
32d914ba37SJoel Fernandes 	if (!flags)
33d914ba37SJoel Fernandes 		return;
34d914ba37SJoel Fernandes 	tracing_record_taskinfo_sched_switch(prev, next, flags);
3535e8e302SSteven Rostedt }
3635e8e302SSteven Rostedt 
375b82a1b0SMathieu Desnoyers static void
38fbd705a0SPeter Zijlstra probe_sched_wakeup(void *ignore, struct task_struct *wakee)
395b82a1b0SMathieu Desnoyers {
40d914ba37SJoel Fernandes 	int flags;
41dcef788eSZhaolei 
42d914ba37SJoel Fernandes 	flags = (RECORD_TGID * !!sched_tgid_ref) +
43d914ba37SJoel Fernandes 		(RECORD_CMDLINE * !!sched_cmdline_ref);
44d914ba37SJoel Fernandes 
45d914ba37SJoel Fernandes 	if (!flags)
46d914ba37SJoel Fernandes 		return;
47*55bc8384SSteven Rostedt (Google) 	tracing_record_taskinfo_sched_switch(current, wakee, flags);
4857422797SIngo Molnar }
4957422797SIngo Molnar 
505b82a1b0SMathieu Desnoyers static int tracing_sched_register(void)
515b82a1b0SMathieu Desnoyers {
525b82a1b0SMathieu Desnoyers 	int ret;
535b82a1b0SMathieu Desnoyers 
5438516ab5SSteven Rostedt 	ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
555b82a1b0SMathieu Desnoyers 	if (ret) {
56b07c3f19SMathieu Desnoyers 		pr_info("wakeup trace: Couldn't activate tracepoint"
575b82a1b0SMathieu Desnoyers 			" probe to kernel_sched_wakeup\n");
585b82a1b0SMathieu Desnoyers 		return ret;
595b82a1b0SMathieu Desnoyers 	}
605b82a1b0SMathieu Desnoyers 
6138516ab5SSteven Rostedt 	ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
625b82a1b0SMathieu Desnoyers 	if (ret) {
63b07c3f19SMathieu Desnoyers 		pr_info("wakeup trace: Couldn't activate tracepoint"
645b82a1b0SMathieu Desnoyers 			" probe to kernel_sched_wakeup_new\n");
655b82a1b0SMathieu Desnoyers 		goto fail_deprobe;
665b82a1b0SMathieu Desnoyers 	}
675b82a1b0SMathieu Desnoyers 
6838516ab5SSteven Rostedt 	ret = register_trace_sched_switch(probe_sched_switch, NULL);
695b82a1b0SMathieu Desnoyers 	if (ret) {
70b07c3f19SMathieu Desnoyers 		pr_info("sched trace: Couldn't activate tracepoint"
7173d8b8bcSWenji Huang 			" probe to kernel_sched_switch\n");
725b82a1b0SMathieu Desnoyers 		goto fail_deprobe_wake_new;
735b82a1b0SMathieu Desnoyers 	}
745b82a1b0SMathieu Desnoyers 
755b82a1b0SMathieu Desnoyers 	return ret;
765b82a1b0SMathieu Desnoyers fail_deprobe_wake_new:
7738516ab5SSteven Rostedt 	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
785b82a1b0SMathieu Desnoyers fail_deprobe:
7938516ab5SSteven Rostedt 	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
805b82a1b0SMathieu Desnoyers 	return ret;
815b82a1b0SMathieu Desnoyers }
825b82a1b0SMathieu Desnoyers 
835b82a1b0SMathieu Desnoyers static void tracing_sched_unregister(void)
845b82a1b0SMathieu Desnoyers {
8538516ab5SSteven Rostedt 	unregister_trace_sched_switch(probe_sched_switch, NULL);
8638516ab5SSteven Rostedt 	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
8738516ab5SSteven Rostedt 	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
885b82a1b0SMathieu Desnoyers }
895b82a1b0SMathieu Desnoyers 
90d914ba37SJoel Fernandes static void tracing_start_sched_switch(int ops)
915b82a1b0SMathieu Desnoyers {
9264ae572bSMathieu Desnoyers 	bool sched_register;
9364ae572bSMathieu Desnoyers 
94efade6e7SFrederic Weisbecker 	mutex_lock(&sched_register_mutex);
9564ae572bSMathieu Desnoyers 	sched_register = (!sched_cmdline_ref && !sched_tgid_ref);
96d914ba37SJoel Fernandes 
97d914ba37SJoel Fernandes 	switch (ops) {
98d914ba37SJoel Fernandes 	case RECORD_CMDLINE:
99d914ba37SJoel Fernandes 		sched_cmdline_ref++;
100d914ba37SJoel Fernandes 		break;
101d914ba37SJoel Fernandes 
102d914ba37SJoel Fernandes 	case RECORD_TGID:
103d914ba37SJoel Fernandes 		sched_tgid_ref++;
104d914ba37SJoel Fernandes 		break;
105d914ba37SJoel Fernandes 	}
106d914ba37SJoel Fernandes 
107d914ba37SJoel Fernandes 	if (sched_register && (sched_cmdline_ref || sched_tgid_ref))
1085b82a1b0SMathieu Desnoyers 		tracing_sched_register();
109efade6e7SFrederic Weisbecker 	mutex_unlock(&sched_register_mutex);
1105b82a1b0SMathieu Desnoyers }
1115b82a1b0SMathieu Desnoyers 
112d914ba37SJoel Fernandes static void tracing_stop_sched_switch(int ops)
1135b82a1b0SMathieu Desnoyers {
114efade6e7SFrederic Weisbecker 	mutex_lock(&sched_register_mutex);
115d914ba37SJoel Fernandes 
116d914ba37SJoel Fernandes 	switch (ops) {
117d914ba37SJoel Fernandes 	case RECORD_CMDLINE:
118d914ba37SJoel Fernandes 		sched_cmdline_ref--;
119d914ba37SJoel Fernandes 		break;
120d914ba37SJoel Fernandes 
121d914ba37SJoel Fernandes 	case RECORD_TGID:
122d914ba37SJoel Fernandes 		sched_tgid_ref--;
123d914ba37SJoel Fernandes 		break;
124d914ba37SJoel Fernandes 	}
125d914ba37SJoel Fernandes 
126d914ba37SJoel Fernandes 	if (!sched_cmdline_ref && !sched_tgid_ref)
1275b82a1b0SMathieu Desnoyers 		tracing_sched_unregister();
128efade6e7SFrederic Weisbecker 	mutex_unlock(&sched_register_mutex);
1295b82a1b0SMathieu Desnoyers }
1305b82a1b0SMathieu Desnoyers 
13141bc8144SSteven Rostedt void tracing_start_cmdline_record(void)
13241bc8144SSteven Rostedt {
133d914ba37SJoel Fernandes 	tracing_start_sched_switch(RECORD_CMDLINE);
13441bc8144SSteven Rostedt }
13541bc8144SSteven Rostedt 
13641bc8144SSteven Rostedt void tracing_stop_cmdline_record(void)
13741bc8144SSteven Rostedt {
138d914ba37SJoel Fernandes 	tracing_stop_sched_switch(RECORD_CMDLINE);
139d914ba37SJoel Fernandes }
140d914ba37SJoel Fernandes 
141d914ba37SJoel Fernandes void tracing_start_tgid_record(void)
142d914ba37SJoel Fernandes {
143d914ba37SJoel Fernandes 	tracing_start_sched_switch(RECORD_TGID);
144d914ba37SJoel Fernandes }
145d914ba37SJoel Fernandes 
146d914ba37SJoel Fernandes void tracing_stop_tgid_record(void)
147d914ba37SJoel Fernandes {
148d914ba37SJoel Fernandes 	tracing_stop_sched_switch(RECORD_TGID);
14941bc8144SSteven Rostedt }
150