xref: /openbmc/linux/kernel/power/process.c (revision 545e4006)
1 /*
2  * drivers/power/process.c - Functions for starting/stopping processes on
3  *                           suspend transitions.
4  *
5  * Originally from swsusp.
6  */
7 
8 
9 #undef DEBUG
10 
11 #include <linux/interrupt.h>
12 #include <linux/suspend.h>
13 #include <linux/module.h>
14 #include <linux/syscalls.h>
15 #include <linux/freezer.h>
16 
17 /*
18  * Timeout for stopping processes
19  */
20 #define TIMEOUT	(20 * HZ)
21 
22 static inline int freezeable(struct task_struct * p)
23 {
24 	if ((p == current) ||
25 	    (p->flags & PF_NOFREEZE) ||
26 	    (p->exit_state != 0))
27 		return 0;
28 	return 1;
29 }
30 
31 /*
32  * freezing is complete, mark current process as frozen
33  */
34 static inline void frozen_process(void)
35 {
36 	if (!unlikely(current->flags & PF_NOFREEZE)) {
37 		current->flags |= PF_FROZEN;
38 		wmb();
39 	}
40 	clear_freeze_flag(current);
41 }
42 
43 /* Refrigerator is place where frozen processes are stored :-). */
44 void refrigerator(void)
45 {
46 	/* Hmm, should we be allowed to suspend when there are realtime
47 	   processes around? */
48 	long save;
49 
50 	task_lock(current);
51 	if (freezing(current)) {
52 		frozen_process();
53 		task_unlock(current);
54 	} else {
55 		task_unlock(current);
56 		return;
57 	}
58 	save = current->state;
59 	pr_debug("%s entered refrigerator\n", current->comm);
60 
61 	spin_lock_irq(&current->sighand->siglock);
62 	recalc_sigpending(); /* We sent fake signal, clean it up */
63 	spin_unlock_irq(&current->sighand->siglock);
64 
65 	for (;;) {
66 		set_current_state(TASK_UNINTERRUPTIBLE);
67 		if (!frozen(current))
68 			break;
69 		schedule();
70 	}
71 	pr_debug("%s left refrigerator\n", current->comm);
72 	__set_current_state(save);
73 }
74 
75 static void fake_signal_wake_up(struct task_struct *p)
76 {
77 	unsigned long flags;
78 
79 	spin_lock_irqsave(&p->sighand->siglock, flags);
80 	signal_wake_up(p, 0);
81 	spin_unlock_irqrestore(&p->sighand->siglock, flags);
82 }
83 
84 static inline bool should_send_signal(struct task_struct *p)
85 {
86 	return !(p->flags & PF_FREEZER_NOSIG);
87 }
88 
89 /**
90  *	freeze_task - send a freeze request to given task
91  *	@p: task to send the request to
92  *	@sig_only: if set, the request will only be sent if the task has the
93  *		PF_FREEZER_NOSIG flag unset
94  *	Return value: 'false', if @sig_only is set and the task has
95  *		PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
96  *
97  *	The freeze request is sent by setting the tasks's TIF_FREEZE flag and
98  *	either sending a fake signal to it or waking it up, depending on whether
99  *	or not it has PF_FREEZER_NOSIG set.  If @sig_only is set and the task
100  *	has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
101  *	TIF_FREEZE flag will not be set.
102  */
103 static bool freeze_task(struct task_struct *p, bool sig_only)
104 {
105 	/*
106 	 * We first check if the task is freezing and next if it has already
107 	 * been frozen to avoid the race with frozen_process() which first marks
108 	 * the task as frozen and next clears its TIF_FREEZE.
109 	 */
110 	if (!freezing(p)) {
111 		rmb();
112 		if (frozen(p))
113 			return false;
114 
115 		if (!sig_only || should_send_signal(p))
116 			set_freeze_flag(p);
117 		else
118 			return false;
119 	}
120 
121 	if (should_send_signal(p)) {
122 		if (!signal_pending(p))
123 			fake_signal_wake_up(p);
124 	} else if (sig_only) {
125 		return false;
126 	} else {
127 		wake_up_state(p, TASK_INTERRUPTIBLE);
128 	}
129 
130 	return true;
131 }
132 
133 static void cancel_freezing(struct task_struct *p)
134 {
135 	unsigned long flags;
136 
137 	if (freezing(p)) {
138 		pr_debug("  clean up: %s\n", p->comm);
139 		clear_freeze_flag(p);
140 		spin_lock_irqsave(&p->sighand->siglock, flags);
141 		recalc_sigpending_and_wake(p);
142 		spin_unlock_irqrestore(&p->sighand->siglock, flags);
143 	}
144 }
145 
146 static int try_to_freeze_tasks(bool sig_only)
147 {
148 	struct task_struct *g, *p;
149 	unsigned long end_time;
150 	unsigned int todo;
151 	struct timeval start, end;
152 	u64 elapsed_csecs64;
153 	unsigned int elapsed_csecs;
154 
155 	do_gettimeofday(&start);
156 
157 	end_time = jiffies + TIMEOUT;
158 	do {
159 		todo = 0;
160 		read_lock(&tasklist_lock);
161 		do_each_thread(g, p) {
162 			if (frozen(p) || !freezeable(p))
163 				continue;
164 
165 			if (!freeze_task(p, sig_only))
166 				continue;
167 
168 			/*
169 			 * Now that we've done set_freeze_flag, don't
170 			 * perturb a task in TASK_STOPPED or TASK_TRACED.
171 			 * It is "frozen enough".  If the task does wake
172 			 * up, it will immediately call try_to_freeze.
173 			 */
174 			if (!task_is_stopped_or_traced(p) &&
175 			    !freezer_should_skip(p))
176 				todo++;
177 		} while_each_thread(g, p);
178 		read_unlock(&tasklist_lock);
179 		yield();			/* Yield is okay here */
180 		if (time_after(jiffies, end_time))
181 			break;
182 	} while (todo);
183 
184 	do_gettimeofday(&end);
185 	elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
186 	do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
187 	elapsed_csecs = elapsed_csecs64;
188 
189 	if (todo) {
190 		/* This does not unfreeze processes that are already frozen
191 		 * (we have slightly ugly calling convention in that respect,
192 		 * and caller must call thaw_processes() if something fails),
193 		 * but it cleans up leftover PF_FREEZE requests.
194 		 */
195 		printk("\n");
196 		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
197 				"(%d tasks refusing to freeze):\n",
198 				elapsed_csecs / 100, elapsed_csecs % 100, todo);
199 		show_state();
200 		read_lock(&tasklist_lock);
201 		do_each_thread(g, p) {
202 			task_lock(p);
203 			if (freezing(p) && !freezer_should_skip(p))
204 				printk(KERN_ERR " %s\n", p->comm);
205 			cancel_freezing(p);
206 			task_unlock(p);
207 		} while_each_thread(g, p);
208 		read_unlock(&tasklist_lock);
209 	} else {
210 		printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
211 			elapsed_csecs % 100);
212 	}
213 
214 	return todo ? -EBUSY : 0;
215 }
216 
217 /**
218  *	freeze_processes - tell processes to enter the refrigerator
219  */
220 int freeze_processes(void)
221 {
222 	int error;
223 
224 	printk("Freezing user space processes ... ");
225 	error = try_to_freeze_tasks(true);
226 	if (error)
227 		goto Exit;
228 	printk("done.\n");
229 
230 	printk("Freezing remaining freezable tasks ... ");
231 	error = try_to_freeze_tasks(false);
232 	if (error)
233 		goto Exit;
234 	printk("done.");
235  Exit:
236 	BUG_ON(in_atomic());
237 	printk("\n");
238 	return error;
239 }
240 
241 static void thaw_tasks(bool nosig_only)
242 {
243 	struct task_struct *g, *p;
244 
245 	read_lock(&tasklist_lock);
246 	do_each_thread(g, p) {
247 		if (!freezeable(p))
248 			continue;
249 
250 		if (nosig_only && should_send_signal(p))
251 			continue;
252 
253 		thaw_process(p);
254 	} while_each_thread(g, p);
255 	read_unlock(&tasklist_lock);
256 }
257 
258 void thaw_processes(void)
259 {
260 	printk("Restarting tasks ... ");
261 	thaw_tasks(true);
262 	thaw_tasks(false);
263 	schedule();
264 	printk("done.\n");
265 }
266 
267 EXPORT_SYMBOL(refrigerator);
268