Blame view
include/linux/freezer.h
9.99 KB
7dfb71030
|
1 |
/* Freezer declarations */ |
831441862
|
2 3 |
#ifndef FREEZER_H_INCLUDED #define FREEZER_H_INCLUDED |
0f9548ca1
|
4 |
#include <linux/debug_locks.h> |
5c543eff6
|
5 |
#include <linux/sched.h> |
e42837bcd
|
6 |
#include <linux/wait.h> |
a3201227f
|
7 |
#include <linux/atomic.h> |
5c543eff6
|
8 |
|
8174f1503
|
9 |
#ifdef CONFIG_FREEZER |
a3201227f
|
10 11 12 |
extern atomic_t system_freezing_cnt; /* nr of freezing conds in effect */ extern bool pm_freezing; /* PM freezing in effect */ extern bool pm_nosig_freezing; /* PM nosig freezing in effect */ |
7dfb71030
|
13 |
/* |
957d1282b
|
14 15 16 17 18 |
* Timeout for stopping processes */ extern unsigned int freeze_timeout_msecs; /* |
7dfb71030
|
19 20 |
* Check if a process has been frozen */ |
948246f70
|
21 |
static inline bool frozen(struct task_struct *p) |
7dfb71030
|
22 23 24 |
{ return p->flags & PF_FROZEN; } |
a3201227f
|
25 |
extern bool freezing_slow_path(struct task_struct *p); |
7dfb71030
|
26 27 |
/* |
a3201227f
|
28 |
* Check if there is a request to freeze a process |
7dfb71030
|
29 |
*/ |
a3201227f
|
30 |
static inline bool freezing(struct task_struct *p) |
7dfb71030
|
31 |
{ |
a3201227f
|
32 33 34 |
if (likely(!atomic_read(&system_freezing_cnt))) return false; return freezing_slow_path(p); |
7dfb71030
|
35 |
} |
dc52ddc0e
|
36 |
/* Takes and releases task alloc lock using task_lock() */ |
a5be2d0d1
|
37 |
extern void __thaw_task(struct task_struct *t); |
7dfb71030
|
38 |
|
8a32c441c
|
39 |
extern bool __refrigerator(bool check_kthr_stop); |
7dfb71030
|
40 |
extern int freeze_processes(void); |
2aede851d
|
41 |
extern int freeze_kernel_threads(void); |
a9b6f562f
|
42 |
extern void thaw_processes(void); |
181e9bdef
|
43 |
extern void thaw_kernel_threads(void); |
7dfb71030
|
44 |
|
416ad3c9c
|
45 46 47 48 49 |
/* * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION * If try_to_freeze causes a lockdep warning it means the caller may deadlock */ static inline bool try_to_freeze_unsafe(void) |
7dfb71030
|
50 |
{ |
a0acae0e8
|
51 52 53 |
might_sleep(); if (likely(!freezing(current))) return false; |
8a32c441c
|
54 |
return __refrigerator(false); |
7dfb71030
|
55 |
} |
ff39593ad
|
56 |
|
416ad3c9c
|
57 58 |
static inline bool try_to_freeze(void) { |
0f9548ca1
|
59 60 |
if (!(current->flags & PF_NOFREEZE)) debug_check_no_locks_held(); |
416ad3c9c
|
61 62 |
return try_to_freeze_unsafe(); } |
839e3407d
|
63 |
extern bool freeze_task(struct task_struct *p); |
34b087e48
|
64 |
extern bool set_freezable(void); |
8174f1503
|
65 |
|
dc52ddc0e
|
66 |
#ifdef CONFIG_CGROUP_FREEZER |
22b4e111f
|
67 |
extern bool cgroup_freezing(struct task_struct *task); |
dc52ddc0e
|
68 |
#else /* !CONFIG_CGROUP_FREEZER */ |
22b4e111f
|
69 |
static inline bool cgroup_freezing(struct task_struct *task) |
5a7aadfe2
|
70 |
{ |
22b4e111f
|
71 |
return false; |
5a7aadfe2
|
72 |
} |
dc52ddc0e
|
73 |
#endif /* !CONFIG_CGROUP_FREEZER */ |
ba96a0c88
|
74 75 76 77 78 79 80 |
/* * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it * calls wait_for_completion(&vfork) and reset right after it returns from this * function. Next, the parent should call try_to_freeze() to freeze itself * appropriately in case the child has exited before the freezing of tasks is * complete. However, we don't want kernel threads to be frozen in unexpected * places, so we allow them to block freeze_processes() instead or to set |
467de1fc6
|
81 82 83 84 |
* PF_NOFREEZE if needed. Fortunately, in the ____call_usermodehelper() case the * parent won't really block freeze_processes(), since ____call_usermodehelper() * (the child) does a little before exec/exit and it can't be frozen before * waking up the parent. |
ba96a0c88
|
85 |
*/ |
467de1fc6
|
86 |
|
dd67d32db
|
87 88 89 90 91 92 93 94 95 96 97 |
/** * freezer_do_not_count - tell freezer to ignore %current * * Tell freezers to ignore the current task when determining whether the * target frozen state is reached. IOW, the current task will be * considered frozen enough by freezers. * * The caller shouldn't do anything which isn't allowed for a frozen task * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair * wrap a scheduling operation and nothing much else. */ |
ba96a0c88
|
98 99 |
static inline void freezer_do_not_count(void) { |
467de1fc6
|
100 |
current->flags |= PF_FREEZER_SKIP; |
ba96a0c88
|
101 |
} |
dd67d32db
|
102 103 104 105 106 107 |
/** * freezer_count - tell freezer to stop ignoring %current * * Undo freezer_do_not_count(). It tells freezers that %current should be * considered again and tries to freeze if freezing condition is already in * effect. |
ba96a0c88
|
108 109 110 |
*/ static inline void freezer_count(void) { |
467de1fc6
|
111 |
current->flags &= ~PF_FREEZER_SKIP; |
dd67d32db
|
112 113 114 115 116 117 |
/* * If freezing is in progress, the following paired with smp_mb() * in freezer_should_skip() ensures that either we see %true * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. */ smp_mb(); |
467de1fc6
|
118 |
try_to_freeze(); |
ba96a0c88
|
119 |
} |
416ad3c9c
|
120 121 122 123 124 125 126 |
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ static inline void freezer_count_unsafe(void) { current->flags &= ~PF_FREEZER_SKIP; smp_mb(); try_to_freeze_unsafe(); } |
dd67d32db
|
127 128 129 130 131 132 133 134 135 |
/** * freezer_should_skip - whether to skip a task when determining frozen * state is reached * @p: task in quesion * * This function is used by freezers after establishing %true freezing() to * test whether a task should be skipped when determining the target frozen * state is reached. IOW, if this function returns %true, @p is considered * frozen enough. |
ba96a0c88
|
136 |
*/ |
dd67d32db
|
137 |
static inline bool freezer_should_skip(struct task_struct *p) |
ba96a0c88
|
138 |
{ |
dd67d32db
|
139 140 141 142 143 144 145 146 147 |
/* * The following smp_mb() paired with the one in freezer_count() * ensures that either freezer_count() sees %true freezing() or we * see cleared %PF_FREEZER_SKIP and return %false. This makes it * impossible for a task to slip frozen state testing after * clearing %PF_FREEZER_SKIP. */ smp_mb(); return p->flags & PF_FREEZER_SKIP; |
ba96a0c88
|
148 |
} |
ff39593ad
|
149 |
|
831441862
|
150 |
/* |
8ee492d65
|
151 |
* These functions are intended to be used whenever you want allow a sleeping |
5d8f72b55
|
152 153 |
* task to be frozen. Note that neither return any clear indication of * whether a freeze event happened while in this function. |
d310310cb
|
154 155 156 |
*/ /* Like schedule(), but should not block the freezer. */ |
8ee492d65
|
157 158 159 160 161 162 |
static inline void freezable_schedule(void) { freezer_do_not_count(); schedule(); freezer_count(); } |
d310310cb
|
163 |
|
416ad3c9c
|
164 |
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ |
8ee492d65
|
165 166 167 168 169 170 |
static inline void freezable_schedule_unsafe(void) { freezer_do_not_count(); schedule(); freezer_count_unsafe(); } |
416ad3c9c
|
171 |
|
dd5ec0f4e
|
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
/* * Like freezable_schedule_timeout(), but should not block the freezer. Do not * call this with locks held. */ static inline long freezable_schedule_timeout(long timeout) { long __retval; freezer_do_not_count(); __retval = schedule_timeout(timeout); freezer_count(); return __retval; } /* * Like schedule_timeout_interruptible(), but should not block the freezer. Do not * call this with locks held. */ static inline long freezable_schedule_timeout_interruptible(long timeout) { long __retval; freezer_do_not_count(); __retval = schedule_timeout_interruptible(timeout); freezer_count(); return __retval; } |
d310310cb
|
197 |
/* Like schedule_timeout_killable(), but should not block the freezer. */ |
8ee492d65
|
198 199 200 201 202 203 204 205 |
static inline long freezable_schedule_timeout_killable(long timeout) { long __retval; freezer_do_not_count(); __retval = schedule_timeout_killable(timeout); freezer_count(); return __retval; } |
d310310cb
|
206 |
|
416ad3c9c
|
207 |
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ |
8ee492d65
|
208 209 210 211 212 213 214 215 |
static inline long freezable_schedule_timeout_killable_unsafe(long timeout) { long __retval; freezer_do_not_count(); __retval = schedule_timeout_killable(timeout); freezer_count_unsafe(); return __retval; } |
416ad3c9c
|
216 |
|
d310310cb
|
217 |
/* |
dd5ec0f4e
|
218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
* Like schedule_hrtimeout_range(), but should not block the freezer. Do not * call this with locks held. */ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, unsigned long delta, const enum hrtimer_mode mode) { int __retval; freezer_do_not_count(); __retval = schedule_hrtimeout_range(expires, delta, mode); freezer_count(); return __retval; } /* |
f06ac72e9
|
232 233 234 |
* Freezer-friendly wrappers around wait_event_interruptible(), * wait_event_killable() and wait_event_interruptible_timeout(), originally * defined in <linux/wait.h> |
e42837bcd
|
235 |
*/ |
f06ac72e9
|
236 237 238 |
#define wait_event_freezekillable(wq, condition) \ ({ \ int __retval; \ |
6f35c4abd
|
239 240 241 |
freezer_do_not_count(); \ __retval = wait_event_killable(wq, (condition)); \ freezer_count(); \ |
f06ac72e9
|
242 243 |
__retval; \ }) |
5853cc2a8
|
244 245 246 247 248 249 250 251 252 |
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ #define wait_event_freezekillable_unsafe(wq, condition) \ ({ \ int __retval; \ freezer_do_not_count(); \ __retval = wait_event_killable(wq, (condition)); \ freezer_count_unsafe(); \ __retval; \ }) |
e42837bcd
|
253 254 255 |
#define wait_event_freezable(wq, condition) \ ({ \ int __retval; \ |
b01235861
|
256 257 258 |
freezer_do_not_count(); \ __retval = wait_event_interruptible(wq, (condition)); \ freezer_count(); \ |
e42837bcd
|
259 260 |
__retval; \ }) |
e42837bcd
|
261 262 263 |
#define wait_event_freezable_timeout(wq, condition, timeout) \ ({ \ long __retval = timeout; \ |
b01235861
|
264 265 266 267 |
freezer_do_not_count(); \ __retval = wait_event_interruptible_timeout(wq, (condition), \ __retval); \ freezer_count(); \ |
e42837bcd
|
268 269 |
__retval; \ }) |
24b7ead3f
|
270 |
|
dd5ec0f4e
|
271 272 273 274 275 276 277 278 |
#define wait_event_freezable_exclusive(wq, condition) \ ({ \ int __retval; \ freezer_do_not_count(); \ __retval = wait_event_interruptible_exclusive(wq, condition); \ freezer_count(); \ __retval; \ }) |
8174f1503
|
279 |
#else /* !CONFIG_FREEZER */ |
948246f70
|
280 |
static inline bool frozen(struct task_struct *p) { return false; } |
a3201227f
|
281 |
static inline bool freezing(struct task_struct *p) { return false; } |
62c9ea6b1
|
282 |
static inline void __thaw_task(struct task_struct *t) {} |
7dfb71030
|
283 |
|
8a32c441c
|
284 |
static inline bool __refrigerator(bool check_kthr_stop) { return false; } |
2aede851d
|
285 286 |
static inline int freeze_processes(void) { return -ENOSYS; } static inline int freeze_kernel_threads(void) { return -ENOSYS; } |
7dfb71030
|
287 |
static inline void thaw_processes(void) {} |
181e9bdef
|
288 |
static inline void thaw_kernel_threads(void) {} |
7dfb71030
|
289 |
|
e5f576217
|
290 |
static inline bool try_to_freeze_nowarn(void) { return false; } |
a0acae0e8
|
291 |
static inline bool try_to_freeze(void) { return false; } |
7dfb71030
|
292 |
|
ba96a0c88
|
293 294 295 |
static inline void freezer_do_not_count(void) {} static inline void freezer_count(void) {} static inline int freezer_should_skip(struct task_struct *p) { return 0; } |
831441862
|
296 |
static inline void set_freezable(void) {} |
e42837bcd
|
297 |
|
d310310cb
|
298 |
#define freezable_schedule() schedule() |
416ad3c9c
|
299 |
#define freezable_schedule_unsafe() schedule() |
dd5ec0f4e
|
300 301 302 303 |
#define freezable_schedule_timeout(timeout) schedule_timeout(timeout) #define freezable_schedule_timeout_interruptible(timeout) \ schedule_timeout_interruptible(timeout) |
d310310cb
|
304 305 |
#define freezable_schedule_timeout_killable(timeout) \ schedule_timeout_killable(timeout) |
416ad3c9c
|
306 307 |
#define freezable_schedule_timeout_killable_unsafe(timeout) \ schedule_timeout_killable(timeout) |
dd5ec0f4e
|
308 309 |
#define freezable_schedule_hrtimeout_range(expires, delta, mode) \ schedule_hrtimeout_range(expires, delta, mode) |
e42837bcd
|
310 311 312 313 314 |
#define wait_event_freezable(wq, condition) \ wait_event_interruptible(wq, condition) #define wait_event_freezable_timeout(wq, condition, timeout) \ wait_event_interruptible_timeout(wq, condition, timeout) |
dd5ec0f4e
|
315 316 |
#define wait_event_freezable_exclusive(wq, condition) \ wait_event_interruptible_exclusive(wq, condition) |
e0c8ea1a6
|
317 318 |
#define wait_event_freezekillable(wq, condition) \ wait_event_killable(wq, condition) |
5853cc2a8
|
319 320 |
#define wait_event_freezekillable_unsafe(wq, condition) \ wait_event_killable(wq, condition) |
8174f1503
|
321 |
#endif /* !CONFIG_FREEZER */ |
831441862
|
322 323 |
#endif /* FREEZER_H_INCLUDED */ |