tunnels: fix netns vs proto registration ordering
[safe/jmp/linux-2.6] / kernel / trace / trace_sched_wakeup.c
index 43586b6..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,13 +24,17 @@ 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);
 
+static int save_lat_flag;
+
 #ifdef CONFIG_FUNCTION_TRACER
 /*
  * irqsoff uses its own tracer function to keep the overhead down:
@@ -53,33 +57,23 @@ wakeup_tracer_call(unsigned long ip, unsigned long parent_ip)
        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, data, ip, parent_ip, flags, pc);
+       trace_function(tr, ip, parent_ip, flags, pc);
 
- unlock:
-       __raw_spin_unlock(&wakeup_lock);
        local_irq_restore(flags);
 
  out:
        atomic_dec(&data->disabled);
-
+ out_enable:
        ftrace_preempt_enable(resched);
 }
 
@@ -104,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;
@@ -135,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);
@@ -145,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;
@@ -164,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);
@@ -182,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;
 
@@ -203,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, int success)
 {
+       struct trace_array_cpu *data;
        int cpu = smp_processor_id();
        unsigned long flags;
        long disabled;
@@ -224,7 +214,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success)
        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;
@@ -235,7 +225,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success)
                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)
@@ -245,6 +235,7 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success)
        __wakeup_reset(wakeup_trace);
 
        wakeup_cpu = task_cpu(p);
+       wakeup_current_cpu = wakeup_cpu;
        wakeup_prio = p->prio;
 
        wakeup_task = p;
@@ -252,22 +243,23 @@ probe_wakeup(struct rq *rq, struct task_struct *p, int success)
 
        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);
 }
 
-/*
- * save_tracer_enabled is used to save the state of the tracer_enabled
- * variable when we disable it when we open a trace output file.
- */
-static int save_tracer_enabled;
-
 static void start_wakeup_tracer(struct trace_array *tr)
 {
        int ret;
@@ -289,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);
 
        /*
@@ -306,13 +305,10 @@ static void start_wakeup_tracer(struct trace_array *tr)
 
        register_ftrace_function(&trace_ops);
 
-       if (tracing_is_enabled()) {
+       if (tracing_is_enabled())
                tracer_enabled = 1;
-               save_tracer_enabled = 1;
-       } else {
+       else
                tracer_enabled = 0;
-               save_tracer_enabled = 0;
-       }
 
        return;
 fail_deprobe_wake_new:
@@ -324,53 +320,55 @@ fail_deprobe:
 static void stop_wakeup_tracer(struct trace_array *tr)
 {
        tracer_enabled = 0;
-       save_tracer_enabled = 0;
        unregister_ftrace_function(&trace_ops);
        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 int 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;
 }
 
+static int wakeup_tracer_init(struct trace_array *tr)
+{
+       wakeup_rt = 0;
+       return __wakeup_tracer_init(tr);
+}
+
+static int wakeup_rt_tracer_init(struct trace_array *tr)
+{
+       wakeup_rt = 1;
+       return __wakeup_tracer_init(tr);
+}
+
 static void wakeup_tracer_reset(struct trace_array *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_start(struct trace_array *tr)
 {
        wakeup_reset(tr);
        tracer_enabled = 1;
-       save_tracer_enabled = 1;
 }
 
 static void wakeup_tracer_stop(struct trace_array *tr)
 {
        tracer_enabled = 0;
-       save_tracer_enabled = 0;
-}
-
-static void wakeup_tracer_open(struct trace_iterator *iter)
-{
-       /* stop the trace while dumping */
-       tracer_enabled = 0;
-}
-
-static void wakeup_tracer_close(struct trace_iterator *iter)
-{
-       /* forget about any processes we were recording */
-       if (save_tracer_enabled) {
-               wakeup_reset(iter->tr);
-               tracer_enabled = 1;
-       }
 }
 
 static struct tracer wakeup_tracer __read_mostly =
@@ -380,8 +378,20 @@ static struct tracer wakeup_tracer __read_mostly =
        .reset          = wakeup_tracer_reset,
        .start          = wakeup_tracer_start,
        .stop           = wakeup_tracer_stop,
-       .open           = wakeup_tracer_open,
-       .close          = wakeup_tracer_close,
+       .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,
@@ -396,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);