1. 04 6月, 2010 2 次提交
    • S
      tracing: Remove ftrace_preempt_disable/enable · 5168ae50
      Steven Rostedt 提交于
      The ftrace_preempt_disable/enable functions were to address a
      recursive race caused by the function tracer. The function tracer
      traces all functions which makes it easily susceptible to recursion.
      One area was preempt_enable(). This would call the scheduler and
      the schedulre would call the function tracer and loop.
      (So was it thought).
      
      The ftrace_preempt_disable/enable was made to protect against recursion
      inside the scheduler by storing the NEED_RESCHED flag. If it was
      set before the ftrace_preempt_disable() it would not call schedule
      on ftrace_preempt_enable(), thinking that if it was set before then
      it would have already scheduled unless it was already in the scheduler.
      
      This worked fine except in the case of SMP, where another task would set
      the NEED_RESCHED flag for a task on another CPU, and then kick off an
      IPI to trigger it. This could cause the NEED_RESCHED to be saved at
      ftrace_preempt_disable() but the IPI to arrive in the the preempt
      disabled section. The ftrace_preempt_enable() would not call the scheduler
      because the flag was already set before entring the section.
      
      This bug would cause a missed preemption check and cause lower latencies.
      
      Investigating further, I found that the recusion caused by the function
      tracer was not due to schedule(), but due to preempt_schedule(). Now
      that preempt_schedule is completely annotated with notrace, the recusion
      no longer is an issue.
      Reported-by: NThomas Gleixner <tglx@linutronix.de>
      Signed-off-by: NSteven Rostedt <rostedt@goodmis.org>
      5168ae50
    • S
      tracing/sched: Make preempt_schedule() notrace · d1f74e20
      Steven Rostedt 提交于
      The function tracer code uses ftrace_preempt_disable() to disable
      preemption instead of normal preempt_disable(). But there's a slight
      race condition that may cause it to lose a preemption check.
      
      This was made to keep the function tracer from recursing on itself
      by disabling preemption then having the enable call the function tracer
      again, causing infinite recursion.
      
      The bug was assumed to happen if the call was just in schedule, but
      this is incorrect. The bug is caused by preempt_schedule() which
      is called by preempt_enable(). The calling of preempt_enable() when
      NEED_RESCHED was set would call preempt_schedule() which would call
      the function tracer again.
      
      By making the preempt_schedule() and add_preempt_count() notrace
      then this will prevent the inifinite recursion. This is because
      the add_preempt_count() would stop the preempt_enable() in the
      function tracer from calling preempt_schedule() again.
      
      The sub_preempt_count() is also made notrace just to keep it
      symmetric.
      Signed-off-by: NSteven Rostedt <rostedt@goodmis.org>
      d1f74e20
  2. 28 5月, 2010 38 次提交