diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /include/linux/freezer.h | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'include/linux/freezer.h')
-rw-r--r-- | include/linux/freezer.h | 226 |
1 files changed, 91 insertions, 135 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index e4238ceaa4d..1effc8b56b4 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h | |||
@@ -5,59 +5,70 @@ | |||
5 | 5 | ||
6 | #include <linux/sched.h> | 6 | #include <linux/sched.h> |
7 | #include <linux/wait.h> | 7 | #include <linux/wait.h> |
8 | #include <linux/atomic.h> | ||
9 | 8 | ||
10 | #ifdef CONFIG_FREEZER | 9 | #ifdef CONFIG_FREEZER |
11 | extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */ | ||
12 | extern bool pm_freezing; /* PM freezing in effect */ | ||
13 | extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ | ||
14 | |||
15 | /* | 10 | /* |
16 | * Check if a process has been frozen | 11 | * Check if a process has been frozen |
17 | */ | 12 | */ |
18 | static inline bool frozen(struct task_struct *p) | 13 | static inline int frozen(struct task_struct *p) |
19 | { | 14 | { |
20 | return p->flags & PF_FROZEN; | 15 | return p->flags & PF_FROZEN; |
21 | } | 16 | } |
22 | 17 | ||
23 | extern bool freezing_slow_path(struct task_struct *p); | ||
24 | |||
25 | /* | 18 | /* |
26 | * Check if there is a request to freeze a process | 19 | * Check if there is a request to freeze a process |
27 | */ | 20 | */ |
28 | static inline bool freezing(struct task_struct *p) | 21 | static inline int freezing(struct task_struct *p) |
22 | { | ||
23 | return test_tsk_thread_flag(p, TIF_FREEZE); | ||
24 | } | ||
25 | |||
26 | /* | ||
27 | * Request that a process be frozen | ||
28 | */ | ||
29 | static inline void set_freeze_flag(struct task_struct *p) | ||
30 | { | ||
31 | set_tsk_thread_flag(p, TIF_FREEZE); | ||
32 | } | ||
33 | |||
34 | /* | ||
35 | * Sometimes we may need to cancel the previous 'freeze' request | ||
36 | */ | ||
37 | static inline void clear_freeze_flag(struct task_struct *p) | ||
38 | { | ||
39 | clear_tsk_thread_flag(p, TIF_FREEZE); | ||
40 | } | ||
41 | |||
42 | static inline bool should_send_signal(struct task_struct *p) | ||
29 | { | 43 | { |
30 | if (likely(!atomic_read(&system_freezing_cnt))) | 44 | return !(p->flags & PF_FREEZER_NOSIG); |
31 | return false; | ||
32 | return freezing_slow_path(p); | ||
33 | } | 45 | } |
34 | 46 | ||
35 | /* Takes and releases task alloc lock using task_lock() */ | 47 | /* Takes and releases task alloc lock using task_lock() */ |
36 | extern void __thaw_task(struct task_struct *t); | 48 | extern int thaw_process(struct task_struct *p); |
37 | 49 | ||
38 | extern bool __refrigerator(bool check_kthr_stop); | 50 | extern void refrigerator(void); |
39 | extern int freeze_processes(void); | 51 | extern int freeze_processes(void); |
40 | extern int freeze_kernel_threads(void); | ||
41 | extern void thaw_processes(void); | 52 | extern void thaw_processes(void); |
42 | extern void thaw_kernel_threads(void); | ||
43 | 53 | ||
44 | static inline bool try_to_freeze(void) | 54 | static inline int try_to_freeze(void) |
45 | { | 55 | { |
46 | might_sleep(); | 56 | if (freezing(current)) { |
47 | if (likely(!freezing(current))) | 57 | refrigerator(); |
48 | return false; | 58 | return 1; |
49 | return __refrigerator(false); | 59 | } else |
60 | return 0; | ||
50 | } | 61 | } |
51 | 62 | ||
52 | extern bool freeze_task(struct task_struct *p); | 63 | extern bool freeze_task(struct task_struct *p, bool sig_only); |
53 | extern bool set_freezable(void); | 64 | extern void cancel_freezing(struct task_struct *p); |
54 | 65 | ||
55 | #ifdef CONFIG_CGROUP_FREEZER | 66 | #ifdef CONFIG_CGROUP_FREEZER |
56 | extern bool cgroup_freezing(struct task_struct *task); | 67 | extern int cgroup_freezing_or_frozen(struct task_struct *task); |
57 | #else /* !CONFIG_CGROUP_FREEZER */ | 68 | #else /* !CONFIG_CGROUP_FREEZER */ |
58 | static inline bool cgroup_freezing(struct task_struct *task) | 69 | static inline int cgroup_freezing_or_frozen(struct task_struct *task) |
59 | { | 70 | { |
60 | return false; | 71 | return 0; |
61 | } | 72 | } |
62 | #endif /* !CONFIG_CGROUP_FREEZER */ | 73 | #endif /* !CONFIG_CGROUP_FREEZER */ |
63 | 74 | ||
@@ -68,160 +79,108 @@ static inline bool cgroup_freezing(struct task_struct *task) | |||
68 | * appropriately in case the child has exited before the freezing of tasks is | 79 | * appropriately in case the child has exited before the freezing of tasks is |
69 | * complete. However, we don't want kernel threads to be frozen in unexpected | 80 | * complete. However, we don't want kernel threads to be frozen in unexpected |
70 | * places, so we allow them to block freeze_processes() instead or to set | 81 | * places, so we allow them to block freeze_processes() instead or to set |
71 | * PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the | 82 | * PF_NOFREEZE if needed and PF_FREEZER_SKIP is only set for userland vfork |
72 | * parent won't really block freeze_processes(), since ____call_usermodehelper() | 83 | * parents. Fortunately, in the ____call_usermodehelper() case the parent won't |
73 | * (the child) does a little before exec/exit and it can't be frozen before | 84 | * really block freeze_processes(), since ____call_usermodehelper() (the child) |
74 | * waking up the parent. | 85 | * does a little before exec/exit and it can't be frozen before waking up the |
86 | * parent. | ||
75 | */ | 87 | */ |
76 | 88 | ||
77 | 89 | /* | |
78 | /** | 90 | * If the current task is a user space one, tell the freezer not to count it as |
79 | * freezer_do_not_count - tell freezer to ignore %current | 91 | * freezable. |
80 | * | ||
81 | * Tell freezers to ignore the current task when determining whether the | ||
82 | * target frozen state is reached. IOW, the current task will be | ||
83 | * considered frozen enough by freezers. | ||
84 | * | ||
85 | * The caller shouldn't do anything which isn't allowed for a frozen task | ||
86 | * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair | ||
87 | * wrap a scheduling operation and nothing much else. | ||
88 | */ | 92 | */ |
89 | static inline void freezer_do_not_count(void) | 93 | static inline void freezer_do_not_count(void) |
90 | { | 94 | { |
91 | current->flags |= PF_FREEZER_SKIP; | 95 | if (current->mm) |
96 | current->flags |= PF_FREEZER_SKIP; | ||
92 | } | 97 | } |
93 | 98 | ||
94 | /** | 99 | /* |
95 | * freezer_count - tell freezer to stop ignoring %current | 100 | * If the current task is a user space one, tell the freezer to count it as |
96 | * | 101 | * freezable again and try to freeze it. |
97 | * Undo freezer_do_not_count(). It tells freezers that %current should be | ||
98 | * considered again and tries to freeze if freezing condition is already in | ||
99 | * effect. | ||
100 | */ | 102 | */ |
101 | static inline void freezer_count(void) | 103 | static inline void freezer_count(void) |
102 | { | 104 | { |
103 | current->flags &= ~PF_FREEZER_SKIP; | 105 | if (current->mm) { |
104 | /* | 106 | current->flags &= ~PF_FREEZER_SKIP; |
105 | * If freezing is in progress, the following paired with smp_mb() | 107 | try_to_freeze(); |
106 | * in freezer_should_skip() ensures that either we see %true | 108 | } |
107 | * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. | ||
108 | */ | ||
109 | smp_mb(); | ||
110 | try_to_freeze(); | ||
111 | } | 109 | } |
112 | 110 | ||
113 | /** | 111 | /* |
114 | * freezer_should_skip - whether to skip a task when determining frozen | 112 | * Check if the task should be counted as freezable by the freezer |
115 | * state is reached | ||
116 | * @p: task in quesion | ||
117 | * | ||
118 | * This function is used by freezers after establishing %true freezing() to | ||
119 | * test whether a task should be skipped when determining the target frozen | ||
120 | * state is reached. IOW, if this function returns %true, @p is considered | ||
121 | * frozen enough. | ||
122 | */ | 113 | */ |
123 | static inline bool freezer_should_skip(struct task_struct *p) | 114 | static inline int freezer_should_skip(struct task_struct *p) |
124 | { | 115 | { |
125 | /* | 116 | return !!(p->flags & PF_FREEZER_SKIP); |
126 | * The following smp_mb() paired with the one in freezer_count() | ||
127 | * ensures that either freezer_count() sees %true freezing() or we | ||
128 | * see cleared %PF_FREEZER_SKIP and return %false. This makes it | ||
129 | * impossible for a task to slip frozen state testing after | ||
130 | * clearing %PF_FREEZER_SKIP. | ||
131 | */ | ||
132 | smp_mb(); | ||
133 | return p->flags & PF_FREEZER_SKIP; | ||
134 | } | 117 | } |
135 | 118 | ||
136 | /* | 119 | /* |
137 | * These macros are intended to be used whenever you want allow a sleeping | 120 | * Tell the freezer that the current task should be frozen by it |
138 | * task to be frozen. Note that neither return any clear indication of | ||
139 | * whether a freeze event happened while in this function. | ||
140 | */ | 121 | */ |
141 | 122 | static inline void set_freezable(void) | |
142 | /* Like schedule(), but should not block the freezer. */ | 123 | { |
143 | #define freezable_schedule() \ | 124 | current->flags &= ~PF_NOFREEZE; |
144 | ({ \ | 125 | } |
145 | freezer_do_not_count(); \ | ||
146 | schedule(); \ | ||
147 | freezer_count(); \ | ||
148 | }) | ||
149 | |||
150 | /* Like schedule_timeout_killable(), but should not block the freezer. */ | ||
151 | #define freezable_schedule_timeout_killable(timeout) \ | ||
152 | ({ \ | ||
153 | long __retval; \ | ||
154 | freezer_do_not_count(); \ | ||
155 | __retval = schedule_timeout_killable(timeout); \ | ||
156 | freezer_count(); \ | ||
157 | __retval; \ | ||
158 | }) | ||
159 | 126 | ||
160 | /* | 127 | /* |
161 | * Freezer-friendly wrappers around wait_event_interruptible(), | 128 | * Tell the freezer that the current task should be frozen by it and that it |
162 | * wait_event_killable() and wait_event_interruptible_timeout(), originally | 129 | * should send a fake signal to the task to freeze it. |
163 | * defined in <linux/wait.h> | ||
164 | */ | 130 | */ |
131 | static inline void set_freezable_with_signal(void) | ||
132 | { | ||
133 | current->flags &= ~(PF_NOFREEZE | PF_FREEZER_NOSIG); | ||
134 | } | ||
165 | 135 | ||
166 | #define wait_event_freezekillable(wq, condition) \ | 136 | /* |
167 | ({ \ | 137 | * Freezer-friendly wrappers around wait_event_interruptible() and |
168 | int __retval; \ | 138 | * wait_event_interruptible_timeout(), originally defined in <linux/wait.h> |
169 | freezer_do_not_count(); \ | 139 | */ |
170 | __retval = wait_event_killable(wq, (condition)); \ | ||
171 | freezer_count(); \ | ||
172 | __retval; \ | ||
173 | }) | ||
174 | 140 | ||
175 | #define wait_event_freezable(wq, condition) \ | 141 | #define wait_event_freezable(wq, condition) \ |
176 | ({ \ | 142 | ({ \ |
177 | int __retval; \ | 143 | int __retval; \ |
178 | for (;;) { \ | 144 | do { \ |
179 | __retval = wait_event_interruptible(wq, \ | 145 | __retval = wait_event_interruptible(wq, \ |
180 | (condition) || freezing(current)); \ | 146 | (condition) || freezing(current)); \ |
181 | if (__retval || (condition)) \ | 147 | if (__retval && !freezing(current)) \ |
182 | break; \ | 148 | break; \ |
183 | try_to_freeze(); \ | 149 | else if (!(condition)) \ |
184 | } \ | 150 | __retval = -ERESTARTSYS; \ |
151 | } while (try_to_freeze()); \ | ||
185 | __retval; \ | 152 | __retval; \ |
186 | }) | 153 | }) |
187 | 154 | ||
155 | |||
188 | #define wait_event_freezable_timeout(wq, condition, timeout) \ | 156 | #define wait_event_freezable_timeout(wq, condition, timeout) \ |
189 | ({ \ | 157 | ({ \ |
190 | long __retval = timeout; \ | 158 | long __retval = timeout; \ |
191 | for (;;) { \ | 159 | do { \ |
192 | __retval = wait_event_interruptible_timeout(wq, \ | 160 | __retval = wait_event_interruptible_timeout(wq, \ |
193 | (condition) || freezing(current), \ | 161 | (condition) || freezing(current), \ |
194 | __retval); \ | 162 | __retval); \ |
195 | if (__retval <= 0 || (condition)) \ | 163 | } while (try_to_freeze()); \ |
196 | break; \ | ||
197 | try_to_freeze(); \ | ||
198 | } \ | ||
199 | __retval; \ | 164 | __retval; \ |
200 | }) | 165 | }) |
201 | |||
202 | #else /* !CONFIG_FREEZER */ | 166 | #else /* !CONFIG_FREEZER */ |
203 | static inline bool frozen(struct task_struct *p) { return false; } | 167 | static inline int frozen(struct task_struct *p) { return 0; } |
204 | static inline bool freezing(struct task_struct *p) { return false; } | 168 | static inline int freezing(struct task_struct *p) { return 0; } |
205 | static inline void __thaw_task(struct task_struct *t) {} | 169 | static inline void set_freeze_flag(struct task_struct *p) {} |
206 | 170 | static inline void clear_freeze_flag(struct task_struct *p) {} | |
207 | static inline bool __refrigerator(bool check_kthr_stop) { return false; } | 171 | static inline int thaw_process(struct task_struct *p) { return 1; } |
208 | static inline int freeze_processes(void) { return -ENOSYS; } | 172 | |
209 | static inline int freeze_kernel_threads(void) { return -ENOSYS; } | 173 | static inline void refrigerator(void) {} |
174 | static inline int freeze_processes(void) { BUG(); return 0; } | ||
210 | static inline void thaw_processes(void) {} | 175 | static inline void thaw_processes(void) {} |
211 | static inline void thaw_kernel_threads(void) {} | ||
212 | 176 | ||
213 | static inline bool try_to_freeze_nowarn(void) { return false; } | 177 | static inline int try_to_freeze(void) { return 0; } |
214 | static inline bool try_to_freeze(void) { return false; } | ||
215 | 178 | ||
216 | static inline void freezer_do_not_count(void) {} | 179 | static inline void freezer_do_not_count(void) {} |
217 | static inline void freezer_count(void) {} | 180 | static inline void freezer_count(void) {} |
218 | static inline int freezer_should_skip(struct task_struct *p) { return 0; } | 181 | static inline int freezer_should_skip(struct task_struct *p) { return 0; } |
219 | static inline void set_freezable(void) {} | 182 | static inline void set_freezable(void) {} |
220 | 183 | static inline void set_freezable_with_signal(void) {} | |
221 | #define freezable_schedule() schedule() | ||
222 | |||
223 | #define freezable_schedule_timeout_killable(timeout) \ | ||
224 | schedule_timeout_killable(timeout) | ||
225 | 184 | ||
226 | #define wait_event_freezable(wq, condition) \ | 185 | #define wait_event_freezable(wq, condition) \ |
227 | wait_event_interruptible(wq, condition) | 186 | wait_event_interruptible(wq, condition) |
@@ -229,9 +188,6 @@ static inline void set_freezable(void) {} | |||
229 | #define wait_event_freezable_timeout(wq, condition, timeout) \ | 188 | #define wait_event_freezable_timeout(wq, condition, timeout) \ |
230 | wait_event_interruptible_timeout(wq, condition, timeout) | 189 | wait_event_interruptible_timeout(wq, condition, timeout) |
231 | 190 | ||
232 | #define wait_event_freezekillable(wq, condition) \ | ||
233 | wait_event_killable(wq, condition) | ||
234 | |||
235 | #endif /* !CONFIG_FREEZER */ | 191 | #endif /* !CONFIG_FREEZER */ |
236 | 192 | ||
237 | #endif /* FREEZER_H_INCLUDED */ | 193 | #endif /* FREEZER_H_INCLUDED */ |