]>
git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blob - kernel/freezer.c
2 * kernel/freezer.c - Function to freeze a process
4 * Originally from kernel/power/process.c
7 #include <linux/interrupt.h>
8 #include <linux/suspend.h>
9 #include <linux/export.h>
10 #include <linux/syscalls.h>
11 #include <linux/freezer.h>
12 #include <linux/kthread.h>
14 /* protects freezing and frozen transitions */
15 static DEFINE_SPINLOCK(freezer_lock
);
17 /* Refrigerator is place where frozen processes are stored :-). */
18 bool __refrigerator(bool check_kthr_stop
)
20 /* Hmm, should we be allowed to suspend when there are realtime
22 bool was_frozen
= false;
26 * Enter FROZEN. If NOFREEZE, schedule immediate thawing by
29 spin_lock_irq(&freezer_lock
);
31 if (!freezing(current
)) {
32 spin_unlock_irq(&freezer_lock
);
35 if (current
->flags
& PF_NOFREEZE
)
36 clear_freeze_flag(current
);
37 current
->flags
|= PF_FROZEN
;
38 spin_unlock_irq(&freezer_lock
);
40 save
= current
->state
;
41 pr_debug("%s entered refrigerator\n", current
->comm
);
43 spin_lock_irq(¤t
->sighand
->siglock
);
44 recalc_sigpending(); /* We sent fake signal, clean it up */
45 spin_unlock_irq(¤t
->sighand
->siglock
);
48 set_current_state(TASK_UNINTERRUPTIBLE
);
49 if (!freezing(current
) ||
50 (check_kthr_stop
&& kthread_should_stop()))
57 spin_lock_irq(&freezer_lock
);
58 if (freezing(current
))
60 current
->flags
&= ~PF_FROZEN
;
61 spin_unlock_irq(&freezer_lock
);
63 pr_debug("%s left refrigerator\n", current
->comm
);
66 * Restore saved task state before returning. The mb'd version
67 * needs to be used; otherwise, it might silently break
68 * synchronization which depends on ordered task state change.
70 set_current_state(save
);
74 EXPORT_SYMBOL(__refrigerator
);
76 static void fake_signal_wake_up(struct task_struct
*p
)
80 spin_lock_irqsave(&p
->sighand
->siglock
, flags
);
82 spin_unlock_irqrestore(&p
->sighand
->siglock
, flags
);
86 * freeze_task - send a freeze request to given task
87 * @p: task to send the request to
88 * @sig_only: if set, the request will only be sent if the task has the
89 * PF_FREEZER_NOSIG flag unset
90 * Return value: 'false', if @sig_only is set and the task has
91 * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
93 * The freeze request is sent by setting the tasks's TIF_FREEZE flag and
94 * either sending a fake signal to it or waking it up, depending on whether
95 * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task
96 * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
97 * TIF_FREEZE flag will not be set.
99 bool freeze_task(struct task_struct
*p
, bool sig_only
)
104 spin_lock_irqsave(&freezer_lock
, flags
);
106 if ((p
->flags
& PF_NOFREEZE
) ||
107 (sig_only
&& !should_send_signal(p
)))
115 if (should_send_signal(p
)) {
116 fake_signal_wake_up(p
);
118 * fake_signal_wake_up() goes through p's scheduler
119 * lock and guarantees that TASK_STOPPED/TRACED ->
120 * TASK_RUNNING transition can't race with task state
121 * testing in try_to_freeze_tasks().
124 wake_up_state(p
, TASK_INTERRUPTIBLE
);
128 spin_unlock_irqrestore(&freezer_lock
, flags
);
132 void __thaw_task(struct task_struct
*p
)
137 * Clear freezing and kick @p if FROZEN. Clearing is guaranteed to
138 * be visible to @p as waking up implies wmb. Waking up inside
139 * freezer_lock also prevents wakeups from leaking outside
142 * If !FROZEN, @p hasn't reached refrigerator, recalc sigpending to
143 * avoid leaving dangling TIF_SIGPENDING behind.
145 spin_lock_irqsave(&freezer_lock
, flags
);
146 clear_freeze_flag(p
);
150 spin_lock(&p
->sighand
->siglock
);
151 recalc_sigpending_and_wake(p
);
152 spin_unlock(&p
->sighand
->siglock
);
154 spin_unlock_irqrestore(&freezer_lock
, flags
);