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 */
16*f5d39b02SPeter Zijlstra DEFINE_STATIC_KEY_FALSE(freezer_active);
17*f5d39b02SPeter Zijlstra EXPORT_SYMBOL(freezer_active);
18a3201227STejun Heo
19*f5d39b02SPeter Zijlstra /*
20*f5d39b02SPeter 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 *
33*f5d39b02SPeter 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 */
freezing_slow_path(struct task_struct * p)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
frozen(struct task_struct * p)56*f5d39b02SPeter Zijlstra bool frozen(struct task_struct *p)
57*f5d39b02SPeter Zijlstra {
58*f5d39b02SPeter Zijlstra return READ_ONCE(p->__state) & TASK_FROZEN;
59*f5d39b02SPeter Zijlstra }
60*f5d39b02SPeter Zijlstra
618174f150SMatt Helsley /* Refrigerator is place where frozen processes are stored :-). */
__refrigerator(bool check_kthr_stop)628a32c441STejun Heo bool __refrigerator(bool check_kthr_stop)
638174f150SMatt Helsley {
64*f5d39b02SPeter 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
69*f5d39b02SPeter Zijlstra WARN_ON_ONCE(state && !(state & TASK_NORMAL));
70*f5d39b02SPeter Zijlstra
718174f150SMatt Helsley for (;;) {
72*f5d39b02SPeter Zijlstra bool freeze;
73*f5d39b02SPeter Zijlstra
74*f5d39b02SPeter Zijlstra set_current_state(TASK_FROZEN);
755ece3eaeSTejun Heo
765ece3eaeSTejun Heo spin_lock_irq(&freezer_lock);
77*f5d39b02SPeter Zijlstra freeze = freezing(current) && !(check_kthr_stop && kthread_should_stop());
785ece3eaeSTejun Heo spin_unlock_irq(&freezer_lock);
795ece3eaeSTejun Heo
80*f5d39b02SPeter Zijlstra if (!freeze)
818174f150SMatt Helsley break;
82*f5d39b02SPeter Zijlstra
83a0acae0eSTejun Heo was_frozen = true;
848174f150SMatt Helsley schedule();
858174f150SMatt Helsley }
86*f5d39b02SPeter Zijlstra __set_current_state(TASK_RUNNING);
876301cb95SThomas Gleixner
888174f150SMatt Helsley pr_debug("%s left refrigerator\n", current->comm);
8950fb4f7fSTejun Heo
90a0acae0eSTejun Heo return was_frozen;
918174f150SMatt Helsley }
92a0acae0eSTejun Heo EXPORT_SYMBOL(__refrigerator);
938174f150SMatt Helsley
fake_signal_wake_up(struct task_struct * p)948174f150SMatt Helsley static void fake_signal_wake_up(struct task_struct *p)
958174f150SMatt Helsley {
968174f150SMatt Helsley unsigned long flags;
978174f150SMatt Helsley
9837ad8acaSTejun Heo if (lock_task_sighand(p, &flags)) {
99d6cc7685STejun Heo signal_wake_up(p, 0);
10037ad8acaSTejun Heo unlock_task_sighand(p, &flags);
10137ad8acaSTejun Heo }
1028174f150SMatt Helsley }
1038174f150SMatt Helsley
__set_task_frozen(struct task_struct * p,void * arg)104*f5d39b02SPeter Zijlstra static int __set_task_frozen(struct task_struct *p, void *arg)
105*f5d39b02SPeter Zijlstra {
106*f5d39b02SPeter Zijlstra unsigned int state = READ_ONCE(p->__state);
107*f5d39b02SPeter Zijlstra
108*f5d39b02SPeter Zijlstra if (p->on_rq)
109*f5d39b02SPeter Zijlstra return 0;
110*f5d39b02SPeter Zijlstra
111*f5d39b02SPeter Zijlstra if (p != current && task_curr(p))
112*f5d39b02SPeter Zijlstra return 0;
113*f5d39b02SPeter Zijlstra
114*f5d39b02SPeter Zijlstra if (!(state & (TASK_FREEZABLE | __TASK_STOPPED | __TASK_TRACED)))
115*f5d39b02SPeter Zijlstra return 0;
116*f5d39b02SPeter Zijlstra
117*f5d39b02SPeter Zijlstra /*
118*f5d39b02SPeter Zijlstra * Only TASK_NORMAL can be augmented with TASK_FREEZABLE, since they
119*f5d39b02SPeter Zijlstra * can suffer spurious wakeups.
120*f5d39b02SPeter Zijlstra */
121*f5d39b02SPeter Zijlstra if (state & TASK_FREEZABLE)
122*f5d39b02SPeter Zijlstra WARN_ON_ONCE(!(state & TASK_NORMAL));
123*f5d39b02SPeter Zijlstra
124*f5d39b02SPeter Zijlstra #ifdef CONFIG_LOCKDEP
125*f5d39b02SPeter Zijlstra /*
126*f5d39b02SPeter Zijlstra * It's dangerous to freeze with locks held; there be dragons there.
127*f5d39b02SPeter Zijlstra */
128*f5d39b02SPeter Zijlstra if (!(state & __TASK_FREEZABLE_UNSAFE))
129*f5d39b02SPeter Zijlstra WARN_ON_ONCE(debug_locks && p->lockdep_depth);
130*f5d39b02SPeter Zijlstra #endif
131*f5d39b02SPeter Zijlstra
132*f5d39b02SPeter Zijlstra WRITE_ONCE(p->__state, TASK_FROZEN);
133*f5d39b02SPeter Zijlstra return TASK_FROZEN;
134*f5d39b02SPeter Zijlstra }
135*f5d39b02SPeter Zijlstra
__freeze_task(struct task_struct * p)136*f5d39b02SPeter Zijlstra static bool __freeze_task(struct task_struct *p)
137*f5d39b02SPeter Zijlstra {
138*f5d39b02SPeter Zijlstra /* TASK_FREEZABLE|TASK_STOPPED|TASK_TRACED -> TASK_FROZEN */
139*f5d39b02SPeter Zijlstra return task_call_func(p, __set_task_frozen, NULL);
140*f5d39b02SPeter Zijlstra }
141*f5d39b02SPeter Zijlstra
1428174f150SMatt Helsley /**
1438174f150SMatt Helsley * freeze_task - send a freeze request to given task
1448174f150SMatt Helsley * @p: task to send the request to
1458174f150SMatt Helsley *
14637f08be1SMarcos Paulo de Souza * If @p is freezing, the freeze request is sent either by sending a fake
14737f08be1SMarcos Paulo de Souza * signal (if it's not a kernel thread) or waking it up (if it's a kernel
14837f08be1SMarcos Paulo de Souza * thread).
149839e3407STejun Heo *
150839e3407STejun Heo * RETURNS:
151839e3407STejun Heo * %false, if @p is not freezing or already frozen; %true, otherwise
1528174f150SMatt Helsley */
freeze_task(struct task_struct * p)153839e3407STejun Heo bool freeze_task(struct task_struct *p)
1548174f150SMatt Helsley {
1550c9af092STejun Heo unsigned long flags;
1568174f150SMatt Helsley
1570c9af092STejun Heo spin_lock_irqsave(&freezer_lock, flags);
158*f5d39b02SPeter Zijlstra if (!freezing(p) || frozen(p) || __freeze_task(p)) {
159a3201227STejun Heo spin_unlock_irqrestore(&freezer_lock, flags);
160a3201227STejun Heo return false;
161a3201227STejun Heo }
1628174f150SMatt Helsley
163d3dc04cdSJens Axboe if (!(p->flags & PF_KTHREAD))
1648174f150SMatt Helsley fake_signal_wake_up(p);
1655d8f72b5SOleg Nesterov else
166*f5d39b02SPeter Zijlstra wake_up_state(p, TASK_NORMAL);
167a3201227STejun Heo
1680c9af092STejun Heo spin_unlock_irqrestore(&freezer_lock, flags);
169a3201227STejun Heo return true;
1708174f150SMatt Helsley }
1718174f150SMatt Helsley
172*f5d39b02SPeter Zijlstra /*
173*f5d39b02SPeter Zijlstra * The special task states (TASK_STOPPED, TASK_TRACED) keep their canonical
174*f5d39b02SPeter Zijlstra * state in p->jobctl. If either of them got a wakeup that was missed because
175*f5d39b02SPeter Zijlstra * TASK_FROZEN, then their canonical state reflects that and the below will
176*f5d39b02SPeter Zijlstra * refuse to restore the special state and instead issue the wakeup.
177*f5d39b02SPeter Zijlstra */
__set_task_special(struct task_struct * p,void * arg)178*f5d39b02SPeter Zijlstra static int __set_task_special(struct task_struct *p, void *arg)
179*f5d39b02SPeter Zijlstra {
180*f5d39b02SPeter Zijlstra unsigned int state = 0;
181*f5d39b02SPeter Zijlstra
182*f5d39b02SPeter Zijlstra if (p->jobctl & JOBCTL_TRACED)
183*f5d39b02SPeter Zijlstra state = TASK_TRACED;
184*f5d39b02SPeter Zijlstra
185*f5d39b02SPeter Zijlstra else if (p->jobctl & JOBCTL_STOPPED)
186*f5d39b02SPeter Zijlstra state = TASK_STOPPED;
187*f5d39b02SPeter Zijlstra
188*f5d39b02SPeter Zijlstra if (state)
189*f5d39b02SPeter Zijlstra WRITE_ONCE(p->__state, state);
190*f5d39b02SPeter Zijlstra
191*f5d39b02SPeter Zijlstra return state;
192*f5d39b02SPeter Zijlstra }
193*f5d39b02SPeter Zijlstra
__thaw_task(struct task_struct * p)194a5be2d0dSTejun Heo void __thaw_task(struct task_struct *p)
195dc52ddc0SMatt Helsley {
196*f5d39b02SPeter Zijlstra unsigned long flags, flags2;
197a5be2d0dSTejun Heo
1980c9af092STejun Heo spin_lock_irqsave(&freezer_lock, flags);
199*f5d39b02SPeter Zijlstra if (WARN_ON_ONCE(freezing(p)))
200*f5d39b02SPeter Zijlstra goto unlock;
201*f5d39b02SPeter Zijlstra
202*f5d39b02SPeter Zijlstra if (lock_task_sighand(p, &flags2)) {
203*f5d39b02SPeter Zijlstra /* TASK_FROZEN -> TASK_{STOPPED,TRACED} */
204*f5d39b02SPeter Zijlstra bool ret = task_call_func(p, __set_task_special, NULL);
205*f5d39b02SPeter Zijlstra unlock_task_sighand(p, &flags2);
206*f5d39b02SPeter Zijlstra if (ret)
207*f5d39b02SPeter Zijlstra goto unlock;
208*f5d39b02SPeter Zijlstra }
209*f5d39b02SPeter Zijlstra
210*f5d39b02SPeter Zijlstra wake_up_state(p, TASK_FROZEN);
211*f5d39b02SPeter Zijlstra unlock:
2120c9af092STejun Heo spin_unlock_irqrestore(&freezer_lock, flags);
213dc52ddc0SMatt Helsley }
21496ee6d85STejun Heo
21596ee6d85STejun Heo /**
21634b087e4STejun Heo * set_freezable - make %current freezable
21796ee6d85STejun Heo *
21896ee6d85STejun Heo * Mark %current freezable and enter refrigerator if necessary.
21996ee6d85STejun Heo */
set_freezable(void)22034b087e4STejun Heo bool set_freezable(void)
22196ee6d85STejun Heo {
22296ee6d85STejun Heo might_sleep();
22396ee6d85STejun Heo
22496ee6d85STejun Heo /*
22596ee6d85STejun Heo * Modify flags while holding freezer_lock. This ensures the
22696ee6d85STejun Heo * freezer notices that we aren't frozen yet or the freezing
22796ee6d85STejun Heo * condition is visible to try_to_freeze() below.
22896ee6d85STejun Heo */
22996ee6d85STejun Heo spin_lock_irq(&freezer_lock);
23096ee6d85STejun Heo current->flags &= ~PF_NOFREEZE;
23196ee6d85STejun Heo spin_unlock_irq(&freezer_lock);
23296ee6d85STejun Heo
23396ee6d85STejun Heo return try_to_freeze();
23496ee6d85STejun Heo }
23534b087e4STejun Heo EXPORT_SYMBOL(set_freezable);
236