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