xref: /openbmc/linux/kernel/power/process.c (revision 1da177e4)
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/smp_lock.h>
12 #include <linux/interrupt.h>
13 #include <linux/suspend.h>
14 #include <linux/module.h>
15 
16 /*
17  * Timeout for stopping processes
18  */
19 #define TIMEOUT	(6 * HZ)
20 
21 
22 static inline int freezeable(struct task_struct * p)
23 {
24 	if ((p == current) ||
25 	    (p->flags & PF_NOFREEZE) ||
26 	    (p->exit_state == EXIT_ZOMBIE) ||
27 	    (p->exit_state == EXIT_DEAD) ||
28 	    (p->state == TASK_STOPPED) ||
29 	    (p->state == TASK_TRACED))
30 		return 0;
31 	return 1;
32 }
33 
34 /* Refrigerator is place where frozen processes are stored :-). */
35 void refrigerator(unsigned long flag)
36 {
37 	/* Hmm, should we be allowed to suspend when there are realtime
38 	   processes around? */
39 	long save;
40 	save = current->state;
41 	current->state = TASK_UNINTERRUPTIBLE;
42 	pr_debug("%s entered refrigerator\n", current->comm);
43 	printk("=");
44 	current->flags &= ~PF_FREEZE;
45 
46 	spin_lock_irq(&current->sighand->siglock);
47 	recalc_sigpending(); /* We sent fake signal, clean it up */
48 	spin_unlock_irq(&current->sighand->siglock);
49 
50 	current->flags |= PF_FROZEN;
51 	while (current->flags & PF_FROZEN)
52 		schedule();
53 	pr_debug("%s left refrigerator\n", current->comm);
54 	current->state = save;
55 }
56 
57 /* 0 = success, else # of processes that we failed to stop */
58 int freeze_processes(void)
59 {
60        int todo;
61        unsigned long start_time;
62 	struct task_struct *g, *p;
63 
64 	printk( "Stopping tasks: " );
65 	start_time = jiffies;
66 	do {
67 		todo = 0;
68 		read_lock(&tasklist_lock);
69 		do_each_thread(g, p) {
70 			unsigned long flags;
71 			if (!freezeable(p))
72 				continue;
73 			if ((p->flags & PF_FROZEN) ||
74 			    (p->state == TASK_TRACED) ||
75 			    (p->state == TASK_STOPPED))
76 				continue;
77 
78 			/* FIXME: smp problem here: we may not access other process' flags
79 			   without locking */
80 			p->flags |= PF_FREEZE;
81 			spin_lock_irqsave(&p->sighand->siglock, flags);
82 			signal_wake_up(p, 0);
83 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
84 			todo++;
85 		} while_each_thread(g, p);
86 		read_unlock(&tasklist_lock);
87 		yield();			/* Yield is okay here */
88 		if (time_after(jiffies, start_time + TIMEOUT)) {
89 			printk( "\n" );
90 			printk(KERN_ERR " stopping tasks failed (%d tasks remaining)\n", todo );
91 			return todo;
92 		}
93 	} while(todo);
94 
95 	printk( "|\n" );
96 	BUG_ON(in_atomic());
97 	return 0;
98 }
99 
100 void thaw_processes(void)
101 {
102 	struct task_struct *g, *p;
103 
104 	printk( "Restarting tasks..." );
105 	read_lock(&tasklist_lock);
106 	do_each_thread(g, p) {
107 		if (!freezeable(p))
108 			continue;
109 		if (p->flags & PF_FROZEN) {
110 			p->flags &= ~PF_FROZEN;
111 			wake_up_process(p);
112 		} else
113 			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
114 	} while_each_thread(g, p);
115 
116 	read_unlock(&tasklist_lock);
117 	schedule();
118 	printk( " done\n" );
119 }
120 
121 EXPORT_SYMBOL(refrigerator);
122