diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-10-29 07:21:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-11-04 01:17:45 -0500 |
commit | 36df04bc5273a046f53b5e359febc1225f85aa7b (patch) | |
tree | dac2719884ca16c1c11b003be614ad0a1bb1fee0 | |
parent | cb6538e740d7543cd989128625cf8cac4b471e0a (diff) |
sched/wait: Reimplement wait_event_freezable()
Provide better implementations of wait_event_freezable() APIs.
The problem is with freezer_do_not_count(), it hides the thread from
the freezer, even though this thread might not actually freeze/sleep
at all.
Cc: oleg@redhat.com
Cc: Rafael Wysocki <rjw@rjwysocki.net>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Len Brown <len.brown@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: linux-pm@vger.kernel.org
Link: http://lkml.kernel.org/n/tip-d86fz1jmso9wjxa8jfpinp8o@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | include/linux/freezer.h | 38 | ||||
-rw-r--r-- | include/linux/wait.h | 57 |
2 files changed, 57 insertions, 38 deletions
diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 7fd81b8c4897..e203665c0faa 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h | |||
@@ -265,35 +265,6 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, | |||
265 | __retval; \ | 265 | __retval; \ |
266 | }) | 266 | }) |
267 | 267 | ||
268 | #define wait_event_freezable(wq, condition) \ | ||
269 | ({ \ | ||
270 | int __retval; \ | ||
271 | freezer_do_not_count(); \ | ||
272 | __retval = wait_event_interruptible(wq, (condition)); \ | ||
273 | freezer_count(); \ | ||
274 | __retval; \ | ||
275 | }) | ||
276 | |||
277 | #define wait_event_freezable_timeout(wq, condition, timeout) \ | ||
278 | ({ \ | ||
279 | long __retval = timeout; \ | ||
280 | freezer_do_not_count(); \ | ||
281 | __retval = wait_event_interruptible_timeout(wq, (condition), \ | ||
282 | __retval); \ | ||
283 | freezer_count(); \ | ||
284 | __retval; \ | ||
285 | }) | ||
286 | |||
287 | #define wait_event_freezable_exclusive(wq, condition) \ | ||
288 | ({ \ | ||
289 | int __retval; \ | ||
290 | freezer_do_not_count(); \ | ||
291 | __retval = wait_event_interruptible_exclusive(wq, condition); \ | ||
292 | freezer_count(); \ | ||
293 | __retval; \ | ||
294 | }) | ||
295 | |||
296 | |||
297 | #else /* !CONFIG_FREEZER */ | 268 | #else /* !CONFIG_FREEZER */ |
298 | static inline bool frozen(struct task_struct *p) { return false; } | 269 | static inline bool frozen(struct task_struct *p) { return false; } |
299 | static inline bool freezing(struct task_struct *p) { return false; } | 270 | static inline bool freezing(struct task_struct *p) { return false; } |
@@ -331,15 +302,6 @@ static inline void set_freezable(void) {} | |||
331 | #define freezable_schedule_hrtimeout_range(expires, delta, mode) \ | 302 | #define freezable_schedule_hrtimeout_range(expires, delta, mode) \ |
332 | schedule_hrtimeout_range(expires, delta, mode) | 303 | schedule_hrtimeout_range(expires, delta, mode) |
333 | 304 | ||
334 | #define wait_event_freezable(wq, condition) \ | ||
335 | wait_event_interruptible(wq, condition) | ||
336 | |||
337 | #define wait_event_freezable_timeout(wq, condition, timeout) \ | ||
338 | wait_event_interruptible_timeout(wq, condition, timeout) | ||
339 | |||
340 | #define wait_event_freezable_exclusive(wq, condition) \ | ||
341 | wait_event_interruptible_exclusive(wq, condition) | ||
342 | |||
343 | #define wait_event_freezekillable(wq, condition) \ | 305 | #define wait_event_freezekillable(wq, condition) \ |
344 | wait_event_killable(wq, condition) | 306 | wait_event_killable(wq, condition) |
345 | 307 | ||
diff --git a/include/linux/wait.h b/include/linux/wait.h index 0421775e0b9f..2232ed16635a 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h | |||
@@ -267,6 +267,31 @@ do { \ | |||
267 | __wait_event(wq, condition); \ | 267 | __wait_event(wq, condition); \ |
268 | } while (0) | 268 | } while (0) |
269 | 269 | ||
270 | #define __wait_event_freezable(wq, condition) \ | ||
271 | ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0, \ | ||
272 | schedule(); try_to_freeze()) | ||
273 | |||
274 | /** | ||
275 | * wait_event - sleep (or freeze) until a condition gets true | ||
276 | * @wq: the waitqueue to wait on | ||
277 | * @condition: a C expression for the event to wait for | ||
278 | * | ||
279 | * The process is put to sleep (TASK_INTERRUPTIBLE -- so as not to contribute | ||
280 | * to system load) until the @condition evaluates to true. The | ||
281 | * @condition is checked each time the waitqueue @wq is woken up. | ||
282 | * | ||
283 | * wake_up() has to be called after changing any variable that could | ||
284 | * change the result of the wait condition. | ||
285 | */ | ||
286 | #define wait_event_freezable(wq, condition) \ | ||
287 | ({ \ | ||
288 | int __ret = 0; \ | ||
289 | might_sleep(); \ | ||
290 | if (!(condition)) \ | ||
291 | __ret = __wait_event_freezable(wq, condition); \ | ||
292 | __ret; \ | ||
293 | }) | ||
294 | |||
270 | #define __wait_event_timeout(wq, condition, timeout) \ | 295 | #define __wait_event_timeout(wq, condition, timeout) \ |
271 | ___wait_event(wq, ___wait_cond_timeout(condition), \ | 296 | ___wait_event(wq, ___wait_cond_timeout(condition), \ |
272 | TASK_UNINTERRUPTIBLE, 0, timeout, \ | 297 | TASK_UNINTERRUPTIBLE, 0, timeout, \ |
@@ -300,6 +325,24 @@ do { \ | |||
300 | __ret; \ | 325 | __ret; \ |
301 | }) | 326 | }) |
302 | 327 | ||
328 | #define __wait_event_freezable_timeout(wq, condition, timeout) \ | ||
329 | ___wait_event(wq, ___wait_cond_timeout(condition), \ | ||
330 | TASK_INTERRUPTIBLE, 0, timeout, \ | ||
331 | __ret = schedule_timeout(__ret); try_to_freeze()) | ||
332 | |||
333 | /* | ||
334 | * like wait_event_timeout() -- except it uses TASK_INTERRUPTIBLE to avoid | ||
335 | * increasing load and is freezable. | ||
336 | */ | ||
337 | #define wait_event_freezable_timeout(wq, condition, timeout) \ | ||
338 | ({ \ | ||
339 | long __ret = timeout; \ | ||
340 | might_sleep(); \ | ||
341 | if (!___wait_cond_timeout(condition)) \ | ||
342 | __ret = __wait_event_freezable_timeout(wq, condition, timeout); \ | ||
343 | __ret; \ | ||
344 | }) | ||
345 | |||
303 | #define __wait_event_cmd(wq, condition, cmd1, cmd2) \ | 346 | #define __wait_event_cmd(wq, condition, cmd1, cmd2) \ |
304 | (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0, \ | 347 | (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0, \ |
305 | cmd1; schedule(); cmd2) | 348 | cmd1; schedule(); cmd2) |
@@ -480,6 +523,20 @@ do { \ | |||
480 | }) | 523 | }) |
481 | 524 | ||
482 | 525 | ||
526 | #define __wait_event_freezable_exclusive(wq, condition) \ | ||
527 | ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 1, 0, \ | ||
528 | schedule(); try_to_freeze()) | ||
529 | |||
530 | #define wait_event_freezable_exclusive(wq, condition) \ | ||
531 | ({ \ | ||
532 | int __ret = 0; \ | ||
533 | might_sleep(); \ | ||
534 | if (!(condition)) \ | ||
535 | __ret = __wait_event_freezable_exclusive(wq, condition);\ | ||
536 | __ret; \ | ||
537 | }) | ||
538 | |||
539 | |||
483 | #define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \ | 540 | #define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \ |
484 | ({ \ | 541 | ({ \ |
485 | int __ret = 0; \ | 542 | int __ret = 0; \ |