147 lines · 3.0 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * trace context switch * * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com> * */#include <linux/module.h>#include <linux/kallsyms.h>#include <linux/uaccess.h>#include <linux/ftrace.h>#include <trace/events/sched.h> #include "trace.h" #define RECORD_CMDLINE	1#define RECORD_TGID	2 static int		sched_cmdline_ref;static int		sched_tgid_ref;static DEFINE_MUTEX(sched_register_mutex); static voidprobe_sched_switch(void *ignore, bool preempt,		   struct task_struct *prev, struct task_struct *next){	int flags; 	flags = (RECORD_TGID * !!sched_tgid_ref) +		(RECORD_CMDLINE * !!sched_cmdline_ref); 	if (!flags)		return;	tracing_record_taskinfo_sched_switch(prev, next, flags);} static voidprobe_sched_wakeup(void *ignore, struct task_struct *wakee){	int flags; 	flags = (RECORD_TGID * !!sched_tgid_ref) +		(RECORD_CMDLINE * !!sched_cmdline_ref); 	if (!flags)		return;	tracing_record_taskinfo(current, flags);} static int tracing_sched_register(void){	int ret; 	ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);	if (ret) {		pr_info("wakeup trace: Couldn't activate tracepoint"			" probe to kernel_sched_wakeup\n");		return ret;	} 	ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);	if (ret) {		pr_info("wakeup trace: Couldn't activate tracepoint"			" probe to kernel_sched_wakeup_new\n");		goto fail_deprobe;	} 	ret = register_trace_sched_switch(probe_sched_switch, NULL);	if (ret) {		pr_info("sched trace: Couldn't activate tracepoint"			" probe to kernel_sched_switch\n");		goto fail_deprobe_wake_new;	} 	return ret;fail_deprobe_wake_new:	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);fail_deprobe:	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);	return ret;} static void tracing_sched_unregister(void){	unregister_trace_sched_switch(probe_sched_switch, NULL);	unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);	unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);} static void tracing_start_sched_switch(int ops){	bool sched_register = (!sched_cmdline_ref && !sched_tgid_ref);	mutex_lock(&sched_register_mutex); 	switch (ops) {	case RECORD_CMDLINE:		sched_cmdline_ref++;		break; 	case RECORD_TGID:		sched_tgid_ref++;		break;	} 	if (sched_register && (sched_cmdline_ref || sched_tgid_ref))		tracing_sched_register();	mutex_unlock(&sched_register_mutex);} static void tracing_stop_sched_switch(int ops){	mutex_lock(&sched_register_mutex); 	switch (ops) {	case RECORD_CMDLINE:		sched_cmdline_ref--;		break; 	case RECORD_TGID:		sched_tgid_ref--;		break;	} 	if (!sched_cmdline_ref && !sched_tgid_ref)		tracing_sched_unregister();	mutex_unlock(&sched_register_mutex);} void tracing_start_cmdline_record(void){	tracing_start_sched_switch(RECORD_CMDLINE);} void tracing_stop_cmdline_record(void){	tracing_stop_sched_switch(RECORD_CMDLINE);} void tracing_start_tgid_record(void){	tracing_start_sched_switch(RECORD_TGID);} void tracing_stop_tgid_record(void){	tracing_stop_sched_switch(RECORD_TGID);}