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