xref: /openbmc/linux/kernel/power/process.c (revision e8e0929d)
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/oom.h>
13 #include <linux/suspend.h>
14 #include <linux/module.h>
15 #include <linux/syscalls.h>
16 #include <linux/freezer.h>
17 
18 /*
19  * Timeout for stopping processes
20  */
21 #define TIMEOUT	(20 * HZ)
22 
23 static inline int freezeable(struct task_struct * p)
24 {
25 	if ((p == current) ||
26 	    (p->flags & PF_NOFREEZE) ||
27 	    (p->exit_state != 0))
28 		return 0;
29 	return 1;
30 }
31 
32 static int try_to_freeze_tasks(bool sig_only)
33 {
34 	struct task_struct *g, *p;
35 	unsigned long end_time;
36 	unsigned int todo;
37 	struct timeval start, end;
38 	u64 elapsed_csecs64;
39 	unsigned int elapsed_csecs;
40 
41 	do_gettimeofday(&start);
42 
43 	end_time = jiffies + TIMEOUT;
44 	do {
45 		todo = 0;
46 		read_lock(&tasklist_lock);
47 		do_each_thread(g, p) {
48 			if (frozen(p) || !freezeable(p))
49 				continue;
50 
51 			if (!freeze_task(p, sig_only))
52 				continue;
53 
54 			/*
55 			 * Now that we've done set_freeze_flag, don't
56 			 * perturb a task in TASK_STOPPED or TASK_TRACED.
57 			 * It is "frozen enough".  If the task does wake
58 			 * up, it will immediately call try_to_freeze.
59 			 */
60 			if (!task_is_stopped_or_traced(p) &&
61 			    !freezer_should_skip(p))
62 				todo++;
63 		} while_each_thread(g, p);
64 		read_unlock(&tasklist_lock);
65 		yield();			/* Yield is okay here */
66 		if (time_after(jiffies, end_time))
67 			break;
68 	} while (todo);
69 
70 	do_gettimeofday(&end);
71 	elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
72 	do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
73 	elapsed_csecs = elapsed_csecs64;
74 
75 	if (todo) {
76 		/* This does not unfreeze processes that are already frozen
77 		 * (we have slightly ugly calling convention in that respect,
78 		 * and caller must call thaw_processes() if something fails),
79 		 * but it cleans up leftover PF_FREEZE requests.
80 		 */
81 		printk("\n");
82 		printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
83 				"(%d tasks refusing to freeze):\n",
84 				elapsed_csecs / 100, elapsed_csecs % 100, todo);
85 		show_state();
86 		read_lock(&tasklist_lock);
87 		do_each_thread(g, p) {
88 			task_lock(p);
89 			if (freezing(p) && !freezer_should_skip(p))
90 				printk(KERN_ERR " %s\n", p->comm);
91 			cancel_freezing(p);
92 			task_unlock(p);
93 		} while_each_thread(g, p);
94 		read_unlock(&tasklist_lock);
95 	} else {
96 		printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
97 			elapsed_csecs % 100);
98 	}
99 
100 	return todo ? -EBUSY : 0;
101 }
102 
103 /**
104  *	freeze_processes - tell processes to enter the refrigerator
105  */
106 int freeze_processes(void)
107 {
108 	int error;
109 
110 	printk("Freezing user space processes ... ");
111 	error = try_to_freeze_tasks(true);
112 	if (error)
113 		goto Exit;
114 	printk("done.\n");
115 
116 	printk("Freezing remaining freezable tasks ... ");
117 	error = try_to_freeze_tasks(false);
118 	if (error)
119 		goto Exit;
120 	printk("done.");
121 
122 	oom_killer_disable();
123  Exit:
124 	BUG_ON(in_atomic());
125 	printk("\n");
126 
127 	return error;
128 }
129 
130 static void thaw_tasks(bool nosig_only)
131 {
132 	struct task_struct *g, *p;
133 
134 	read_lock(&tasklist_lock);
135 	do_each_thread(g, p) {
136 		if (!freezeable(p))
137 			continue;
138 
139 		if (nosig_only && should_send_signal(p))
140 			continue;
141 
142 		if (cgroup_frozen(p))
143 			continue;
144 
145 		thaw_process(p);
146 	} while_each_thread(g, p);
147 	read_unlock(&tasklist_lock);
148 }
149 
150 void thaw_processes(void)
151 {
152 	oom_killer_enable();
153 
154 	printk("Restarting tasks ... ");
155 	thaw_tasks(true);
156 	thaw_tasks(false);
157 	schedule();
158 	printk("done.\n");
159 }
160 
161