sched/wait: Introduce ___wait_event()
authorPeter Zijlstra <peterz@infradead.org>
Wed, 2 Oct 2013 09:22:21 +0000 (11:22 +0200)
committerIngo Molnar <mingo@kernel.org>
Fri, 4 Oct 2013 08:14:46 +0000 (10:14 +0200)
There's far too much duplication in the __wait_event macros; in order
to fix this introduce ___wait_event() a macro with the capability to
replace most other macros.

With the previous patches changing the various __wait_event*()
implementations to be more uniform; we can now collapse the lot
without also changing generated code.

Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20131002092528.181897111@infradead.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
include/linux/wait.h

index 7d7819dafcc566ad4f77e0bf26a700bbf8e9e6d4..29d0249e03ababd8cffdb944e15536344382649e 100644 (file)
@@ -187,6 +187,42 @@ wait_queue_head_t *bit_waitqueue(void *, int);
        __cond || !ret;                                                 \
 })
 
+#define ___wait_signal_pending(state)                                  \
+       ((state == TASK_INTERRUPTIBLE && signal_pending(current)) ||    \
+        (state == TASK_KILLABLE && fatal_signal_pending(current)))
+
+#define ___wait_nop_ret                int ret __always_unused
+
+#define ___wait_event(wq, condition, state, exclusive, ret, cmd)       \
+do {                                                                   \
+       __label__ __out;                                                \
+       DEFINE_WAIT(__wait);                                            \
+                                                                       \
+       for (;;) {                                                      \
+               if (exclusive)                                          \
+                       prepare_to_wait_exclusive(&wq, &__wait, state); \
+               else                                                    \
+                       prepare_to_wait(&wq, &__wait, state);           \
+                                                                       \
+               if (condition)                                          \
+                       break;                                          \
+                                                                       \
+               if (___wait_signal_pending(state)) {                    \
+                       ret = -ERESTARTSYS;                             \
+                       if (exclusive) {                                \
+                               abort_exclusive_wait(&wq, &__wait,      \
+                                                    state, NULL);      \
+                               goto __out;                             \
+                       }                                               \
+                       break;                                          \
+               }                                                       \
+                                                                       \
+               cmd;                                                    \
+       }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+__out: ;                                                               \
+} while (0)
+
 #define __wait_event(wq, condition)                                    \
 do {                                                                   \
        DEFINE_WAIT(__wait);                                            \