1
2
3
4
5
6
7#include <linux/interrupt.h>
8#include <linux/suspend.h>
9#include <linux/module.h>
10#include <linux/syscalls.h>
11#include <linux/freezer.h>
12
13
14
15
16static inline void frozen_process(void)
17{
18 if (!unlikely(current->flags & PF_NOFREEZE)) {
19 current->flags |= PF_FROZEN;
20 wmb();
21 }
22 clear_freeze_flag(current);
23}
24
25
26void refrigerator(void)
27{
28
29
30 long save;
31
32 task_lock(current);
33 if (freezing(current)) {
34 frozen_process();
35 task_unlock(current);
36 } else {
37 task_unlock(current);
38 return;
39 }
40 save = current->state;
41 pr_debug("%s entered refrigerator\n", current->comm);
42
43 spin_lock_irq(¤t->sighand->siglock);
44 recalc_sigpending();
45 spin_unlock_irq(¤t->sighand->siglock);
46
47
48 current->flags |= PF_FREEZING;
49
50 for (;;) {
51 set_current_state(TASK_UNINTERRUPTIBLE);
52 if (!frozen(current))
53 break;
54 schedule();
55 }
56
57
58 current->flags &= ~PF_FREEZING;
59
60 pr_debug("%s left refrigerator\n", current->comm);
61 __set_current_state(save);
62}
63EXPORT_SYMBOL(refrigerator);
64
65static void fake_signal_wake_up(struct task_struct *p)
66{
67 unsigned long flags;
68
69 spin_lock_irqsave(&p->sighand->siglock, flags);
70 signal_wake_up(p, 0);
71 spin_unlock_irqrestore(&p->sighand->siglock, flags);
72}
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88bool freeze_task(struct task_struct *p, bool sig_only)
89{
90
91
92
93
94
95 if (!freezing(p)) {
96 rmb();
97 if (frozen(p))
98 return false;
99
100 if (!sig_only || should_send_signal(p))
101 set_freeze_flag(p);
102 else
103 return false;
104 }
105
106 if (should_send_signal(p)) {
107 if (!signal_pending(p))
108 fake_signal_wake_up(p);
109 } else if (sig_only) {
110 return false;
111 } else {
112 wake_up_state(p, TASK_INTERRUPTIBLE);
113 }
114
115 return true;
116}
117
118void cancel_freezing(struct task_struct *p)
119{
120 unsigned long flags;
121
122 if (freezing(p)) {
123 pr_debug(" clean up: %s\n", p->comm);
124 clear_freeze_flag(p);
125 spin_lock_irqsave(&p->sighand->siglock, flags);
126 recalc_sigpending_and_wake(p);
127 spin_unlock_irqrestore(&p->sighand->siglock, flags);
128 }
129}
130
131static int __thaw_process(struct task_struct *p)
132{
133 if (frozen(p)) {
134 p->flags &= ~PF_FROZEN;
135 return 1;
136 }
137 clear_freeze_flag(p);
138 return 0;
139}
140
141
142
143
144
145
146
147
148
149
150int thaw_process(struct task_struct *p)
151{
152 task_lock(p);
153 if (__thaw_process(p) == 1) {
154 task_unlock(p);
155 wake_up_process(p);
156 return 1;
157 }
158 task_unlock(p);
159 return 0;
160}
161EXPORT_SYMBOL(thaw_process);
162