Skip to content
  • Linus Torvalds's avatar
    sched: don't cause task state changes in nested sleep debugging · 00845eb9
    Linus Torvalds authored
    Commit 8eb23b9f
    
     ("sched: Debug nested sleeps") added code to report
    on nested sleep conditions, which we generally want to avoid because the
    inner sleeping operation can re-set the thread state to TASK_RUNNING,
    but that will then cause the outer sleep loop not actually sleep when it
    calls schedule.
    
    However, that's actually valid traditional behavior, with the inner
    sleep being some fairly rare case (like taking a sleeping lock that
    normally doesn't actually need to sleep).
    
    And the debug code would actually change the state of the task to
    TASK_RUNNING internally, which makes that kind of traditional and
    working code not work at all, because now the nested sleep doesn't just
    sometimes cause the outer one to not block, but will cause it to happen
    every time.
    
    In particular, it will cause the cardbus kernel daemon (pccardd) to
    basically busy-loop doing scheduling, converting a laptop into a heater,
    as reported by Bruno Prémont.  But there may be other legacy uses of
    that nested sleep model in other drivers that are also likely to never
    get converted to the new model.
    
    This fixes both cases:
    
     - don't set TASK_RUNNING when the nested condition happens (note: even
       if WARN_ONCE() only _warns_ once, the return value isn't whether the
       warning happened, but whether the condition for the warning was true.
       So despite the warning only happening once, the "if (WARN_ON(..))"
       would trigger for every nested sleep.
    
     - in the cases where we knowingly disable the warning by using
       "sched_annotate_sleep()", don't change the task state (that is used
       for all core scheduling decisions), instead use '->task_state_change'
       that is used for the debugging decision itself.
    
    (Credit for the second part of the fix goes to Oleg Nesterov: "Can't we
    avoid this subtle change in behaviour DEBUG_ATOMIC_SLEEP adds?" with the
    suggested change to use 'task_state_change' as part of the test)
    
    Reported-and-bisected-by: default avatarBruno Prémont <bonbons@linux-vserver.org>
    Tested-by: default avatarRafael J Wysocki <rjw@rjwysocki.net>
    Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>,
    Cc: Ilya Dryomov <ilya.dryomov@inktank.com>,
    Cc: Mike Galbraith <umgwanakikbuti@gmail.com>
    Cc: Ingo Molnar <mingo@kernel.org>
    Cc: Peter Hurley <peter@hurleysoftware.com>,
    Cc: Davidlohr Bueso <dave@stgolabs.net>,
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    00845eb9