aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2014-10-29 07:21:57 -0400
committerIngo Molnar <mingo@kernel.org>2014-11-04 01:17:45 -0500
commit36df04bc5273a046f53b5e359febc1225f85aa7b (patch)
treedac2719884ca16c1c11b003be614ad0a1bb1fee0
parentcb6538e740d7543cd989128625cf8cac4b471e0a (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.h38
-rw-r--r--include/linux/wait.h57
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 */
298static inline bool frozen(struct task_struct *p) { return false; } 269static inline bool frozen(struct task_struct *p) { return false; }
299static inline bool freezing(struct task_struct *p) { return false; } 270static 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; \