Freezer: avoid freezing kernel threads prematurely
[safe/jmp/linux-2.6] / include / linux / freezer.h
1 /* Freezer declarations */
2
3 #ifndef FREEZER_H_INCLUDED
4 #define FREEZER_H_INCLUDED
5
6 #include <linux/sched.h>
7
8 #ifdef CONFIG_PM
9 /*
10  * Check if a process has been frozen
11  */
12 static inline int frozen(struct task_struct *p)
13 {
14         return p->flags & PF_FROZEN;
15 }
16
17 /*
18  * Check if there is a request to freeze a process
19  */
20 static inline int freezing(struct task_struct *p)
21 {
22         return test_tsk_thread_flag(p, TIF_FREEZE);
23 }
24
25 /*
26  * Request that a process be frozen
27  */
28 static inline void set_freeze_flag(struct task_struct *p)
29 {
30         set_tsk_thread_flag(p, TIF_FREEZE);
31 }
32
33 /*
34  * Sometimes we may need to cancel the previous 'freeze' request
35  */
36 static inline void clear_freeze_flag(struct task_struct *p)
37 {
38         clear_tsk_thread_flag(p, TIF_FREEZE);
39 }
40
41 /*
42  * Wake up a frozen process
43  *
44  * task_lock() is taken to prevent the race with refrigerator() which may
45  * occur if the freezing of tasks fails.  Namely, without the lock, if the
46  * freezing of tasks failed, thaw_tasks() might have run before a task in
47  * refrigerator() could call frozen_process(), in which case the task would be
48  * frozen and no one would thaw it.
49  */
50 static inline int thaw_process(struct task_struct *p)
51 {
52         task_lock(p);
53         if (frozen(p)) {
54                 p->flags &= ~PF_FROZEN;
55                 task_unlock(p);
56                 wake_up_process(p);
57                 return 1;
58         }
59         clear_freeze_flag(p);
60         task_unlock(p);
61         return 0;
62 }
63
64 extern void refrigerator(void);
65 extern int freeze_processes(void);
66 extern void thaw_processes(void);
67
68 static inline int try_to_freeze(void)
69 {
70         if (freezing(current)) {
71                 refrigerator();
72                 return 1;
73         } else
74                 return 0;
75 }
76
77 /*
78  * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
79  * calls wait_for_completion(&vfork) and reset right after it returns from this
80  * function.  Next, the parent should call try_to_freeze() to freeze itself
81  * appropriately in case the child has exited before the freezing of tasks is
82  * complete.  However, we don't want kernel threads to be frozen in unexpected
83  * places, so we allow them to block freeze_processes() instead or to set
84  * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork
85  * parents.  Fortunately, in the ____call_usermodehelper() case the parent won't
86  * really block freeze_processes(), since ____call_usermodehelper() (the child)
87  * does a little before exec/exit and it can't be frozen before waking up the
88  * parent.
89  */
90
91 /*
92  * If the current task is a user space one, tell the freezer not to count it as
93  * freezable.
94  */
95 static inline void freezer_do_not_count(void)
96 {
97         if (current->mm)
98                 current->flags |= PF_FREEZER_SKIP;
99 }
100
101 /*
102  * If the current task is a user space one, tell the freezer to count it as
103  * freezable again and try to freeze it.
104  */
105 static inline void freezer_count(void)
106 {
107         if (current->mm) {
108                 current->flags &= ~PF_FREEZER_SKIP;
109                 try_to_freeze();
110         }
111 }
112
113 /*
114  * Check if the task should be counted as freezeable by the freezer
115  */
116 static inline int freezer_should_skip(struct task_struct *p)
117 {
118         return !!(p->flags & PF_FREEZER_SKIP);
119 }
120
121 /*
122  * Tell the freezer that the current task should be frozen by it
123  */
124 static inline void set_freezable(void)
125 {
126         current->flags &= ~PF_NOFREEZE;
127 }
128
129 #else
130 static inline int frozen(struct task_struct *p) { return 0; }
131 static inline int freezing(struct task_struct *p) { return 0; }
132 static inline void set_freeze_flag(struct task_struct *p) {}
133 static inline void clear_freeze_flag(struct task_struct *p) {}
134 static inline int thaw_process(struct task_struct *p) { return 1; }
135
136 static inline void refrigerator(void) {}
137 static inline int freeze_processes(void) { BUG(); return 0; }
138 static inline void thaw_processes(void) {}
139
140 static inline int try_to_freeze(void) { return 0; }
141
142 static inline void freezer_do_not_count(void) {}
143 static inline void freezer_count(void) {}
144 static inline int freezer_should_skip(struct task_struct *p) { return 0; }
145 static inline void set_freezable(void) {}
146 #endif
147
148 #endif  /* FREEZER_H_INCLUDED */