Skip to content
Snippets Groups Projects
  1. Nov 29, 2023
  2. Sep 18, 2023
    • Elliot Berman's avatar
      freezer,sched: Use saved_state to reduce some spurious wakeups · 8f0eed4a
      Elliot Berman authored and Ingo Molnar's avatar Ingo Molnar committed
      
      After commit f5d39b02 ("freezer,sched: Rewrite core freezer logic"),
      tasks that transition directly from TASK_FREEZABLE to TASK_FROZEN  are
      always woken up on the thaw path. Prior to that commit, tasks could ask
      freezer to consider them "frozen enough" via freezer_do_not_count(). The
      commit replaced freezer_do_not_count() with a TASK_FREEZABLE state which
      allows freezer to immediately mark the task as TASK_FROZEN without
      waking up the task.  This is efficient for the suspend path, but on the
      thaw path, the task is always woken up even if the task didn't need to
      wake up and goes back to its TASK_(UN)INTERRUPTIBLE state. Although
      these tasks are capable of handling of the wakeup, we can observe a
      power/perf impact from the extra wakeup.
      
      We observed on Android many tasks wait in the TASK_FREEZABLE state
      (particularly due to many of them being binder clients). We observed
      nearly 4x the number of tasks and a corresponding linear increase in
      latency and power consumption when thawing the system. The latency
      increased from ~15ms to ~50ms.
      
      Avoid the spurious wakeups by saving the state of TASK_FREEZABLE tasks.
      If the task was running before entering TASK_FROZEN state
      (__refrigerator()) or if the task received a wake up for the saved
      state, then the task is woken on thaw. saved_state from PREEMPT_RT locks
      can be re-used because freezer would not stomp on the rtlock wait flow:
      TASK_RTLOCK_WAIT isn't considered freezable.
      
      Reported-by: default avatarPrakash Viswalingam <quic_prakashv@quicinc.com>
      Signed-off-by: default avatarElliot Berman <quic_eberman@quicinc.com>
      Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
      Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
      8f0eed4a
  3. Sep 07, 2022
    • Peter Zijlstra's avatar
      freezer,sched: Rewrite core freezer logic · f5d39b02
      Peter Zijlstra authored
      
      Rewrite the core freezer to behave better wrt thawing and be simpler
      in general.
      
      By replacing PF_FROZEN with TASK_FROZEN, a special block state, it is
      ensured frozen tasks stay frozen until thawed and don't randomly wake
      up early, as is currently possible.
      
      As such, it does away with PF_FROZEN and PF_FREEZER_SKIP, freeing up
      two PF_flags (yay!).
      
      Specifically; the current scheme works a little like:
      
      	freezer_do_not_count();
      	schedule();
      	freezer_count();
      
      And either the task is blocked, or it lands in try_to_freezer()
      through freezer_count(). Now, when it is blocked, the freezer
      considers it frozen and continues.
      
      However, on thawing, once pm_freezing is cleared, freezer_count()
      stops working, and any random/spurious wakeup will let a task run
      before its time.
      
      That is, thawing tries to thaw things in explicit order; kernel
      threads and workqueues before doing bringing SMP back before userspace
      etc.. However due to the above mentioned races it is entirely possible
      for userspace tasks to thaw (by accident) before SMP is back.
      
      This can be a fatal problem in asymmetric ISA architectures (eg ARMv9)
      where the userspace task requires a special CPU to run.
      
      As said; replace this with a special task state TASK_FROZEN and add
      the following state transitions:
      
      	TASK_FREEZABLE	-> TASK_FROZEN
      	__TASK_STOPPED	-> TASK_FROZEN
      	__TASK_TRACED	-> TASK_FROZEN
      
      The new TASK_FREEZABLE can be set on any state part of TASK_NORMAL
      (IOW. TASK_INTERRUPTIBLE and TASK_UNINTERRUPTIBLE) -- any such state
      is already required to deal with spurious wakeups and the freezer
      causes one such when thawing the task (since the original state is
      lost).
      
      The special __TASK_{STOPPED,TRACED} states *can* be restored since
      their canonical state is in ->jobctl.
      
      With this, frozen tasks need an explicit TASK_FROZEN wakeup and are
      free of undue (early / spurious) wakeups.
      
      Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
      Reviewed-by: default avatarIngo Molnar <mingo@kernel.org>
      Acked-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
      Link: https://lore.kernel.org/r/20220822114649.055452969@infradead.org
      f5d39b02
  4. Jun 18, 2021
  5. Mar 27, 2021
  6. Mar 13, 2021
  7. Oct 06, 2019
  8. May 21, 2019
  9. Aug 06, 2018
  10. Jul 28, 2016
  11. Oct 21, 2014
  12. Dec 19, 2013
    • Tejun Heo's avatar
      libata, freezer: avoid block device removal while system is frozen · 85fbd722
      Tejun Heo authored
      
      Freezable kthreads and workqueues are fundamentally problematic in
      that they effectively introduce a big kernel lock widely used in the
      kernel and have already been the culprit of several deadlock
      scenarios.  This is the latest occurrence.
      
      During resume, libata rescans all the ports and revalidates all
      pre-existing devices.  If it determines that a device has gone
      missing, the device is removed from the system which involves
      invalidating block device and flushing bdi while holding driver core
      layer locks.  Unfortunately, this can race with the rest of device
      resume.  Because freezable kthreads and workqueues are thawed after
      device resume is complete and block device removal depends on
      freezable workqueues and kthreads (e.g. bdi_wq, jbd2) to make
      progress, this can lead to deadlock - block device removal can't
      proceed because kthreads are frozen and kthreads can't be thawed
      because device resume is blocked behind block device removal.
      
      839a8e86 ("writeback: replace custom worker pool implementation
      with unbound workqueue") made this particular deadlock scenario more
      visible but the underlying problem has always been there - the
      original forker task and jbd2 are freezable too.  In fact, this is
      highly likely just one of many possible deadlock scenarios given that
      freezer behaves as a big kernel lock and we don't have any debug
      mechanism around it.
      
      I believe the right thing to do is getting rid of freezable kthreads
      and workqueues.  This is something fundamentally broken.  For now,
      implement a funny workaround in libata - just avoid doing block device
      hot[un]plug while the system is frozen.  Kernel engineering at its
      finest.  :(
      
      v2: Add EXPORT_SYMBOL_GPL(pm_freezing) for cases where libata is built
          as a module.
      
      v3: Comment updated and polling interval changed to 10ms as suggested
          by Rafael.
      
      v4: Add #ifdef CONFIG_FREEZER around the hack as pm_freezing is not
          defined when FREEZER is not configured thus breaking build.
          Reported by kbuild test robot.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarTomaž Šolc <tomaz.solc@tablix.org>
      Reviewed-by: default avatar"Rafael J. Wysocki" <rjw@rjwysocki.net>
      Link: https://bugzilla.kernel.org/show_bug.cgi?id=62801
      Link: http://lkml.kernel.org/r/20131213174932.GA27070@htj.dyndns.org
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Len Brown <len.brown@intel.com>
      Cc: Oleg Nesterov <oleg@redhat.com>
      Cc: stable@vger.kernel.org
      Cc: kbuild test robot <fengguang.wu@intel.com>
      85fbd722
  13. Jul 30, 2013
    • Colin Cross's avatar
      freezer: set PF_SUSPEND_TASK flag on tasks that call freeze_processes · 2b44c4db
      Colin Cross authored
      
      Calling freeze_processes sets a global flag that will cause any
      process that calls try_to_freeze to enter the refrigerator.  It
      skips sending a signal to the current task, but if the current
      task ever hits try_to_freeze, all threads will be frozen and the
      system will deadlock.
      
      Set a new flag, PF_SUSPEND_TASK, on the task that calls
      freeze_processes.  The flag notifies the freezer that the thread
      is involved in suspend and should not be frozen.  Also add a
      WARN_ON in thaw_processes if the caller does not have the
      PF_SUSPEND_TASK flag set to catch if a different task calls
      thaw_processes than the one that called freeze_processes, leaving
      a task with PF_SUSPEND_TASK permanently set on it.
      
      Threads that spawn off a task with PF_SUSPEND_TASK set (which
      swsusp does) will also have PF_SUSPEND_TASK set, preventing them
      from freezing while they are helping with suspend, but they need
      to be dead by the time suspend is triggered, otherwise they may
      run when userspace is expected to be frozen.  Add a WARN_ON in
      thaw_processes if more than one thread has the PF_SUSPEND_TASK
      flag set.
      
      Reported-and-tested-by: default avatarMichael Leun <lkml20130126@newton.leun.net>
      Signed-off-by: default avatarColin Cross <ccross@android.com>
      Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
      2b44c4db
  14. May 12, 2013
    • Colin Cross's avatar
      freezer: skip waking up tasks with PF_FREEZER_SKIP set · 613f5d13
      Colin Cross authored
      
      Android goes through suspend/resume very often (every few seconds when
      on a busy wifi network with the screen off), and a significant portion
      of the energy used to go in and out of suspend is spent in the
      freezer.  If a task has called freezer_do_not_count(), don't bother
      waking it up.  If it happens to wake up later it will call
      freezer_count() and immediately enter the refrigerator.
      
      Combined with patches to convert freezable helpers to use
      freezer_do_not_count() and convert common sites where idle userspace
      tasks are blocked to use the freezable helpers, this reduces the
      time and energy required to suspend and resume.
      
      Acked-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarPavel Machek <pavel@ucw.cz>
      Signed-off-by: default avatarColin Cross <ccross@android.com>
      Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
      613f5d13
  15. Oct 26, 2012
    • Oleg Nesterov's avatar
      freezer: change ptrace_stop/do_signal_stop to use freezable_schedule() · 5d8f72b5
      Oleg Nesterov authored
      
      try_to_freeze_tasks() and cgroup_freezer rely on scheduler locks
      to ensure that a task doing STOPPED/TRACED -> RUNNING transition
      can't escape freezing. This mostly works, but ptrace_stop() does
      not necessarily call schedule(), it can change task->state back to
      RUNNING and check freezing() without any lock/barrier in between.
      
      We could add the necessary barrier, but this patch changes
      ptrace_stop() and do_signal_stop() to use freezable_schedule().
      This fixes the race, freezer_count() and freezer_should_skip()
      carefully avoid the race.
      
      And this simplifies the code, try_to_freeze_tasks/update_if_frozen
      no longer need to use task_is_stopped_or_traced() checks with the
      non trivial assumptions. We can rely on the mechanism which was
      specially designed to mark the sleeping task as "frozen enough".
      
      v2: As Tejun pointed out, we can also change get_signal_to_deliver()
      and move try_to_freeze() up before 'relock' label.
      
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      5d8f72b5
  16. Mar 04, 2012
  17. Nov 23, 2011
    • Tejun Heo's avatar
      freezer: kill unused set_freezable_with_signal() · 34b087e4
      Tejun Heo authored
      
      There's no in-kernel user of set_freezable_with_signal() left.  Mixing
      TIF_SIGPENDING with kernel threads can lead to nasty corner cases as
      kernel threads never travel signal delivery path on their own.
      
      e.g. the current implementation is buggy in the cancelation path of
      __thaw_task().  It calls recalc_sigpending_and_wake() in an attempt to
      clear TIF_SIGPENDING but the function never clears it regardless of
      sigpending state.  This means that signallable freezable kthreads may
      continue executing with !freezing() && stuck TIF_SIGPENDING, which can
      be troublesome.
      
      This patch removes set_freezable_with_signal() along with
      PF_FREEZER_NOSIG and recalc_sigpending*() calls in freezer.  User
      tasks get TIF_SIGPENDING, kernel tasks get woken up and the spurious
      sigpending is dealt with in the usual signal delivery path.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
      34b087e4
  18. Nov 21, 2011
    • Tejun Heo's avatar
      freezer: remove unused @sig_only from freeze_task() · 839e3407
      Tejun Heo authored
      
      After "freezer: make freezing() test freeze conditions in effect
      instead of TIF_FREEZE", freezing() returns authoritative answer on
      whether the current task should freeze or not and freeze_task()
      doesn't need or use @sig_only.  Remove it.
      
      While at it, rewrite function comment for freeze_task() and rename
      @sig_only to @user_only in try_to_freeze_tasks().
      
      This patch doesn't cause any functional change.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
      839e3407
    • Tejun Heo's avatar
      freezer: use lock_task_sighand() in fake_signal_wake_up() · 37ad8aca
      Tejun Heo authored
      
      cgroup_freezer calls freeze_task() without holding tasklist_lock and,
      if the task is exiting, its ->sighand may be gone by the time
      fake_signal_wake_up() is called.  Use lock_task_sighand() instead of
      accessing ->sighand directly.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
      Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
      Cc: Paul Menage <paul@paulmenage.org>
      37ad8aca
    • Tejun Heo's avatar
      freezer: restructure __refrigerator() · 5ece3eae
      Tejun Heo authored
      
      If another freeze happens before all tasks leave FROZEN state after
      being thawed, the freezer can see the existing FROZEN and consider the
      tasks to be frozen but they can clear FROZEN without checking the new
      freezing().
      
      Oleg suggested restructuring __refrigerator() such that there's single
      condition check section inside freezer_lock and sigpending is cleared
      afterwards, which fixes the problem and simplifies the code.
      Restructure accordingly.
      
      -v2: Frozen loop exited without releasing freezer_lock.  Fixed.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Reported-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
      Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
      5ece3eae
    • Tejun Heo's avatar
      freezer: fix set_freezable[_with_signal]() race · 96ee6d85
      Tejun Heo authored
      
      A kthread doing set_freezable*() may race with on-going PM freeze and
      the freezer might think all tasks are frozen while the new freezable
      kthread is merrily proceeding to execute code paths which aren't
      supposed to be executing during PM freeze.
      
      Reimplement set_freezable[_with_signal]() using __set_freezable() such
      that freezable PF flags are modified under freezer_lock and
      try_to_freeze() is called afterwards.  This eliminates race condition
      against freezing.
      
      Note: Separated out from larger patch to resolve fix order dependency
            Oleg pointed out.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Oleg Nesterov <oleg@redhat.com>
      96ee6d85
    • Tejun Heo's avatar
      freezer: remove should_send_signal() and update frozen() · 948246f7
      Tejun Heo authored
      
      should_send_signal() is only used in freezer.c.  Exporting them only
      increases chance of abuse.  Open code the two users and remove it.
      
      Update frozen() to return bool.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      948246f7
    • Tejun Heo's avatar
      freezer: make freezing() test freeze conditions in effect instead of TIF_FREEZE · a3201227
      Tejun Heo authored
      
      Using TIF_FREEZE for freezing worked when there was only single
      freezing condition (the PM one); however, now there is also the
      cgroup_freezer and single bit flag is getting clumsy.
      thaw_processes() is already testing whether cgroup freezing in in
      effect to avoid thawing tasks which were frozen by both PM and cgroup
      freezers.
      
      This is racy (nothing prevents race against cgroup freezing) and
      fragile.  A much simpler way is to test actual freeze conditions from
      freezing() - ie. directly test whether PM or cgroup freezing is in
      effect.
      
      This patch adds variables to indicate whether and what type of
      freezing conditions are in effect and reimplements freezing() such
      that it directly tests whether any of the two freezing conditions is
      active and the task should freeze.  On fast path, freezing() is still
      very cheap - it only tests system_freezing_cnt.
      
      This makes the clumsy dancing aroung TIF_FREEZE unnecessary and
      freeze/thaw operations more usual - updating state variables for the
      new state and nudging target tasks so that they notice the new state
      and comply.  As long as the nudging happens after state update, it's
      race-free.
      
      * This allows use of freezing() in freeze_task().  Replace the open
        coded tests with freezing().
      
      * p != current test is added to warning printing conditions in
        try_to_freeze_tasks() failure path.  This is necessary as freezing()
        is now true for the task which initiated freezing too.
      
      -v2: Oleg pointed out that re-freezing FROZEN cgroup could increment
           system_freezing_cnt.  Fixed.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: Paul Menage <paul@paulmenage.org>  (for the cgroup portions)
      a3201227
    • Tejun Heo's avatar
      freezer: clean up freeze_processes() failure path · 03afed8b
      Tejun Heo authored
      
      freeze_processes() failure path is rather messy.  Freezing is canceled
      for workqueues and tasks which aren't frozen yet but frozen tasks are
      left alone and should be thawed by the caller and of course some
      callers (xen and kexec) didn't do it.
      
      This patch updates __thaw_task() to handle cancelation correctly and
      makes freeze_processes() and freeze_kernel_threads() call
      thaw_processes() on failure instead so that the system is fully thawed
      on failure.  Unnecessary [suspend_]thaw_processes() calls are removed
      from kernel/power/hibernate.c, suspend.c and user.c.
      
      While at it, restructure error checking if clause in suspend_prepare()
      to be less weird.
      
      -v2: Srivatsa spotted missing removal of suspend_thaw_processes() in
           suspend_prepare() and error in commit message.  Updated.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarSrivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
      03afed8b
    • Tejun Heo's avatar
      freezer: kill PF_FREEZING · 376fede8
      Tejun Heo authored
      
      With the previous changes, there's no meaningful difference between
      PF_FREEZING and PF_FROZEN.  Remove PF_FREEZING and use PF_FROZEN
      instead in task_contributes_to_load().
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      376fede8
    • Tejun Heo's avatar
      freezer: test freezable conditions while holding freezer_lock · 85f1d476
      Tejun Heo authored
      
      try_to_freeze_tasks() and thaw_processes() use freezable() and
      frozen() as preliminary tests before initiating operations on a task.
      These are done without any synchronization and hinder with
      synchronization cleanup without any real performance benefits.
      
      In try_to_freeze_tasks(), open code self test and move PF_NOFREEZE and
      frozen() tests inside freezer_lock in freeze_task().
      
      thaw_processes() can simply drop freezable() test as frozen() test in
      __thaw_task() is enough.
      
      Note: This used to be a part of larger patch to fix set_freezable()
            race.  Separated out to satisfy ordering among dependent fixes.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Oleg Nesterov <oleg@redhat.com>
      85f1d476
    • Tejun Heo's avatar
      freezer: make freezing indicate freeze condition in effect · 6907483b
      Tejun Heo authored
      
      Currently freezing (TIF_FREEZE) and frozen (PF_FROZEN) states are
      interlocked - freezing is set to request freeze and when the task
      actually freezes, it clears freezing and sets frozen.
      
      This interlocking makes things more complex than necessary - freezing
      doesn't mean there's freezing condition in effect and frozen doesn't
      match the task actually entering and leaving frozen state (it's
      cleared by the thawing task).
      
      This patch makes freezing indicate that freeze condition is in effect.
      A task enters and stays frozen if freezing.  This makes PF_FROZEN
      manipulation done only by the task itself and prevents wakeup from
      __thaw_task() leaking outside of refrigerator.
      
      The only place which needs to tell freezing && !frozen is
      try_to_freeze_task() to whine about tasks which don't enter frozen.
      It's updated to test the condition explicitly.
      
      With the change, frozen() state my linger after __thaw_task() until
      the task wakes up and exits fridge.  This can trigger BUG_ON() in
      update_if_frozen().  Work it around by testing freezing() && frozen()
      instead of frozen().
      
      -v2: Oleg pointed out missing re-check of freezing() when trying to
           clear FROZEN and possible spurious BUG_ON() trigger in
           update_if_frozen().  Both fixed.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Oleg Nesterov <oleg@redhat.com>
      Cc: Paul Menage <paul@paulmenage.org>
      6907483b
    • Tejun Heo's avatar
      freezer: use dedicated lock instead of task_lock() + memory barrier · 0c9af092
      Tejun Heo authored
      
      Freezer synchronization is needlessly complicated - it's by no means a
      hot path and the priority is staying unintrusive and safe.  This patch
      makes it simply use a dedicated lock instead of piggy-backing on
      task_lock() and playing with memory barriers.
      
      On the failure path of try_to_freeze_tasks(), locking is moved from it
      to cancel_freezing().  This makes the frozen() test racy but the race
      here is a non-issue as the warning is printed for tasks which failed
      to enter frozen for 20 seconds and race on PF_FROZEN at the last
      moment doesn't change anything.
      
      This simplifies freezer implementation and eases further changes
      including some race fixes.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      0c9af092
    • Tejun Heo's avatar
      freezer: rename thaw_process() to __thaw_task() and simplify the implementation · a5be2d0d
      Tejun Heo authored
      
      thaw_process() now has only internal users - system and cgroup
      freezers.  Remove the unnecessary return value, rename, unexport and
      collapse __thaw_process() into it.  This will help further updates to
      the freezer code.
      
      -v3: oom_kill grew a use of thaw_process() while this patch was
           pending.  Convert it to use __thaw_task() for now.  In the longer
           term, this should be handled by allowing tasks to die if killed
           even if it's frozen.
      
      -v2: minor style update as suggested by Matt.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Paul Menage <menage@google.com>
      Cc: Matt Helsley <matthltc@us.ibm.com>
      a5be2d0d
    • Tejun Heo's avatar
      freezer: implement and use kthread_freezable_should_stop() · 8a32c441
      Tejun Heo authored
      
      Writeback and thinkpad_acpi have been using thaw_process() to prevent
      deadlock between the freezer and kthread_stop(); unfortunately, this
      is inherently racy - nothing prevents freezing from happening between
      thaw_process() and kthread_stop().
      
      This patch implements kthread_freezable_should_stop() which enters
      refrigerator if necessary but is guaranteed to return if
      kthread_stop() is invoked.  Both thaw_process() users are converted to
      use the new function.
      
      Note that this deadlock condition exists for many of freezable
      kthreads.  They need to be converted to use the new should_stop or
      freezable workqueue.
      
      Tested with synthetic test case.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Acked-by: default avatarHenrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
      Cc: Jens Axboe <axboe@kernel.dk>
      Cc: Oleg Nesterov <oleg@redhat.com>
      8a32c441
    • Tejun Heo's avatar
      freezer: unexport refrigerator() and update try_to_freeze() slightly · a0acae0e
      Tejun Heo authored
      
      There is no reason to export two functions for entering the
      refrigerator.  Calling refrigerator() instead of try_to_freeze()
      doesn't save anything noticeable or removes any race condition.
      
      * Rename refrigerator() to __refrigerator() and make it return bool
        indicating whether it scheduled out for freezing.
      
      * Update try_to_freeze() to return bool and relay the return value of
        __refrigerator() if freezing().
      
      * Convert all refrigerator() users to try_to_freeze().
      
      * Update documentation accordingly.
      
      * While at it, add might_sleep() to try_to_freeze().
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Cc: Samuel Ortiz <samuel@sortiz.org>
      Cc: Chris Mason <chris.mason@oracle.com>
      Cc: "Theodore Ts'o" <tytso@mit.edu>
      Cc: Steven Whitehouse <swhiteho@redhat.com>
      Cc: Andrew Morton <akpm@linux-foundation.org>
      Cc: Jan Kara <jack@suse.cz>
      Cc: KONISHI Ryusuke <konishi.ryusuke@lab.ntt.co.jp>
      Cc: Christoph Hellwig <hch@infradead.org>
      a0acae0e
    • Tejun Heo's avatar
      freezer: fix current->state restoration race in refrigerator() · 50fb4f7f
      Tejun Heo authored
      
      refrigerator() saves current->state before entering frozen state and
      restores it before returning using __set_current_state(); however,
      this is racy, for example, please consider the following sequence.
      
      	set_current_state(TASK_INTERRUPTIBLE);
      	try_to_freeze();
      	if (kthread_should_stop())
      		break;
      	schedule();
      
      If kthread_stop() races with ->state restoration, the restoration can
      restore ->state to TASK_INTERRUPTIBLE after kthread_stop() sets it to
      TASK_RUNNING but kthread_should_stop() may still see zero
      ->should_stop because there's no memory barrier between restoring
      TASK_INTERRUPTIBLE and kthread_should_stop() test.
      
      This isn't restricted to kthread_should_stop().  current->state is
      often used in memory barrier based synchronization and silently
      restoring it w/o mb breaks them.
      
      Use set_current_state() instead.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      50fb4f7f
  19. Nov 04, 2011
    • Tejun Heo's avatar
      PM / Freezer: Revert 27920651 "PM / Freezer: Make fake_signal_wake_up() wake... · d6cc7685
      Tejun Heo authored
      PM / Freezer: Revert 27920651 "PM / Freezer: Make fake_signal_wake_up() wake TASK_KILLABLE tasks too"
      
      Commit 27920651 "PM / Freezer: Make fake_signal_wake_up() wake
      TASK_KILLABLE tasks too" updated fake_signal_wake_up() used by freezer
      to wake up KILLABLE tasks.  Sending unsolicited wakeups to tasks in
      killable sleep is dangerous as there are code paths which depend on
      tasks not waking up spuriously from KILLABLE sleep.
      
      For example. sys_read() or page can sleep in TASK_KILLABLE assuming
      that wait/down/whatever _killable can only fail if we can not return
      to the usermode.  TASK_TRACED is another obvious example.
      
      The previous patch updated wait_event_freezekillable() such that it
      doesn't depend on the spurious wakeup.  This patch reverts the
      offending commit.
      
      Note that the spurious KILLABLE wakeup had other implicit effects in
      KILLABLE sleeps in nfs and cifs and those will need further updates to
      regain freezekillable behavior.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
      d6cc7685
  20. Oct 31, 2011
  21. Oct 16, 2011
    • Jeff Layton's avatar
      PM / Freezer: Make fake_signal_wake_up() wake TASK_KILLABLE tasks too · 27920651
      Jeff Layton authored
      
      TASK_KILLABLE is often used to put tasks to sleep for quite some time.
      One of the most common uses is to put tasks to sleep while waiting for
      replies from a server on a networked filesystem (such as CIFS or NFS).
      
      Unfortunately, fake_signal_wake_up does not currently wake up tasks
      that are sleeping in TASK_KILLABLE state. This means that even if the
      code were in place to allow them to freeze while in this sleep, it
      wouldn't work anyway.
      
      This patch changes this function to wake tasks in this state as well.
      This should be harmless -- if the code doing the sleeping doesn't have
      handling to deal with freezer events, it should just go back to sleep.
      If it does, then this will allow that code to do the right thing.
      
      Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
      Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
      27920651
  22. May 17, 2011
  23. Dec 24, 2010
    • Tejun Heo's avatar
      Freezer: Fix a race during freezing of TASK_STOPPED tasks · 8cfe400c
      Tejun Heo authored
      
      After calling freeze_task(), try_to_freeze_tasks() see whether the
      task is stopped or traced and if so, considers it to be frozen;
      however, nothing guarantees that either the task being frozen sees
      TIF_FREEZE or the freezer sees TASK_STOPPED -> TASK_RUNNING
      transition.  The task being frozen may wake up and not see TIF_FREEZE
      while the freezer fails to notice the transition and believes the task
      is still stopped.
      
      This patch fixes the race by making freeze_task() always go through
      fake_signal_wake_up() for applicable tasks.  The function goes through
      the target task's scheduler lock and thus guarantees that either the
      target sees TIF_FREEZE or try_to_freeze_task() sees TASK_RUNNING.
      
      Signed-off-by: default avatarTejun Heo <tj@kernel.org>
      Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
      8cfe400c
  24. Jul 18, 2009
    • Thomas Gleixner's avatar
      sched: fix nr_uninterruptible accounting of frozen tasks really · 6301cb95
      Thomas Gleixner authored
      
      commit e3c8ca83 (sched: do not count frozen tasks toward load) broke
      the nr_uninterruptible accounting on freeze/thaw. On freeze the task
      is excluded from accounting with a check for (task->flags &
      PF_FROZEN), but that flag is cleared before the task is thawed. So
      while we prevent that the task with state TASK_UNINTERRUPTIBLE
      is accounted to nr_uninterruptible on freeze we decrement
      nr_uninterruptible on thaw.
      
      Use a separate flag which is handled by the freezing task itself. Set
      it before calling the scheduler with TASK_UNINTERRUPTIBLE state and
      clear it after we return from frozen state.
      
      Cc: <stable@kernel.org>
      Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
      6301cb95
Loading