1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 28174f150SMatt Helsley /* 38174f150SMatt Helsley * kernel/freezer.c - Function to freeze a process 48174f150SMatt Helsley * 58174f150SMatt Helsley * Originally from kernel/power/process.c 68174f150SMatt Helsley */ 78174f150SMatt Helsley 88174f150SMatt Helsley #include <linux/interrupt.h> 98174f150SMatt Helsley #include <linux/suspend.h> 109984de1aSPaul Gortmaker #include <linux/export.h> 118174f150SMatt Helsley #include <linux/syscalls.h> 128174f150SMatt Helsley #include <linux/freezer.h> 138a32c441STejun Heo #include <linux/kthread.h> 148174f150SMatt Helsley 15a3201227STejun Heo /* total number of freezing conditions in effect */ 16f5d39b02SPeter Zijlstra DEFINE_STATIC_KEY_FALSE(freezer_active); 17f5d39b02SPeter Zijlstra EXPORT_SYMBOL(freezer_active); 18a3201227STejun Heo 19f5d39b02SPeter Zijlstra /* 20f5d39b02SPeter Zijlstra * indicate whether PM freezing is in effect, protected by 2155f2503cSPingfan Liu * system_transition_mutex 2255f2503cSPingfan Liu */ 23a3201227STejun Heo bool pm_freezing; 24a3201227STejun Heo bool pm_nosig_freezing; 25a3201227STejun Heo 260c9af092STejun Heo /* protects freezing and frozen transitions */ 270c9af092STejun Heo static DEFINE_SPINLOCK(freezer_lock); 288174f150SMatt Helsley 29a3201227STejun Heo /** 30a3201227STejun Heo * freezing_slow_path - slow path for testing whether a task needs to be frozen 31a3201227STejun Heo * @p: task to be tested 32a3201227STejun Heo * 33f5d39b02SPeter Zijlstra * This function is called by freezing() if freezer_active isn't zero 34a3201227STejun Heo * and tests whether @p needs to enter and stay in frozen state. Can be 35a3201227STejun Heo * called under any context. The freezers are responsible for ensuring the 36a3201227STejun Heo * target tasks see the updated state. 37a3201227STejun Heo */ 38a3201227STejun Heo bool freezing_slow_path(struct task_struct *p) 39a3201227STejun Heo { 402b44c4dbSColin Cross if (p->flags & (PF_NOFREEZE | PF_SUSPEND_TASK)) 41a3201227STejun Heo return false; 42a3201227STejun Heo 43a34c80a7SMichal Hocko if (test_tsk_thread_flag(p, TIF_MEMDIE)) 4451fae6daSCong Wang return false; 4551fae6daSCong Wang 46a3201227STejun Heo if (pm_nosig_freezing || cgroup_freezing(p)) 47a3201227STejun Heo return true; 48a3201227STejun Heo 4934b087e4STejun Heo if (pm_freezing && !(p->flags & PF_KTHREAD)) 50a3201227STejun Heo return true; 51a3201227STejun Heo 52a3201227STejun Heo return false; 53a3201227STejun Heo } 54a3201227STejun Heo EXPORT_SYMBOL(freezing_slow_path); 55a3201227STejun Heo 56f5d39b02SPeter Zijlstra bool frozen(struct task_struct *p) 57f5d39b02SPeter Zijlstra { 58f5d39b02SPeter Zijlstra return READ_ONCE(p->__state) & TASK_FROZEN; 59f5d39b02SPeter Zijlstra } 60f5d39b02SPeter Zijlstra 618174f150SMatt Helsley /* Refrigerator is place where frozen processes are stored :-). */ 628a32c441STejun Heo bool __refrigerator(bool check_kthr_stop) 638174f150SMatt Helsley { 64f5d39b02SPeter Zijlstra unsigned int state = get_current_state(); 65a0acae0eSTejun Heo bool was_frozen = false; 668174f150SMatt Helsley 678174f150SMatt Helsley pr_debug("%s entered refrigerator\n", current->comm); 688174f150SMatt Helsley 69f5d39b02SPeter Zijlstra WARN_ON_ONCE(state && !(state & TASK_NORMAL)); 70f5d39b02SPeter Zijlstra 718174f150SMatt Helsley for (;;) { 72f5d39b02SPeter Zijlstra bool freeze; 73f5d39b02SPeter Zijlstra 74*8f0eed4aSElliot Berman raw_spin_lock_irq(¤t->pi_lock); 75f5d39b02SPeter Zijlstra set_current_state(TASK_FROZEN); 76*8f0eed4aSElliot Berman /* unstale saved_state so that __thaw_task() will wake us up */ 77*8f0eed4aSElliot Berman current->saved_state = TASK_RUNNING; 78*8f0eed4aSElliot Berman raw_spin_unlock_irq(¤t->pi_lock); 795ece3eaeSTejun Heo 805ece3eaeSTejun Heo spin_lock_irq(&freezer_lock); 81f5d39b02SPeter Zijlstra freeze = freezing(current) && !(check_kthr_stop && kthread_should_stop()); 825ece3eaeSTejun Heo spin_unlock_irq(&freezer_lock); 835ece3eaeSTejun Heo 84f5d39b02SPeter Zijlstra if (!freeze) 858174f150SMatt Helsley break; 86f5d39b02SPeter Zijlstra 87a0acae0eSTejun Heo was_frozen = true; 888174f150SMatt Helsley schedule(); 898174f150SMatt Helsley } 90f5d39b02SPeter Zijlstra __set_current_state(TASK_RUNNING); 916301cb95SThomas Gleixner 928174f150SMatt Helsley pr_debug("%s left refrigerator\n", current->comm); 9350fb4f7fSTejun Heo 94a0acae0eSTejun Heo return was_frozen; 958174f150SMatt Helsley } 96a0acae0eSTejun Heo EXPORT_SYMBOL(__refrigerator); 978174f150SMatt Helsley 988174f150SMatt Helsley static void fake_signal_wake_up(struct task_struct *p) 998174f150SMatt Helsley { 1008174f150SMatt Helsley unsigned long flags; 1018174f150SMatt Helsley 10237ad8acaSTejun Heo if (lock_task_sighand(p, &flags)) { 103d6cc7685STejun Heo signal_wake_up(p, 0); 10437ad8acaSTejun Heo unlock_task_sighand(p, &flags); 10537ad8acaSTejun Heo } 1068174f150SMatt Helsley } 1078174f150SMatt Helsley 108f5d39b02SPeter Zijlstra static int __set_task_frozen(struct task_struct *p, void *arg) 109f5d39b02SPeter Zijlstra { 110f5d39b02SPeter Zijlstra unsigned int state = READ_ONCE(p->__state); 111f5d39b02SPeter Zijlstra 112f5d39b02SPeter Zijlstra if (p->on_rq) 113f5d39b02SPeter Zijlstra return 0; 114f5d39b02SPeter Zijlstra 115f5d39b02SPeter Zijlstra if (p != current && task_curr(p)) 116f5d39b02SPeter Zijlstra return 0; 117f5d39b02SPeter Zijlstra 118f5d39b02SPeter Zijlstra if (!(state & (TASK_FREEZABLE | __TASK_STOPPED | __TASK_TRACED))) 119f5d39b02SPeter Zijlstra return 0; 120f5d39b02SPeter Zijlstra 121f5d39b02SPeter Zijlstra /* 122f5d39b02SPeter Zijlstra * Only TASK_NORMAL can be augmented with TASK_FREEZABLE, since they 123f5d39b02SPeter Zijlstra * can suffer spurious wakeups. 124f5d39b02SPeter Zijlstra */ 125f5d39b02SPeter Zijlstra if (state & TASK_FREEZABLE) 126f5d39b02SPeter Zijlstra WARN_ON_ONCE(!(state & TASK_NORMAL)); 127f5d39b02SPeter Zijlstra 128f5d39b02SPeter Zijlstra #ifdef CONFIG_LOCKDEP 129f5d39b02SPeter Zijlstra /* 130f5d39b02SPeter Zijlstra * It's dangerous to freeze with locks held; there be dragons there. 131f5d39b02SPeter Zijlstra */ 132f5d39b02SPeter Zijlstra if (!(state & __TASK_FREEZABLE_UNSAFE)) 133f5d39b02SPeter Zijlstra WARN_ON_ONCE(debug_locks && p->lockdep_depth); 134f5d39b02SPeter Zijlstra #endif 135f5d39b02SPeter Zijlstra 136*8f0eed4aSElliot Berman p->saved_state = p->__state; 137f5d39b02SPeter Zijlstra WRITE_ONCE(p->__state, TASK_FROZEN); 138f5d39b02SPeter Zijlstra return TASK_FROZEN; 139f5d39b02SPeter Zijlstra } 140f5d39b02SPeter Zijlstra 141f5d39b02SPeter Zijlstra static bool __freeze_task(struct task_struct *p) 142f5d39b02SPeter Zijlstra { 143f5d39b02SPeter Zijlstra /* TASK_FREEZABLE|TASK_STOPPED|TASK_TRACED -> TASK_FROZEN */ 144f5d39b02SPeter Zijlstra return task_call_func(p, __set_task_frozen, NULL); 145f5d39b02SPeter Zijlstra } 146f5d39b02SPeter Zijlstra 1478174f150SMatt Helsley /** 1488174f150SMatt Helsley * freeze_task - send a freeze request to given task 1498174f150SMatt Helsley * @p: task to send the request to 1508174f150SMatt Helsley * 15137f08be1SMarcos Paulo de Souza * If @p is freezing, the freeze request is sent either by sending a fake 15237f08be1SMarcos Paulo de Souza * signal (if it's not a kernel thread) or waking it up (if it's a kernel 15337f08be1SMarcos Paulo de Souza * thread). 154839e3407STejun Heo * 155839e3407STejun Heo * RETURNS: 156839e3407STejun Heo * %false, if @p is not freezing or already frozen; %true, otherwise 1578174f150SMatt Helsley */ 158839e3407STejun Heo bool freeze_task(struct task_struct *p) 1598174f150SMatt Helsley { 1600c9af092STejun Heo unsigned long flags; 1618174f150SMatt Helsley 1620c9af092STejun Heo spin_lock_irqsave(&freezer_lock, flags); 163f5d39b02SPeter Zijlstra if (!freezing(p) || frozen(p) || __freeze_task(p)) { 164a3201227STejun Heo spin_unlock_irqrestore(&freezer_lock, flags); 165a3201227STejun Heo return false; 166a3201227STejun Heo } 1678174f150SMatt Helsley 168d3dc04cdSJens Axboe if (!(p->flags & PF_KTHREAD)) 1698174f150SMatt Helsley fake_signal_wake_up(p); 1705d8f72b5SOleg Nesterov else 171f5d39b02SPeter Zijlstra wake_up_state(p, TASK_NORMAL); 172a3201227STejun Heo 1730c9af092STejun Heo spin_unlock_irqrestore(&freezer_lock, flags); 174a3201227STejun Heo return true; 1758174f150SMatt Helsley } 1768174f150SMatt Helsley 177f5d39b02SPeter Zijlstra /* 178*8f0eed4aSElliot Berman * Restore the saved_state before the task entered freezer. For typical task 179*8f0eed4aSElliot Berman * in the __refrigerator(), saved_state == TASK_RUNNING so nothing happens 180*8f0eed4aSElliot Berman * here. For tasks which were TASK_NORMAL | TASK_FREEZABLE, their initial state 181*8f0eed4aSElliot Berman * is restored unless they got an expected wakeup (see ttwu_state_match()). 182*8f0eed4aSElliot Berman * Returns 1 if the task state was restored. 183f5d39b02SPeter Zijlstra */ 184*8f0eed4aSElliot Berman static int __restore_freezer_state(struct task_struct *p, void *arg) 185f5d39b02SPeter Zijlstra { 186*8f0eed4aSElliot Berman unsigned int state = p->saved_state; 187f5d39b02SPeter Zijlstra 188*8f0eed4aSElliot Berman if (state != TASK_RUNNING) { 189f5d39b02SPeter Zijlstra WRITE_ONCE(p->__state, state); 190*8f0eed4aSElliot Berman return 1; 191*8f0eed4aSElliot Berman } 192f5d39b02SPeter Zijlstra 193*8f0eed4aSElliot Berman return 0; 194f5d39b02SPeter Zijlstra } 195f5d39b02SPeter Zijlstra 196a5be2d0dSTejun Heo void __thaw_task(struct task_struct *p) 197dc52ddc0SMatt Helsley { 198*8f0eed4aSElliot Berman unsigned long flags; 199a5be2d0dSTejun Heo 2000c9af092STejun Heo spin_lock_irqsave(&freezer_lock, flags); 201f5d39b02SPeter Zijlstra if (WARN_ON_ONCE(freezing(p))) 202f5d39b02SPeter Zijlstra goto unlock; 203f5d39b02SPeter Zijlstra 204*8f0eed4aSElliot Berman if (task_call_func(p, __restore_freezer_state, NULL)) 205f5d39b02SPeter Zijlstra goto unlock; 206f5d39b02SPeter Zijlstra 207f5d39b02SPeter Zijlstra wake_up_state(p, TASK_FROZEN); 208f5d39b02SPeter Zijlstra unlock: 2090c9af092STejun Heo spin_unlock_irqrestore(&freezer_lock, flags); 210dc52ddc0SMatt Helsley } 21196ee6d85STejun Heo 21296ee6d85STejun Heo /** 21334b087e4STejun Heo * set_freezable - make %current freezable 21496ee6d85STejun Heo * 21596ee6d85STejun Heo * Mark %current freezable and enter refrigerator if necessary. 21696ee6d85STejun Heo */ 21734b087e4STejun Heo bool set_freezable(void) 21896ee6d85STejun Heo { 21996ee6d85STejun Heo might_sleep(); 22096ee6d85STejun Heo 22196ee6d85STejun Heo /* 22296ee6d85STejun Heo * Modify flags while holding freezer_lock. This ensures the 22396ee6d85STejun Heo * freezer notices that we aren't frozen yet or the freezing 22496ee6d85STejun Heo * condition is visible to try_to_freeze() below. 22596ee6d85STejun Heo */ 22696ee6d85STejun Heo spin_lock_irq(&freezer_lock); 22796ee6d85STejun Heo current->flags &= ~PF_NOFREEZE; 22896ee6d85STejun Heo spin_unlock_irq(&freezer_lock); 22996ee6d85STejun Heo 23096ee6d85STejun Heo return try_to_freeze(); 23196ee6d85STejun Heo } 23234b087e4STejun Heo EXPORT_SYMBOL(set_freezable); 233