Rev 6125 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2967 | Serge | 1 | #ifndef _LINUX_WAIT_H |
2 | #define _LINUX_WAIT_H |
||
5270 | serge | 3 | /* |
4 | * Linux wait queue related types and methods |
||
5 | */ |
||
6 | #include |
||
7 | #include |
||
8 | #include |
||
9 | #include |
||
3192 | Serge | 10 | #include |
11 | |||
2967 | Serge | 12 | typedef struct __wait_queue wait_queue_t; |
3391 | Serge | 13 | typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key); |
4292 | Serge | 14 | int default_wake_function(wait_queue_t *wait, unsigned mode, int flags, void *key); |
3391 | Serge | 15 | |
6102 | serge | 16 | /* __wait_queue::flags */ |
17 | #define WQ_FLAG_EXCLUSIVE 0x01 |
||
18 | #define WQ_FLAG_WOKEN 0x02 |
||
19 | |||
20 | struct __wait_queue { |
||
21 | unsigned int flags; |
||
22 | void *private; |
||
23 | wait_queue_func_t func; |
||
24 | struct list_head task_list; |
||
25 | evhandle_t evnt; |
||
26 | }; |
||
27 | |||
28 | struct wait_bit_key { |
||
29 | void *flags; |
||
30 | int bit_nr; |
||
31 | #define WAIT_ATOMIC_T_BIT_NR -1 |
||
32 | unsigned long timeout; |
||
33 | }; |
||
34 | |||
35 | struct wait_bit_queue { |
||
36 | struct wait_bit_key key; |
||
37 | wait_queue_t wait; |
||
38 | }; |
||
39 | |||
40 | struct __wait_queue_head { |
||
41 | spinlock_t lock; |
||
42 | struct list_head task_list; |
||
43 | }; |
||
2967 | Serge | 44 | typedef struct __wait_queue_head wait_queue_head_t; |
45 | |||
6102 | serge | 46 | struct task_struct; |
47 | |||
48 | /* |
||
49 | * Macros for declaration and initialisaton of the datatypes |
||
50 | */ |
||
51 | |||
52 | #define __WAITQUEUE_INITIALIZER(name, tsk) { \ |
||
53 | .private = tsk, \ |
||
54 | .func = default_wake_function, \ |
||
55 | .task_list = { NULL, NULL } } |
||
56 | |||
57 | #define DECLARE_WAITQUEUE(name, tsk) \ |
||
58 | wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk) |
||
59 | |||
60 | #define __WAIT_QUEUE_HEAD_INITIALIZER(name) { \ |
||
61 | .lock = __SPIN_LOCK_UNLOCKED(name.lock), \ |
||
62 | .task_list = { &(name).task_list, &(name).task_list } } |
||
63 | |||
64 | #define DECLARE_WAIT_QUEUE_HEAD(name) \ |
||
65 | wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name) |
||
66 | |||
67 | #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ |
||
68 | { .flags = word, .bit_nr = bit, } |
||
69 | |||
70 | #define __WAIT_ATOMIC_T_KEY_INITIALIZER(p) \ |
||
71 | { .flags = p, .bit_nr = WAIT_ATOMIC_T_BIT_NR, } |
||
72 | |||
73 | extern void __init_waitqueue_head(wait_queue_head_t *q, const char *name, struct lock_class_key *); |
||
74 | |||
75 | #ifdef CONFIG_LOCKDEP |
||
76 | # define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \ |
||
77 | ({ init_waitqueue_head(&name); name; }) |
||
78 | # define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \ |
||
79 | wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) |
||
80 | #else |
||
81 | # define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name) |
||
82 | #endif |
||
83 | |||
84 | static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p) |
||
2967 | Serge | 85 | { |
6102 | serge | 86 | q->flags = 0; |
87 | q->private = p; |
||
88 | q->func = default_wake_function; |
||
89 | } |
||
2967 | Serge | 90 | |
6102 | serge | 91 | static inline void |
92 | init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func) |
||
2967 | Serge | 93 | { |
6102 | serge | 94 | q->flags = 0; |
95 | q->private = NULL; |
||
96 | q->func = func; |
||
97 | } |
||
98 | |||
4292 | Serge | 99 | static inline int waitqueue_active(wait_queue_head_t *q) |
100 | { |
||
101 | return !list_empty(&q->task_list); |
||
102 | } |
||
2967 | Serge | 103 | |
5270 | serge | 104 | extern void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); |
105 | extern void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait); |
||
106 | extern void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait); |
||
107 | |||
2967 | Serge | 108 | static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new) |
109 | { |
||
6102 | serge | 110 | list_add(&new->task_list, &head->task_list); |
2967 | Serge | 111 | } |
112 | |||
3482 | Serge | 113 | /* |
6102 | serge | 114 | * Used for wake-one threads: |
115 | */ |
||
116 | static inline void |
||
117 | __add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait) |
||
118 | { |
||
119 | wait->flags |= WQ_FLAG_EXCLUSIVE; |
||
120 | __add_wait_queue(q, wait); |
||
121 | } |
||
122 | |||
123 | static inline void __add_wait_queue_tail(wait_queue_head_t *head, |
||
124 | wait_queue_t *new) |
||
125 | { |
||
126 | list_add_tail(&new->task_list, &head->task_list); |
||
127 | } |
||
128 | |||
129 | static inline void |
||
130 | __add_wait_queue_tail_exclusive(wait_queue_head_t *q, wait_queue_t *wait) |
||
131 | { |
||
132 | wait->flags |= WQ_FLAG_EXCLUSIVE; |
||
133 | __add_wait_queue_tail(q, wait); |
||
134 | } |
||
135 | |||
136 | static inline void |
||
137 | __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old) |
||
138 | { |
||
139 | list_del(&old->task_list); |
||
140 | } |
||
141 | |||
142 | typedef int wait_bit_action_f(struct wait_bit_key *, int mode); |
||
143 | void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key); |
||
144 | void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key); |
||
145 | void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key); |
||
146 | void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr); |
||
147 | void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr); |
||
148 | void __wake_up_bit(wait_queue_head_t *, void *, int); |
||
149 | int __wait_on_bit(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_action_f *, unsigned); |
||
150 | int __wait_on_bit_lock(wait_queue_head_t *, struct wait_bit_queue *, wait_bit_action_f *, unsigned); |
||
151 | void wake_up_bit(void *, int); |
||
152 | void wake_up_atomic_t(atomic_t *); |
||
153 | int out_of_line_wait_on_bit(void *, int, wait_bit_action_f *, unsigned); |
||
154 | int out_of_line_wait_on_bit_timeout(void *, int, wait_bit_action_f *, unsigned, unsigned long); |
||
155 | int out_of_line_wait_on_bit_lock(void *, int, wait_bit_action_f *, unsigned); |
||
156 | int out_of_line_wait_on_atomic_t(atomic_t *, int (*)(atomic_t *), unsigned); |
||
157 | wait_queue_head_t *bit_waitqueue(void *, int); |
||
158 | |||
159 | /* |
||
160 | |||
2967 | Serge | 161 | #define __wait_event(wq, condition) \ |
162 | do { \ |
||
163 | DEFINE_WAIT(__wait); \ |
||
164 | \ |
||
165 | for (;;) { \ |
||
166 | prepare_to_wait(&wq, &__wait, TASK_UNINTERRUPTIBLE); \ |
||
167 | if (condition) \ |
||
168 | break; \ |
||
169 | schedule(); \ |
||
170 | } \ |
||
171 | finish_wait(&wq, &__wait); \ |
||
172 | } while (0) |
||
173 | |||
3482 | Serge | 174 | */ |
2967 | Serge | 175 | |
3031 | serge | 176 | #define wait_event_timeout(wq, condition, timeout) \ |
177 | ({ \ |
||
178 | long __ret = timeout; \ |
||
179 | do{ \ |
||
180 | wait_queue_t __wait = { \ |
||
181 | .task_list = LIST_HEAD_INIT(__wait.task_list), \ |
||
182 | .evnt = CreateEvent(NULL, MANUAL_DESTROY), \ |
||
183 | }; \ |
||
3297 | Serge | 184 | unsigned long flags; \ |
3031 | serge | 185 | \ |
186 | spin_lock_irqsave(&wq.lock, flags); \ |
||
187 | if (list_empty(&__wait.task_list)) \ |
||
188 | __add_wait_queue(&wq, &__wait); \ |
||
189 | spin_unlock_irqrestore(&wq.lock, flags); \ |
||
190 | \ |
||
191 | for(;;){ \ |
||
192 | if (condition) \ |
||
193 | break; \ |
||
3391 | Serge | 194 | WaitEventTimeout(__wait.evnt, timeout); \ |
3031 | serge | 195 | }; \ |
3297 | Serge | 196 | if (!list_empty(&__wait.task_list)) { \ |
3031 | serge | 197 | spin_lock_irqsave(&wq.lock, flags); \ |
198 | list_del_init(&__wait.task_list); \ |
||
199 | spin_unlock_irqrestore(&wq.lock, flags); \ |
||
200 | }; \ |
||
201 | DestroyEvent(__wait.evnt); \ |
||
202 | } while (0); \ |
||
203 | __ret; \ |
||
204 | }) |
||
205 | |||
3192 | Serge | 206 | #define wait_event_interruptible_timeout(wq, condition, timeout) \ |
207 | wait_event_timeout(wq, condition, timeout) |
||
3031 | serge | 208 | |
209 | |||
2967 | Serge | 210 | #define wait_event(wq, condition) \ |
5056 | serge | 211 | do{ \ |
2967 | Serge | 212 | wait_queue_t __wait = { \ |
213 | .task_list = LIST_HEAD_INIT(__wait.task_list), \ |
||
214 | .evnt = CreateEvent(NULL, MANUAL_DESTROY), \ |
||
215 | }; \ |
||
3297 | Serge | 216 | unsigned long flags; \ |
2967 | Serge | 217 | \ |
218 | spin_lock_irqsave(&wq.lock, flags); \ |
||
219 | if (list_empty(&__wait.task_list)) \ |
||
220 | __add_wait_queue(&wq, &__wait); \ |
||
221 | spin_unlock_irqrestore(&wq.lock, flags); \ |
||
222 | \ |
||
223 | for(;;){ \ |
||
224 | if (condition) \ |
||
225 | break; \ |
||
226 | WaitEvent(__wait.evnt); \ |
||
227 | }; \ |
||
228 | if (!list_empty_careful(&__wait.task_list)) { \ |
||
229 | spin_lock_irqsave(&wq.lock, flags); \ |
||
230 | list_del_init(&__wait.task_list); \ |
||
231 | spin_unlock_irqrestore(&wq.lock, flags); \ |
||
232 | }; \ |
||
233 | DestroyEvent(__wait.evnt); \ |
||
234 | } while (0) |
||
235 | |||
5056 | serge | 236 | #define wait_event_interruptible(wq, condition) \ |
237 | ({ \ |
||
238 | int __ret = 0; \ |
||
239 | if (!(condition)) \ |
||
240 | wait_event(wq, condition); \ |
||
241 | __ret; \ |
||
242 | }) |
||
2967 | Serge | 243 | |
6102 | serge | 244 | static inline |
245 | void wake_up(wait_queue_head_t *q) |
||
246 | { |
||
247 | wait_queue_t *curr; |
||
248 | unsigned long flags; |
||
3031 | serge | 249 | |
6102 | serge | 250 | spin_lock_irqsave(&q->lock, flags); |
6125 | serge | 251 | curr = list_first_entry_or_null(&q->task_list, typeof(*curr), task_list); |
252 | if(curr != NULL) |
||
6102 | serge | 253 | { |
6125 | serge | 254 | if(!WARN_ON(curr->evnt.handle == 0)) |
255 | { |
||
256 | kevent_t event = {0}; |
||
257 | event.code = -1; |
||
258 | RaiseEvent(curr->evnt, 0, &event); |
||
259 | } |
||
6102 | serge | 260 | } |
261 | spin_unlock_irqrestore(&q->lock, flags); |
||
262 | } |
||
263 | |||
2967 | Serge | 264 | static inline |
6102 | serge | 265 | void wake_up_interruptible(wait_queue_head_t *q) |
266 | { |
||
267 | wait_queue_t *curr; |
||
268 | unsigned long flags; |
||
269 | |||
270 | spin_lock_irqsave(&q->lock, flags); |
||
6125 | serge | 271 | curr = list_first_entry_or_null(&q->task_list, typeof(*curr), task_list); |
272 | if(curr != NULL) |
||
6102 | serge | 273 | { |
6125 | serge | 274 | if(!WARN_ON(curr->evnt.handle == 0)) |
275 | { |
||
276 | kevent_t event = {0}; |
||
277 | event.code = -1; |
||
278 | RaiseEvent(curr->evnt, 0, &event); |
||
279 | } |
||
6102 | serge | 280 | } |
281 | spin_unlock_irqrestore(&q->lock, flags); |
||
282 | } |
||
283 | |||
284 | static inline |
||
2967 | Serge | 285 | void wake_up_all(wait_queue_head_t *q) |
286 | { |
||
287 | wait_queue_t *curr; |
||
288 | unsigned long flags; |
||
289 | spin_lock_irqsave(&q->lock, flags); |
||
290 | list_for_each_entry(curr, &q->task_list, task_list) |
||
291 | { |
||
6125 | serge | 292 | if(WARN_ON(curr->evnt.handle == 0)) |
293 | continue; |
||
294 | kevent_t event = {0}; |
||
2967 | Serge | 295 | event.code = -1; |
296 | RaiseEvent(curr->evnt, 0, &event); |
||
297 | } |
||
298 | spin_unlock_irqrestore(&q->lock, flags); |
||
299 | } |
||
300 | |||
301 | |||
302 | static inline void |
||
303 | init_waitqueue_head(wait_queue_head_t *q) |
||
304 | { |
||
305 | spin_lock_init(&q->lock); |
||
306 | INIT_LIST_HEAD(&q->task_list); |
||
307 | }; |
||
308 | |||
309 | |||
5270 | serge | 310 | //struct completion { |
311 | // unsigned int done; |
||
312 | // wait_queue_head_t wait; |
||
313 | //}; |
||
3031 | serge | 314 | |
7143 | serge | 315 | void prepare_to_wait(wait_queue_head_t *q, wait_queue_t *wait, int state); |
316 | void finish_wait(wait_queue_head_t *q, wait_queue_t *wait); |
||
3391 | Serge | 317 | int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key); |
3031 | serge | 318 | |
3391 | Serge | 319 | |
320 | #define DEFINE_WAIT_FUNC(name, function) \ |
||
321 | wait_queue_t name = { \ |
||
322 | .func = function, \ |
||
323 | .task_list = LIST_HEAD_INIT((name).task_list), \ |
||
324 | .evnt = CreateEvent(NULL, MANUAL_DESTROY), \ |
||
325 | } |
||
326 | |||
327 | #define DEFINE_WAIT(name) DEFINE_WAIT_FUNC(name, autoremove_wake_function) |
||
328 | |||
329 | |||
2967 | Serge | 330 | #endif |
331 |