/* * trace context switch * * Copyright (C) 2007 Steven Rostedt * */ #include #include #include #include #include #include "trace.h" static int sched_ref; static DEFINE_MUTEX(sched_register_mutex); static void probe_sched_switch(void *ignore, 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, int success) { 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(); }