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