aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/wait.h
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2013-10-02 05:22:19 -0400
committerIngo Molnar <mingo@kernel.org>2013-10-04 04:14:44 -0400
commit2953ef246b058989657e1e77b36b67566ac06f7b (patch)
treea63c8aff38d86f4a7db7eb4e5111dc46076cc268 /include/linux/wait.h
parent2f2a2b60adf368bacd6acd2116c01e32caf936c4 (diff)
sched/wait: Change timeout logic
Commit 4c663cf ("wait: fix false timeouts when using wait_event_timeout()") introduced an additional condition check after a timeout but there's a few issues; - it forgot one site - it put the check after the main loop; not at the actual timeout check. Cure both; by wrapping the condition (as suggested by Oleg), this avoids double evaluation of 'condition' which could be quite big. Reviewed-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20131002092528.028892896@infradead.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include/linux/wait.h')
-rw-r--r--include/linux/wait.h24
1 files changed, 11 insertions, 13 deletions
diff --git a/include/linux/wait.h b/include/linux/wait.h
index ccf0c529fd37..b2afd665e4ea 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -179,6 +179,14 @@ wait_queue_head_t *bit_waitqueue(void *, int);
179#define wake_up_interruptible_sync_poll(x, m) \ 179#define wake_up_interruptible_sync_poll(x, m) \
180 __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m)) 180 __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m))
181 181
182#define ___wait_cond_timeout(condition, ret) \
183({ \
184 bool __cond = (condition); \
185 if (__cond && !ret) \
186 ret = 1; \
187 __cond || !ret; \
188})
189
182#define __wait_event(wq, condition) \ 190#define __wait_event(wq, condition) \
183do { \ 191do { \
184 DEFINE_WAIT(__wait); \ 192 DEFINE_WAIT(__wait); \
@@ -217,14 +225,10 @@ do { \
217 \ 225 \
218 for (;;) { \ 226 for (;;) { \
219 prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ 227 prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
220 if (condition) \ 228 if (___wait_cond_timeout(condition, ret)) \
221 break; \ 229 break; \
222 ret = schedule_timeout(ret); \ 230 ret = schedule_timeout(ret); \
223 if (!ret) \
224 break; \
225 } \ 231 } \
226 if (!ret && (condition)) \
227 ret = 1; \
228 finish_wait(&wq, &__wait); \ 232 finish_wait(&wq, &__wait); \
229} while (0) 233} while (0)
230 234
@@ -299,18 +303,14 @@ do { \
299 \ 303 \
300 for (;;) { \ 304 for (;;) { \
301 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ 305 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
302 if (condition) \ 306 if (___wait_cond_timeout(condition, ret)) \
303 break; \ 307 break; \
304 if (signal_pending(current)) { \ 308 if (signal_pending(current)) { \
305 ret = -ERESTARTSYS; \ 309 ret = -ERESTARTSYS; \
306 break; \ 310 break; \
307 } \ 311 } \
308 ret = schedule_timeout(ret); \ 312 ret = schedule_timeout(ret); \
309 if (!ret) \
310 break; \
311 } \ 313 } \
312 if (!ret && (condition)) \
313 ret = 1; \
314 finish_wait(&wq, &__wait); \ 314 finish_wait(&wq, &__wait); \
315} while (0) 315} while (0)
316 316
@@ -815,7 +815,7 @@ do { \
815 \ 815 \
816 for (;;) { \ 816 for (;;) { \
817 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ 817 prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \
818 if (condition) \ 818 if (___wait_cond_timeout(condition, ret)) \
819 break; \ 819 break; \
820 if (signal_pending(current)) { \ 820 if (signal_pending(current)) { \
821 ret = -ERESTARTSYS; \ 821 ret = -ERESTARTSYS; \
@@ -824,8 +824,6 @@ do { \
824 spin_unlock_irq(&lock); \ 824 spin_unlock_irq(&lock); \
825 ret = schedule_timeout(ret); \ 825 ret = schedule_timeout(ret); \
826 spin_lock_irq(&lock); \ 826 spin_lock_irq(&lock); \
827 if (!ret) \
828 break; \
829 } \ 827 } \
830 finish_wait(&wq, &__wait); \ 828 finish_wait(&wq, &__wait); \
831} while (0) 829} while (0)