]>
git.proxmox.com Git - mirror_ubuntu-zesty-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
);
47 /* prevent accounting of that task to load */
48 current
->flags
|= PF_FREEZING
;
51 set_current_state(TASK_UNINTERRUPTIBLE
);
52 if (!freezing(current
) ||
53 (check_kthr_stop
&& kthread_should_stop()))
59 /* Remove the accounting blocker */
60 current
->flags
&= ~PF_FREEZING
;
63 spin_lock_irq(&freezer_lock
);
64 if (freezing(current
))
66 current
->flags
&= ~PF_FROZEN
;
67 spin_unlock_irq(&freezer_lock
);
69 pr_debug("%s left refrigerator\n", current
->comm
);
72 * Restore saved task state before returning. The mb'd version
73 * needs to be used; otherwise, it might silently break
74 * synchronization which depends on ordered task state change.
76 set_current_state(save
);
80 EXPORT_SYMBOL(__refrigerator
);
82 static void fake_signal_wake_up(struct task_struct
*p
)
86 spin_lock_irqsave(&p
->sighand
->siglock
, flags
);
88 spin_unlock_irqrestore(&p
->sighand
->siglock
, flags
);
92 * freeze_task - send a freeze request to given task
93 * @p: task to send the request to
94 * @sig_only: if set, the request will only be sent if the task has the
95 * PF_FREEZER_NOSIG flag unset
96 * Return value: 'false', if @sig_only is set and the task has
97 * PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
99 * The freeze request is sent by setting the tasks's TIF_FREEZE flag and
100 * either sending a fake signal to it or waking it up, depending on whether
101 * or not it has PF_FREEZER_NOSIG set. If @sig_only is set and the task
102 * has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
103 * TIF_FREEZE flag will not be set.
105 bool freeze_task(struct task_struct
*p
, bool sig_only
)
110 spin_lock_irqsave(&freezer_lock
, flags
);
112 if (sig_only
&& !should_send_signal(p
))
120 if (should_send_signal(p
)) {
121 fake_signal_wake_up(p
);
123 * fake_signal_wake_up() goes through p's scheduler
124 * lock and guarantees that TASK_STOPPED/TRACED ->
125 * TASK_RUNNING transition can't race with task state
126 * testing in try_to_freeze_tasks().
129 wake_up_state(p
, TASK_INTERRUPTIBLE
);
133 spin_unlock_irqrestore(&freezer_lock
, flags
);
137 void cancel_freezing(struct task_struct
*p
)
141 spin_lock_irqsave(&freezer_lock
, flags
);
143 pr_debug(" clean up: %s\n", p
->comm
);
144 clear_freeze_flag(p
);
145 spin_lock(&p
->sighand
->siglock
);
146 recalc_sigpending_and_wake(p
);
147 spin_unlock(&p
->sighand
->siglock
);
149 spin_unlock_irqrestore(&freezer_lock
, flags
);
152 void __thaw_task(struct task_struct
*p
)
157 * Clear freezing and kick @p if FROZEN. Clearing is guaranteed to
158 * be visible to @p as waking up implies wmb. Waking up inside
159 * freezer_lock also prevents wakeups from leaking outside
162 spin_lock_irqsave(&freezer_lock
, flags
);
163 clear_freeze_flag(p
);
166 spin_unlock_irqrestore(&freezer_lock
, flags
);