| /* | |
| * 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" | |
| static int sched_ref; | |
| static DEFINE_MUTEX(sched_register_mutex); | |
| static void | |
| probe_sched_switch(void *ignore, bool preempt, | |
| struct task_struct *prev, struct task_struct *next) | |
| { | |
| if (unlikely(!sched_ref)) | |
| return; | |
| tracing_record_cmdline(prev); | |
| tracing_record_cmdline(next); | |
| } | |
| static void | |
| probe_sched_wakeup(void *ignore, struct task_struct *wakee) | |
| { | |
| if (unlikely(!sched_ref)) | |
| return; | |
| tracing_record_cmdline(current); | |
| } | |
| 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(void) | |
| { | |
| mutex_lock(&sched_register_mutex); | |
| if (!(sched_ref++)) | |
| tracing_sched_register(); | |
| mutex_unlock(&sched_register_mutex); | |
| } | |
| static void tracing_stop_sched_switch(void) | |
| { | |
| mutex_lock(&sched_register_mutex); | |
| if (!(--sched_ref)) | |
| tracing_sched_unregister(); | |
| mutex_unlock(&sched_register_mutex); | |
| } | |
| void tracing_start_cmdline_record(void) | |
| { | |
| tracing_start_sched_switch(); | |
| } | |
| void tracing_stop_cmdline_record(void) | |
| { | |
| tracing_stop_sched_switch(); | |
| } |