]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/linux/wait.h
sched/wait: Reimplement wait_event_freezable()
[karo-tx-linux.git] / include / linux / wait.h
index e4a8eb9312eabb508c045b8e0274ae7dd3809a38..2232ed16635ae0929c97f62e1c8c1b09109f0649 100644 (file)
@@ -13,9 +13,12 @@ typedef struct __wait_queue wait_queue_t;
 typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
 int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
 
+/* __wait_queue::flags */
+#define WQ_FLAG_EXCLUSIVE      0x01
+#define WQ_FLAG_WOKEN          0x02
+
 struct __wait_queue {
        unsigned int            flags;
-#define WQ_FLAG_EXCLUSIVE      0x01
        void                    *private;
        wait_queue_func_t       func;
        struct list_head        task_list;
@@ -258,11 +261,37 @@ __out:    __ret;                                                          \
  */
 #define wait_event(wq, condition)                                      \
 do {                                                                   \
+       might_sleep();                                                  \
        if (condition)                                                  \
                break;                                                  \
        __wait_event(wq, condition);                                    \
 } while (0)
 
+#define __wait_event_freezable(wq, condition)                          \
+       ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,          \
+                           schedule(); try_to_freeze())
+
+/**
+ * wait_event - sleep (or freeze) until a condition gets true
+ * @wq: the waitqueue to wait on
+ * @condition: a C expression for the event to wait for
+ *
+ * The process is put to sleep (TASK_INTERRUPTIBLE -- so as not to contribute
+ * to system load) until the @condition evaluates to true. The
+ * @condition is checked each time the waitqueue @wq is woken up.
+ *
+ * wake_up() has to be called after changing any variable that could
+ * change the result of the wait condition.
+ */
+#define wait_event_freezable(wq, condition)                            \
+({                                                                     \
+       int __ret = 0;                                                  \
+       might_sleep();                                                  \
+       if (!(condition))                                               \
+               __ret = __wait_event_freezable(wq, condition);          \
+       __ret;                                                          \
+})
+
 #define __wait_event_timeout(wq, condition, timeout)                   \
        ___wait_event(wq, ___wait_cond_timeout(condition),              \
                      TASK_UNINTERRUPTIBLE, 0, timeout,                 \
@@ -290,11 +319,30 @@ do {                                                                      \
 #define wait_event_timeout(wq, condition, timeout)                     \
 ({                                                                     \
        long __ret = timeout;                                           \
+       might_sleep();                                                  \
        if (!___wait_cond_timeout(condition))                           \
                __ret = __wait_event_timeout(wq, condition, timeout);   \
        __ret;                                                          \
 })
 
+#define __wait_event_freezable_timeout(wq, condition, timeout)         \
+       ___wait_event(wq, ___wait_cond_timeout(condition),              \
+                     TASK_INTERRUPTIBLE, 0, timeout,                   \
+                     __ret = schedule_timeout(__ret); try_to_freeze())
+
+/*
+ * like wait_event_timeout() -- except it uses TASK_INTERRUPTIBLE to avoid
+ * increasing load and is freezable.
+ */
+#define wait_event_freezable_timeout(wq, condition, timeout)           \
+({                                                                     \
+       long __ret = timeout;                                           \
+       might_sleep();                                                  \
+       if (!___wait_cond_timeout(condition))                           \
+               __ret = __wait_event_freezable_timeout(wq, condition, timeout); \
+       __ret;                                                          \
+})
+
 #define __wait_event_cmd(wq, condition, cmd1, cmd2)                    \
        (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,  \
                            cmd1; schedule(); cmd2)
@@ -315,6 +363,7 @@ do {                                                                        \
  */
 #define wait_event_cmd(wq, condition, cmd1, cmd2)                      \
 do {                                                                   \
+       might_sleep();                                                  \
        if (condition)                                                  \
                break;                                                  \
        __wait_event_cmd(wq, condition, cmd1, cmd2);                    \
@@ -342,6 +391,7 @@ do {                                                                        \
 #define wait_event_interruptible(wq, condition)                                \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_interruptible(wq, condition);      \
        __ret;                                                          \
@@ -375,6 +425,7 @@ do {                                                                        \
 #define wait_event_interruptible_timeout(wq, condition, timeout)       \
 ({                                                                     \
        long __ret = timeout;                                           \
+       might_sleep();                                                  \
        if (!___wait_cond_timeout(condition))                           \
                __ret = __wait_event_interruptible_timeout(wq,          \
                                                condition, timeout);    \
@@ -425,6 +476,7 @@ do {                                                                        \
 #define wait_event_hrtimeout(wq, condition, timeout)                   \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_hrtimeout(wq, condition, timeout,  \
                                               TASK_UNINTERRUPTIBLE);   \
@@ -450,6 +502,7 @@ do {                                                                        \
 #define wait_event_interruptible_hrtimeout(wq, condition, timeout)     \
 ({                                                                     \
        long __ret = 0;                                                 \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_hrtimeout(wq, condition, timeout,  \
                                               TASK_INTERRUPTIBLE);     \
@@ -463,12 +516,27 @@ do {                                                                      \
 #define wait_event_interruptible_exclusive(wq, condition)              \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_interruptible_exclusive(wq, condition);\
        __ret;                                                          \
 })
 
 
+#define __wait_event_freezable_exclusive(wq, condition)                        \
+       ___wait_event(wq, condition, TASK_INTERRUPTIBLE, 1, 0,          \
+                       schedule(); try_to_freeze())
+
+#define wait_event_freezable_exclusive(wq, condition)                  \
+({                                                                     \
+       int __ret = 0;                                                  \
+       might_sleep();                                                  \
+       if (!(condition))                                               \
+               __ret = __wait_event_freezable_exclusive(wq, condition);\
+       __ret;                                                          \
+})
+
+
 #define __wait_event_interruptible_locked(wq, condition, exclusive, irq) \
 ({                                                                     \
        int __ret = 0;                                                  \
@@ -637,6 +705,7 @@ do {                                                                        \
 #define wait_event_killable(wq, condition)                             \
 ({                                                                     \
        int __ret = 0;                                                  \
+       might_sleep();                                                  \
        if (!(condition))                                               \
                __ret = __wait_event_killable(wq, condition);           \
        __ret;                                                          \
@@ -830,6 +899,8 @@ void prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int sta
 long prepare_to_wait_event(wait_queue_head_t *q, wait_queue_t *wait, int state);
 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
 void abort_exclusive_wait(wait_queue_head_t *q, wait_queue_t *wait, unsigned int mode, void *key);
+long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
+int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
 
@@ -886,6 +957,7 @@ extern int bit_wait_io_timeout(struct wait_bit_key *);
 static inline int
 wait_on_bit(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
@@ -910,6 +982,7 @@ wait_on_bit(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_io(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
@@ -936,6 +1009,7 @@ wait_on_bit_io(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_action(void *word, int bit, wait_bit_action_f *action, unsigned mode)
 {
+       might_sleep();
        if (!test_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit, action, mode);
@@ -963,6 +1037,7 @@ wait_on_bit_action(void *word, int bit, wait_bit_action_f *action, unsigned mode
 static inline int
 wait_on_bit_lock(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, bit_wait, mode);
@@ -986,6 +1061,7 @@ wait_on_bit_lock(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_lock_io(void *word, int bit, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, bit_wait_io, mode);
@@ -1011,6 +1087,7 @@ wait_on_bit_lock_io(void *word, int bit, unsigned mode)
 static inline int
 wait_on_bit_lock_action(void *word, int bit, wait_bit_action_f *action, unsigned mode)
 {
+       might_sleep();
        if (!test_and_set_bit(bit, word))
                return 0;
        return out_of_line_wait_on_bit_lock(word, bit, action, mode);
@@ -1029,6 +1106,7 @@ wait_on_bit_lock_action(void *word, int bit, wait_bit_action_f *action, unsigned
 static inline
 int wait_on_atomic_t(atomic_t *val, int (*action)(atomic_t *), unsigned mode)
 {
+       might_sleep();
        if (atomic_read(val) == 0)
                return 0;
        return out_of_line_wait_on_atomic_t(val, action, mode);