sysctl extern cleanup: module
[safe/jmp/linux-2.6] / kernel / trace / trace_sched_wakeup.c
index fe4a252..0271742 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
 #include <linux/ftrace.h>
-#include <trace/sched.h>
+#include <trace/events/sched.h>
 
 #include "trace.h"
 
@@ -24,14 +24,18 @@ static int __read_mostly    tracer_enabled;
 
 static struct task_struct      *wakeup_task;
 static int                     wakeup_cpu;
+static int                     wakeup_current_cpu;
 static unsigned                        wakeup_prio = -1;
+static int                     wakeup_rt;
 
-static raw_spinlock_t wakeup_lock =
-       (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+static arch_spinlock_t wakeup_lock =
+       (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
 
 static void __wakeup_reset(struct trace_array *tr);
 
-#ifdef CONFIG_FTRACE
+static int save_lat_flag;
+
+#ifdef CONFIG_FUNCTION_TRACER
 /*
  * irqsoff uses its own tracer function to keep the overhead down:
  */
@@ -50,53 +54,34 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
                return;
 
        pc = preempt_count();
-       resched = need_resched();
-       preempt_disable_notrace();
+       resched = ftrace_preempt_disable();
 
        cpu = raw_smp_processor_id();
+       if (cpu != wakeup_current_cpu)
+               goto out_enable;
+
        data = tr->data[cpu];
        disabled = atomic_inc_return(&data->disabled);
        if (unlikely(disabled != 1))
                goto out;
 
        local_irq_save(flags);
-       __raw_spin_lock(&wakeup_lock);
-
-       if (unlikely(!wakeup_task))
-               goto unlock;
 
-       /*
-        * The task can't disappear because it needs to
-        * wake up first, and we have the wakeup_lock.
-        */
-       if (task_cpu(wakeup_task) != cpu)
-               goto unlock;
+       trace_function(tr, ip, parent_ip, flags, pc);
 
-       trace_function(tr, data, ip, parent_ip, flags, pc);
-
- unlock:
-       __raw_spin_unlock(&wakeup_lock);
        local_irq_restore(flags);
 
  out:
        atomic_dec(&data->disabled);
-
-       /*
-        * To prevent recursion from the scheduler, if the
-        * resched flag was set before we entered, then
-        * don't reschedule.
-        */
-       if (resched)
-               preempt_enable_no_resched_notrace();
-       else
-               preempt_enable_notrace();
+ out_enable:
+       ftrace_preempt_enable(resched);
 }
 
 static struct ftrace_ops trace_ops __read_mostly =
 {
        .func = wakeup_tracer_call,
 };
-#endif /* CONFIG_FTRACE */
+#endif /* CONFIG_FUNCTION_TRACER */
 
 /*
  * Should this new latency be reported/recorded?
@@ -113,11 +98,18 @@ static int report_latency(cycle_t delta)
        return 1;
 }
 
+static void probe_wakeup_migrate_task(struct task_struct *task, int cpu)
+{
+       if (task != wakeup_task)
+               return;
+
+       wakeup_current_cpu = cpu;
+}
+
 static void notrace
 probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
        struct task_struct *next)
 {
-       unsigned long latency = 0, t0 = 0, t1 = 0;
        struct trace_array_cpu *data;
        cycle_t T0, T1, delta;
        unsigned long flags;
@@ -144,9 +136,6 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
 
        pc = preempt_count();
 
-       /* The task we are waiting for is waking up */
-       data = wakeup_trace->data[wakeup_cpu];
-
        /* disable local data, not wakeup_cpu data */
        cpu = raw_smp_processor_id();
        disabled = atomic_inc_return(&wakeup_trace->data[cpu]->disabled);
@@ -154,18 +143,18 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
                goto out;
 
        local_irq_save(flags);
-       __raw_spin_lock(&wakeup_lock);
+       arch_spin_lock(&wakeup_lock);
 
        /* We could race with grabbing wakeup_lock */
        if (unlikely(!tracer_enabled || next != wakeup_task))
                goto out_unlock;
 
-       trace_function(wakeup_trace, data, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
+       /* The task we are waiting for is waking up */
+       data = wakeup_trace->data[wakeup_cpu];
+
+       trace_function(wakeup_trace, CALLER_ADDR0, CALLER_ADDR1, flags, pc);
+       tracing_sched_switch_trace(wakeup_trace, prev, next, flags, pc);
 
-       /*
-        * usecs conversion is slow so we try to delay the conversion
-        * as long as possible:
-        */
        T0 = data->preempt_timestamp;
        T1 = ftrace_now(cpu);
        delta = T1-T0;
@@ -173,17 +162,14 @@ probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
        if (!report_latency(delta))
                goto out_unlock;
 
-       latency = nsecs_to_usecs(delta);
-
-       tracing_max_latency = delta;
-       t0 = nsecs_to_usecs(T0);
-       t1 = nsecs_to_usecs(T1);
-
-       update_max_tr(wakeup_trace, wakeup_task, wakeup_cpu);
+       if (likely(!is_tracing_stopped())) {
+               tracing_max_latency = delta;
+               update_max_tr(wakeup_trace, wakeup_task, wakeup_cpu);
+       }
 
 out_unlock:
        __wakeup_reset(wakeup_trace);
-       __raw_spin_unlock(&wakeup_lock);
+       arch_spin_unlock(&wakeup_lock);
        local_irq_restore(flags);
 out:
        atomic_dec(&wakeup_trace->data[cpu]->disabled);
@@ -191,14 +177,6 @@ out:
 
 static void __wakeup_reset(struct trace_array *tr)
 {
-       struct trace_array_cpu *data;
-       int cpu;
-
-       for_each_possible_cpu(cpu) {
-               data = tr->data[cpu];
-               tracing_reset(tr, cpu);
-       }
-
        wakeup_cpu = -1;
        wakeup_prio = -1;
 
@@ -212,16 +190,19 @@ static void wakeup_reset(struct trace_array *tr)
 {
        unsigned long flags;
 
+       tracing_reset_online_cpus(tr);
+
        local_irq_save(flags);
-       __raw_spin_lock(&wakeup_lock);
+       arch_spin_lock(&wakeup_lock);
        __wakeup_reset(tr);
-       __raw_spin_unlock(&wakeup_lock);
+       arch_spin_unlock(&wakeup_lock);
        local_irq_restore(flags);
 }
 
 static void
-probe_wakeup(struct rq *rq, struct task_struct *p)
+probe_wakeup(struct rq *rq, struct task_struct *p, int success)
 {
+       struct trace_array_cpu *data;
        int cpu = smp_processor_id();
        unsigned long flags;
        long disabled;
@@ -233,7 +214,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p)
        tracing_record_cmdline(p);
        tracing_record_cmdline(current);
 
-       if (likely(!rt_task(p)) ||
+       if ((wakeup_rt && !rt_task(p)) ||
                        p->prio >= wakeup_prio ||
                        p->prio >= current->prio)
                return;
@@ -244,7 +225,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p)
                goto out;
 
        /* interrupts should be off from try_to_wake_up */
-       __raw_spin_lock(&wakeup_lock);
+       arch_spin_lock(&wakeup_lock);
 
        /* check for races. */
        if (!tracer_enabled || p->prio >= wakeup_prio)
@@ -254,6 +235,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p)
        __wakeup_reset(wakeup_trace);
 
        wakeup_cpu = task_cpu(p);
+       wakeup_current_cpu = wakeup_cpu;
        wakeup_prio = p->prio;
 
        wakeup_task = p;
@@ -261,12 +243,19 @@ probe_wakeup(struct rq *rq, struct task_struct *p)
 
        local_save_flags(flags);
 
-       wakeup_trace->data[wakeup_cpu]->preempt_timestamp = ftrace_now(cpu);
-       trace_function(wakeup_trace, wakeup_trace->data[wakeup_cpu],
-                      CALLER_ADDR1, CALLER_ADDR2, flags, pc);
+       data = wakeup_trace->data[wakeup_cpu];
+       data->preempt_timestamp = ftrace_now(cpu);
+       tracing_sched_wakeup_trace(wakeup_trace, p, current, flags, pc);
+
+       /*
+        * We must be careful in using CALLER_ADDR2. But since wake_up
+        * is not called by an assembly function  (where as schedule is)
+        * it should be safe to use it here.
+        */
+       trace_function(wakeup_trace, CALLER_ADDR1, CALLER_ADDR2, flags, pc);
 
 out_locked:
-       __raw_spin_unlock(&wakeup_lock);
+       arch_spin_unlock(&wakeup_lock);
 out:
        atomic_dec(&wakeup_trace->data[cpu]->disabled);
 }
@@ -292,10 +281,17 @@ static void start_wakeup_tracer(struct trace_array *tr)
        ret = register_trace_sched_switch(probe_wakeup_sched_switch);
        if (ret) {
                pr_info("sched trace: Couldn't activate tracepoint"
-                       " probe to kernel_sched_schedule\n");
+                       " probe to kernel_sched_switch\n");
                goto fail_deprobe_wake_new;
        }
 
+       ret = register_trace_sched_migrate_task(probe_wakeup_migrate_task);
+       if (ret) {
+               pr_info("wakeup trace: Couldn't activate tracepoint"
+                       " probe to kernel_sched_migrate_task\n");
+               return;
+       }
+
        wakeup_reset(tr);
 
        /*
@@ -309,7 +305,10 @@ static void start_wakeup_tracer(struct trace_array *tr)
 
        register_ftrace_function(&trace_ops);
 
-       tracer_enabled = 1;
+       if (tracing_is_enabled())
+               tracer_enabled = 1;
+       else
+               tracer_enabled = 0;
 
        return;
 fail_deprobe_wake_new:
@@ -325,45 +324,51 @@ static void stop_wakeup_tracer(struct trace_array *tr)
        unregister_trace_sched_switch(probe_wakeup_sched_switch);
        unregister_trace_sched_wakeup_new(probe_wakeup);
        unregister_trace_sched_wakeup(probe_wakeup);
+       unregister_trace_sched_migrate_task(probe_wakeup_migrate_task);
 }
 
-static void wakeup_tracer_init(struct trace_array *tr)
+static int __wakeup_tracer_init(struct trace_array *tr)
 {
+       save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
+       trace_flags |= TRACE_ITER_LATENCY_FMT;
+
+       tracing_max_latency = 0;
        wakeup_trace = tr;
+       start_wakeup_tracer(tr);
+       return 0;
+}
 
-       if (tr->ctrl)
-               start_wakeup_tracer(tr);
+static int wakeup_tracer_init(struct trace_array *tr)
+{
+       wakeup_rt = 0;
+       return __wakeup_tracer_init(tr);
 }
 
-static void wakeup_tracer_reset(struct trace_array *tr)
+static int wakeup_rt_tracer_init(struct trace_array *tr)
 {
-       if (tr->ctrl) {
-               stop_wakeup_tracer(tr);
-               /* make sure we put back any tasks we are tracing */
-               wakeup_reset(tr);
-       }
+       wakeup_rt = 1;
+       return __wakeup_tracer_init(tr);
 }
 
-static void wakeup_tracer_ctrl_update(struct trace_array *tr)
+static void wakeup_tracer_reset(struct trace_array *tr)
 {
-       if (tr->ctrl)
-               start_wakeup_tracer(tr);
-       else
-               stop_wakeup_tracer(tr);
+       stop_wakeup_tracer(tr);
+       /* make sure we put back any tasks we are tracing */
+       wakeup_reset(tr);
+
+       if (!save_lat_flag)
+               trace_flags &= ~TRACE_ITER_LATENCY_FMT;
 }
 
-static void wakeup_tracer_open(struct trace_iterator *iter)
+static void wakeup_tracer_start(struct trace_array *tr)
 {
-       /* stop the trace while dumping */
-       if (iter->tr->ctrl)
-               stop_wakeup_tracer(iter->tr);
+       wakeup_reset(tr);
+       tracer_enabled = 1;
 }
 
-static void wakeup_tracer_close(struct trace_iterator *iter)
+static void wakeup_tracer_stop(struct trace_array *tr)
 {
-       /* forget about any processes we were recording */
-       if (iter->tr->ctrl)
-               start_wakeup_tracer(iter->tr);
+       tracer_enabled = 0;
 }
 
 static struct tracer wakeup_tracer __read_mostly =
@@ -371,9 +376,22 @@ static struct tracer wakeup_tracer __read_mostly =
        .name           = "wakeup",
        .init           = wakeup_tracer_init,
        .reset          = wakeup_tracer_reset,
-       .open           = wakeup_tracer_open,
-       .close          = wakeup_tracer_close,
-       .ctrl_update    = wakeup_tracer_ctrl_update,
+       .start          = wakeup_tracer_start,
+       .stop           = wakeup_tracer_stop,
+       .print_max      = 1,
+#ifdef CONFIG_FTRACE_SELFTEST
+       .selftest    = trace_selftest_startup_wakeup,
+#endif
+};
+
+static struct tracer wakeup_rt_tracer __read_mostly =
+{
+       .name           = "wakeup_rt",
+       .init           = wakeup_rt_tracer_init,
+       .reset          = wakeup_tracer_reset,
+       .start          = wakeup_tracer_start,
+       .stop           = wakeup_tracer_stop,
+       .wait_pipe      = poll_wait_pipe,
        .print_max      = 1,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_wakeup,
@@ -388,6 +406,10 @@ __init static int init_wakeup_tracer(void)
        if (ret)
                return ret;
 
+       ret = register_tracer(&wakeup_rt_tracer);
+       if (ret)
+               return ret;
+
        return 0;
 }
 device_initcall(init_wakeup_tracer);