linux/kernel/freezer.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * kernel/freezer.c - Function to freeze a process
   4 *
   5 * Originally from kernel/power/process.c
   6 */
   7
   8#include <linux/interrupt.h>
   9#include <linux/suspend.h>
  10#include <linux/export.h>
  11#include <linux/syscalls.h>
  12#include <linux/freezer.h>
  13#include <linux/kthread.h>
  14
  15/* total number of freezing conditions in effect */
  16atomic_t system_freezing_cnt = ATOMIC_INIT(0);
  17EXPORT_SYMBOL(system_freezing_cnt);
  18
  19/* indicate whether PM freezing is in effect, protected by
  20 * system_transition_mutex
  21 */
  22bool pm_freezing;
  23bool pm_nosig_freezing;
  24
  25/*
  26 * Temporary export for the deadlock workaround in ata_scsi_hotplug().
  27 * Remove once the hack becomes unnecessary.
  28 */
  29EXPORT_SYMBOL_GPL(pm_freezing);
  30
  31/* protects freezing and frozen transitions */
  32static DEFINE_SPINLOCK(freezer_lock);
  33
  34/**
  35 * freezing_slow_path - slow path for testing whether a task needs to be frozen
  36 * @p: task to be tested
  37 *
  38 * This function is called by freezing() if system_freezing_cnt isn't zero
  39 * and tests whether @p needs to enter and stay in frozen state.  Can be
  40 * called under any context.  The freezers are responsible for ensuring the
  41 * target tasks see the updated state.
  42 */
  43bool freezing_slow_path(struct task_struct *p)
  44{
  45        if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK))
  46                return false;
  47
  48        if (test_tsk_thread_flag(p, TIF_MEMDIE))
  49                return false;
  50
  51        if (pm_nosig_freezing || cgroup_freezing(p))
  52                return true;
  53
  54        if (pm_freezing && !(p->flags & PF_KTHREAD))
  55                return true;
  56
  57        return false;
  58}
  59EXPORT_SYMBOL(freezing_slow_path);
  60
  61/* Refrigerator is place where frozen processes are stored :-). */
  62bool __refrigerator(bool check_kthr_stop)
  63{
  64        /* Hmm, should we be allowed to suspend when there are realtime
  65           processes around? */
  66        bool was_frozen = false;
  67        long save = current->state;
  68
  69        pr_debug("%s entered refrigerator\n", current->comm);
  70
  71        for (;;) {
  72                set_current_state(TASK_UNINTERRUPTIBLE);
  73
  74                spin_lock_irq(&freezer_lock);
  75                current->flags |= PF_FROZEN;
  76                if (!freezing(current) ||
  77                    (check_kthr_stop && kthread_should_stop()))
  78                        current->flags &= ~PF_FROZEN;
  79                spin_unlock_irq(&freezer_lock);
  80
  81                if (!(current->flags & PF_FROZEN))
  82                        break;
  83                was_frozen = true;
  84                schedule();
  85        }
  86
  87        pr_debug("%s left refrigerator\n", current->comm);
  88
  89        /*
  90         * Restore saved task state before returning.  The mb'd version
  91         * needs to be used; otherwise, it might silently break
  92         * synchronization which depends on ordered task state change.
  93         */
  94        set_current_state(save);
  95
  96        return was_frozen;
  97}
  98EXPORT_SYMBOL(__refrigerator);
  99
 100static void fake_signal_wake_up(struct task_struct *p)
 101{
 102        unsigned long flags;
 103
 104        if (lock_task_sighand(p, &flags)) {
 105                signal_wake_up(p, 0);
 106                unlock_task_sighand(p, &flags);
 107        }
 108}
 109
 110/**
 111 * freeze_task - send a freeze request to given task
 112 * @p: task to send the request to
 113 *
 114 * If @p is freezing, the freeze request is sent either by sending a fake
 115 * signal (if it's not a kernel thread) or waking it up (if it's a kernel
 116 * thread).
 117 *
 118 * RETURNS:
 119 * %false, if @p is not freezing or already frozen; %true, otherwise
 120 */
 121bool freeze_task(struct task_struct *p)
 122{
 123        unsigned long flags;
 124
 125        /*
 126         * This check can race with freezer_do_not_count, but worst case that
 127         * will result in an extra wakeup being sent to the task.  It does not
 128         * race with freezer_count(), the barriers in freezer_count() and
 129         * freezer_should_skip() ensure that either freezer_count() sees
 130         * freezing == true in try_to_freeze() and freezes, or
 131         * freezer_should_skip() sees !PF_FREEZE_SKIP and freezes the task
 132         * normally.
 133         */
 134        if (freezer_should_skip(p))
 135                return false;
 136
 137        spin_lock_irqsave(&freezer_lock, flags);
 138        if (!freezing(p) || frozen(p)) {
 139                spin_unlock_irqrestore(&freezer_lock, flags);
 140                return false;
 141        }
 142
 143        if (!(p->flags & PF_KTHREAD))
 144                fake_signal_wake_up(p);
 145        else
 146                wake_up_state(p, TASK_INTERRUPTIBLE);
 147
 148        spin_unlock_irqrestore(&freezer_lock, flags);
 149        return true;
 150}
 151
 152void __thaw_task(struct task_struct *p)
 153{
 154        unsigned long flags;
 155
 156        spin_lock_irqsave(&freezer_lock, flags);
 157        if (frozen(p))
 158                wake_up_process(p);
 159        spin_unlock_irqrestore(&freezer_lock, flags);
 160}
 161
 162/**
 163 * set_freezable - make %current freezable
 164 *
 165 * Mark %current freezable and enter refrigerator if necessary.
 166 */
 167bool set_freezable(void)
 168{
 169        might_sleep();
 170
 171        /*
 172         * Modify flags while holding freezer_lock.  This ensures the
 173         * freezer notices that we aren't frozen yet or the freezing
 174         * condition is visible to try_to_freeze() below.
 175         */
 176        spin_lock_irq(&freezer_lock);
 177        current->flags &= ~PF_NOFREEZE;
 178        spin_unlock_irq(&freezer_lock);
 179
 180        return try_to_freeze();
 181}
 182EXPORT_SYMBOL(set_freezable);
 183