]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/linux/wait.h
sched/wait: Collapse __wait_event_interruptible_timeout()
[karo-tx-linux.git] / include / linux / wait.h
index a67fc1635592fd34717ef559049924b1add707ca..a79fb15c1dd445068496058436bad16d52eedf41 100644 (file)
@@ -179,19 +179,54 @@ wait_queue_head_t *bit_waitqueue(void *, int);
 #define wake_up_interruptible_sync_poll(x, m)                          \
        __wake_up_sync_key((x), TASK_INTERRUPTIBLE, 1, (void *) (m))
 
-#define __wait_event(wq, condition)                                    \
+#define ___wait_cond_timeout(condition, ret)                           \
+({                                                                     \
+       bool __cond = (condition);                                      \
+       if (__cond && !ret)                                             \
+               ret = 1;                                                \
+       __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 (;;) {                                                      \
-               prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \
+               if (exclusive)                                          \
+                       prepare_to_wait_exclusive(&wq, &__wait, state); \
+               else                                                    \
+                       prepare_to_wait(&wq, &__wait, state);           \
+                                                                       \
                if (condition)                                          \
                        break;                                          \
-               schedule();                                             \
+                                                                       \
+               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)                                    \
+       ___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0,           \
+                     ___wait_nop_ret, schedule())
+
 /**
  * wait_event - sleep until a condition gets true
  * @wq: the waitqueue to wait on
@@ -212,21 +247,9 @@ do {                                                                       \
 } while (0)
 
 #define __wait_event_timeout(wq, condition, ret)                       \
-do {                                                                   \
-       DEFINE_WAIT(__wait);                                            \
-                                                                       \
-       for (;;) {                                                      \
-               prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE);    \
-               if (condition)                                          \
-                       break;                                          \
-               ret = schedule_timeout(ret);                            \
-               if (!ret)                                               \
-                       break;                                          \
-       }                                                               \
-       if (!ret && (condition))                                        \
-               ret = 1;                                                \
-       finish_wait(&wq, &__wait);                                      \
-} while (0)
+       ___wait_event(wq, ___wait_cond_timeout(condition, ret),         \
+                     TASK_UNINTERRUPTIBLE, 0, ret,                     \
+                     ret = schedule_timeout(ret))
 
 /**
  * wait_event_timeout - sleep until a condition gets true or a timeout elapses
@@ -254,22 +277,8 @@ do {                                                                       \
 })
 
 #define __wait_event_interruptible(wq, condition, ret)                 \
-do {                                                                   \
-       DEFINE_WAIT(__wait);                                            \
-                                                                       \
-       for (;;) {                                                      \
-               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
-               if (condition)                                          \
-                       break;                                          \
-               if (!signal_pending(current)) {                         \
-                       schedule();                                     \
-                       continue;                                       \
-               }                                                       \
-               ret = -ERESTARTSYS;                                     \
-               break;                                                  \
-       }                                                               \
-       finish_wait(&wq, &__wait);                                      \
-} while (0)
+       ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, ret,        \
+                     schedule())
 
 /**
  * wait_event_interruptible - sleep until a condition gets true
@@ -295,26 +304,9 @@ do {                                                                       \
 })
 
 #define __wait_event_interruptible_timeout(wq, condition, ret)         \
-do {                                                                   \
-       DEFINE_WAIT(__wait);                                            \
-                                                                       \
-       for (;;) {                                                      \
-               prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
-               if (condition)                                          \
-                       break;                                          \
-               if (!signal_pending(current)) {                         \
-                       ret = schedule_timeout(ret);                    \
-                       if (!ret)                                       \
-                               break;                                  \
-                       continue;                                       \
-               }                                                       \
-               ret = -ERESTARTSYS;                                     \
-               break;                                                  \
-       }                                                               \
-       if (!ret && (condition))                                        \
-               ret = 1;                                                \
-       finish_wait(&wq, &__wait);                                      \
-} while (0)
+       ___wait_event(wq, ___wait_cond_timeout(condition, ret),         \
+                     TASK_INTERRUPTIBLE, 0, ret,                       \
+                     ret = schedule_timeout(ret))
 
 /**
  * wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
@@ -430,24 +422,24 @@ do {                                                                      \
 
 #define __wait_event_interruptible_exclusive(wq, condition, ret)       \
 do {                                                                   \
+       __label__ __out;                                                \
        DEFINE_WAIT(__wait);                                            \
                                                                        \
        for (;;) {                                                      \
                prepare_to_wait_exclusive(&wq, &__wait,                 \
                                        TASK_INTERRUPTIBLE);            \
-               if (condition) {                                        \
-                       finish_wait(&wq, &__wait);                      \
+               if (condition)                                          \
                        break;                                          \
-               }                                                       \
-               if (!signal_pending(current)) {                         \
-                       schedule();                                     \
-                       continue;                                       \
-               }                                                       \
-               ret = -ERESTARTSYS;                                     \
-               abort_exclusive_wait(&wq, &__wait,                      \
+               if (signal_pending(current)) {                          \
+                       ret = -ERESTARTSYS;                             \
+                       abort_exclusive_wait(&wq, &__wait,              \
                                TASK_INTERRUPTIBLE, NULL);              \
-               break;                                                  \
+                       goto __out;                                     \
+               }                                                       \
+               schedule();                                             \
        }                                                               \
+       finish_wait(&wq, &__wait);                                      \
+__out: ;                                                               \
 } while (0)
 
 #define wait_event_interruptible_exclusive(wq, condition)              \
@@ -818,7 +810,7 @@ do {                                                                        \
                                                                        \
        for (;;) {                                                      \
                prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);      \
-               if (condition)                                          \
+               if (___wait_cond_timeout(condition, ret))               \
                        break;                                          \
                if (signal_pending(current)) {                          \
                        ret = -ERESTARTSYS;                             \
@@ -827,8 +819,6 @@ do {                                                                        \
                spin_unlock_irq(&lock);                                 \
                ret = schedule_timeout(ret);                            \
                spin_lock_irq(&lock);                                   \
-               if (!ret)                                               \
-                       break;                                          \
        }                                                               \
        finish_wait(&wq, &__wait);                                      \
 } while (0)