• S
    Kick CPUS that might be sleeping in cpus_idle_wait · 40d6a146
    Steven Rostedt 提交于
    Sometimes cpu_idle_wait gets stuck because it might miss CPUS that are
    already in idle, have no tasks waiting to run and have no interrupts going
    to them.  This is common on bootup when switching cpu idle governors.
    
    This patch gives those CPUS that don't check in an IPI kick.
    
     Background:
     -----------
    I notice this while developing the mcount patches, that every once in a
    while the system would hang. Looking deeper, the hang was always at boot
    up when registering init_menu of the cpu_idle menu governor. Talking
    with Thomas Gliexner, we discovered that one of the CPUS had no timer
    events scheduled for it and it was in idle (running with NO_HZ). So the
    CPU would not set the cpu_idle_state bit.
    
    Hitting sysrq-t a few times would eventually route the interrupt to the
    stuck CPU and the system would continue.
    
    Note, I would have used the PDA isidle but that is set after the
    cpu_idle_state bit is cleared, and would leave a window open where we
    may miss being kicked.
    
    hmm, looking closer at this, we still have a small race window between
    clearing the cpu_idle_state and disabling interrupts (hence the RFC).
    
        CPU0:                          CPU 1:
      ---------                       ---------
     cpu_idle_wait():                 cpu_idle():
          |                           __cpu_cpu_var(is_idle) = 1;
          |                           if (__get_cpu_var(cpu_idle_state)) /* == 0 */
     per_cpu(cpu_idle_state, 1) = 1;         |
     if (per_cpu(is_idle, 1)) /* == 1 */     |
     smp_call_function(1)                    |
          |                             receives ipi and runs do_nothing.
     wait on map == empty               idle();
       /* waits forever */
    
    So really we need interrupts off for most of this then. One might think
    that we could simply clear the cpu_idle_state from do_nothing, but I'm
    assuming that cpu_idle governors can be removed, and this might cause a
    race that a governor might be used after the module was removed.
    
    Venki said:
    
      I think your RFC patch is the right solution here.  As I see it, there is
      no race with your RFC patch.  As long as you call a dummy smp_call_function
      on all CPUs, we should be OK.  We can get rid of cpu_idle_state and the
      current wait forever logic altogether with dummy smp_call_function.  And so
      there wont be any wait forever scenario.
    
      The whole point of cpu_idle_wait() is to make all CPUs come out of idle
      loop atleast once.  The caller will use cpu_idle_wait something like this.
    
      // Want to change idle handler
    
      - Switch global idle handler to always present default_idle
    
      - call cpu_idle_wait so that all cpus come out of idle for an instant
        and stop using old idle pointer and start using default idle
    
      - Change the idle handler to a new handler
    
      - optional cpu_idle_wait if you want all cpus to start using the new
        handler immediately.
    
    Maybe the below 1s patch is safe bet for .24.  But for .25, I would say we
    just replace all complicated logic by simple dummy smp_call_function and
    remove cpu_idle_state altogether.
    Signed-off-by: NSteven Rostedt <srostedt@redhat.com>
    Cc: Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
    Acked-by: NIngo Molnar <mingo@elte.hu>
    Acked-by: NThomas Gleixner <tglx@linutronix.de>
    Cc: Andi Kleen <ak@suse.de>
    Cc: Len Brown <lenb@kernel.org>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    40d6a146
process_32.c 23.9 KB