]> git.sesse.net Git - bcachefs-tools-debian/blob - include/linux/wait.h
4b9cbf38d52afef017d59d215bfe4006798afbf0
[bcachefs-tools-debian] / include / linux / wait.h
1 #ifndef _LINUX_WAIT_H
2 #define _LINUX_WAIT_H
3
4 #include <pthread.h>
5 #include <linux/bitmap.h>
6 #include <linux/list.h>
7 #include <linux/spinlock.h>
8
9 typedef struct __wait_queue wait_queue_t;
10 typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);
11
12 #define WQ_FLAG_EXCLUSIVE       0x01
13
14 struct __wait_queue {
15         unsigned int            flags;
16         void                    *private;
17         wait_queue_func_t       func;
18         struct list_head        task_list;
19 };
20
21 struct wait_queue_head {
22         spinlock_t              lock;
23         struct list_head        task_list;
24 };
25
26 typedef struct wait_queue_head wait_queue_head_t;
27
28 void wake_up(wait_queue_head_t *);
29 void wake_up_all(wait_queue_head_t *);
30 void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state);
31 void finish_wait(wait_queue_head_t *q, wait_queue_t *wait);
32 int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
33 int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key);
34
35 #define DECLARE_WAITQUEUE(name, tsk)                                    \
36         wait_queue_t name = {                                           \
37                 .private        = tsk,                                  \
38                 .func           = default_wake_function,                \
39                 .task_list      = { NULL, NULL }                        \
40         }
41
42 #define __WAIT_QUEUE_HEAD_INITIALIZER(name) {                           \
43         .lock           = __SPIN_LOCK_UNLOCKED(name.lock),              \
44         .task_list      = { &(name).task_list, &(name).task_list } }
45
46 #define DECLARE_WAIT_QUEUE_HEAD(name) \
47         struct wait_queue_head name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
48
49 static inline void init_waitqueue_head(wait_queue_head_t *q)
50 {
51         spin_lock_init(&q->lock);
52         INIT_LIST_HEAD(&q->task_list);
53 }
54
55 #define DEFINE_WAIT(name)                                               \
56         wait_queue_t name = {                                           \
57                 .private        = current,                              \
58                 .func           = autoremove_wake_function,             \
59                 .task_list      = LIST_HEAD_INIT((name).task_list),     \
60         }
61
62 #define ___wait_cond_timeout(condition)                                 \
63 ({                                                                      \
64         bool __cond = (condition);                                      \
65         if (__cond && !__ret)                                           \
66                 __ret = 1;                                              \
67         __cond || !__ret;                                               \
68 })
69
70 #define ___wait_event(wq, condition, state, exclusive, ret, cmd)        \
71 ({                                                                      \
72         DEFINE_WAIT(__wait);                                            \
73         long __ret = ret;                                               \
74                                                                         \
75         for (;;) {                                                      \
76                 prepare_to_wait(&wq, &__wait, state);                   \
77                 if (condition)                                          \
78                         break;                                          \
79                 cmd;                                                    \
80         }                                                               \
81         finish_wait(&wq, &__wait);                                      \
82         __ret;                                                          \
83 })
84
85 #define __wait_event(wq, condition)                                     \
86         (void)___wait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, 0,  \
87                             schedule())
88
89 #define wait_event(wq, condition)                                       \
90 do {                                                                    \
91         if (condition)                                                  \
92                 break;                                                  \
93         __wait_event(wq, condition);                                    \
94 } while (0)
95
96 #define wait_event_freezable(wq, condition)     ({wait_event(wq, condition); 0; })
97 #define wait_event_killable(wq, condition)      ({wait_event(wq, condition); 0; })
98 #define wait_event_interruptible(wq, condition) ({wait_event(wq, condition); 0; })
99
100 #define __wait_event_timeout(wq, condition, timeout)                    \
101         ___wait_event(wq, ___wait_cond_timeout(condition),              \
102                       TASK_UNINTERRUPTIBLE, 0, timeout,                 \
103                       __ret = schedule_timeout(__ret))
104
105 #define wait_event_timeout(wq, condition, timeout)                      \
106 ({                                                                      \
107         long __ret = timeout;                                           \
108         if (!___wait_cond_timeout(condition))                           \
109                 __ret = __wait_event_timeout(wq, condition, timeout);   \
110         __ret;                                                          \
111 })
112
113 void wake_up_bit(void *, int);
114 void __wait_on_bit(void *, int, unsigned);
115 void __wait_on_bit_lock(void *, int, unsigned);
116
117 static inline int
118 wait_on_bit(unsigned long *word, int bit, unsigned mode)
119 {
120         if (!test_bit(bit, word))
121                 return 0;
122         __wait_on_bit(word, bit, mode);
123         return 0;
124 }
125
126 static inline int
127 wait_on_bit_lock(unsigned long *word, int bit, unsigned mode)
128 {
129         if (!test_and_set_bit(bit, word))
130                 return 0;
131         __wait_on_bit_lock(word, bit, mode);
132         return 0;
133 }
134
135 #define wait_on_bit_io(w, b, m)                 wait_on_bit(w, b, m)
136 #define wait_on_bit_lock_io(w, b, m)            wait_on_bit_lock(w, b, m)
137
138 #endif /* _LINUX_WAIT_H */