• P
    kthread, sched/wait: Fix kthread_parkme() completion issue · 85f1abe0
    Peter Zijlstra 提交于
    Even with the wait-loop fixed, there is a further issue with
    kthread_parkme(). Upon hotplug, when we do takedown_cpu(),
    smpboot_park_threads() can return before all those threads are in fact
    blocked, due to the placement of the complete() in __kthread_parkme().
    
    When that happens, sched_cpu_dying() -> migrate_tasks() can end up
    migrating such a still runnable task onto another CPU.
    
    Normally the task will have hit schedule() and gone to sleep by the
    time we do kthread_unpark(), which will then do __kthread_bind() to
    re-bind the task to the correct CPU.
    
    However, when we loose the initial TASK_PARKED store to the concurrent
    wakeup issue described previously, do the complete(), get migrated, it
    is possible to either:
    
     - observe kthread_unpark()'s clearing of SHOULD_PARK and terminate
       the park and set TASK_RUNNING, or
    
     - __kthread_bind()'s wait_task_inactive() to observe the competing
       TASK_RUNNING store.
    
    Either way the WARN() in __kthread_bind() will trigger and fail to
    correctly set the CPU affinity.
    
    Fix this by only issuing the complete() when the kthread has scheduled
    out. This does away with all the icky 'still running' nonsense.
    
    The alternative is to promote TASK_PARKED to a special state, this
    guarantees wait_task_inactive() cannot observe a 'stale' TASK_RUNNING
    and we'll end up doing the right thing, but this preserves the whole
    icky business of potentially migating the still runnable thing.
    Reported-by: NGaurav Kohli <gkohli@codeaurora.org>
    Signed-off-by: NPeter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Oleg Nesterov <oleg@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: NIngo Molnar <mingo@kernel.org>
    85f1abe0
kthread.h 6.6 KB