• Chuansheng Liu's avatar
    genirq: Remove racy waitqueue_active check · c685689f
    Chuansheng Liu authored
    We hit one rare case below:
    
    T1 calling disable_irq(), but hanging at synchronize_irq()
    always;
    The corresponding irq thread is in sleeping state;
    And all CPUs are in idle state;
    
    After analysis, we found there is one possible scenerio which
    causes T1 is waiting there forever:
    CPU0                                       CPU1
     synchronize_irq()
      wait_event()
        spin_lock()
                                               atomic_dec_and_test(&threads_active)
          insert the __wait into queue
        spin_unlock()
                                               if(waitqueue_active)
        atomic_read(&threads_active)
                                                 wake_up()
    
    Here after inserted the __wait into queue on CPU0, and before
    test if queue is empty on CPU1, there is no barrier, it maybe
    cause it is not visible for CPU1 immediately, although CPU0 has
    updated the queue list.
    It is similar for CPU0 atomic_read() threads_active also.
    
    So we'd need one smp_mb() before waitqueue_active.that, but removing
    the waitqueue_active() check solves it as wel l and it makes
    things simple and clear.
    Signed-off-by: default avatarChuansheng Liu <chuansheng.liu@intel.com>
    Cc: Xiaoming Wang <xiaoming.wang@intel.com>
    Link: http://lkml.kernel.org/r/1393212590-32543-1-git-send-email-chuansheng.liu@intel.com
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    c685689f
manage.c 43.4 KB