1
2#ifndef _LINUX_SWAIT_H
3#define _LINUX_SWAIT_H
4
5#include <linux/list.h>
6#include <linux/stddef.h>
7#include <linux/spinlock.h>
8#include <linux/wait.h>
9#include <asm/current.h>
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41struct task_struct;
42
43struct swait_queue_head {
44 raw_spinlock_t lock;
45 struct list_head task_list;
46};
47
48struct swait_queue {
49 struct task_struct *task;
50 struct list_head task_list;
51};
52
53#define __SWAITQUEUE_INITIALIZER(name) { \
54 .task = current, \
55 .task_list = LIST_HEAD_INIT((name).task_list), \
56}
57
58#define DECLARE_SWAITQUEUE(name) \
59 struct swait_queue name = __SWAITQUEUE_INITIALIZER(name)
60
61#define __SWAIT_QUEUE_HEAD_INITIALIZER(name) { \
62 .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \
63 .task_list = LIST_HEAD_INIT((name).task_list), \
64}
65
66#define DECLARE_SWAIT_QUEUE_HEAD(name) \
67 struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INITIALIZER(name)
68
69extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
70 struct lock_class_key *key);
71
72#define init_swait_queue_head(q) \
73 do { \
74 static struct lock_class_key __key; \
75 __init_swait_queue_head((q), #q, &__key); \
76 } while (0)
77
78#ifdef CONFIG_LOCKDEP
79# define __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name) \
80 ({ init_swait_queue_head(&name); name; })
81# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name) \
82 struct swait_queue_head name = __SWAIT_QUEUE_HEAD_INIT_ONSTACK(name)
83#else
84# define DECLARE_SWAIT_QUEUE_HEAD_ONSTACK(name) \
85 DECLARE_SWAIT_QUEUE_HEAD(name)
86#endif
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121static inline int swait_active(struct swait_queue_head *wq)
122{
123 return !list_empty(&wq->task_list);
124}
125
126
127
128
129
130
131
132
133
134static inline bool swq_has_sleeper(struct swait_queue_head *wq)
135{
136
137
138
139
140
141
142
143 smp_mb();
144 return swait_active(wq);
145}
146
147extern void swake_up_one(struct swait_queue_head *q);
148extern void swake_up_all(struct swait_queue_head *q);
149extern void swake_up_locked(struct swait_queue_head *q);
150
151extern void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state);
152extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state);
153
154extern void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
155extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait);
156
157
158#define ___swait_event(wq, condition, state, ret, cmd) \
159({ \
160 __label__ __out; \
161 struct swait_queue __wait; \
162 long __ret = ret; \
163 \
164 INIT_LIST_HEAD(&__wait.task_list); \
165 for (;;) { \
166 long __int = prepare_to_swait_event(&wq, &__wait, state);\
167 \
168 if (condition) \
169 break; \
170 \
171 if (___wait_is_interruptible(state) && __int) { \
172 __ret = __int; \
173 goto __out; \
174 } \
175 \
176 cmd; \
177 } \
178 finish_swait(&wq, &__wait); \
179__out: __ret; \
180})
181
182#define __swait_event(wq, condition) \
183 (void)___swait_event(wq, condition, TASK_UNINTERRUPTIBLE, 0, \
184 schedule())
185
186#define swait_event_exclusive(wq, condition) \
187do { \
188 if (condition) \
189 break; \
190 __swait_event(wq, condition); \
191} while (0)
192
193#define __swait_event_timeout(wq, condition, timeout) \
194 ___swait_event(wq, ___wait_cond_timeout(condition), \
195 TASK_UNINTERRUPTIBLE, timeout, \
196 __ret = schedule_timeout(__ret))
197
198#define swait_event_timeout_exclusive(wq, condition, timeout) \
199({ \
200 long __ret = timeout; \
201 if (!___wait_cond_timeout(condition)) \
202 __ret = __swait_event_timeout(wq, condition, timeout); \
203 __ret; \
204})
205
206#define __swait_event_interruptible(wq, condition) \
207 ___swait_event(wq, condition, TASK_INTERRUPTIBLE, 0, \
208 schedule())
209
210#define swait_event_interruptible_exclusive(wq, condition) \
211({ \
212 int __ret = 0; \
213 if (!(condition)) \
214 __ret = __swait_event_interruptible(wq, condition); \
215 __ret; \
216})
217
218#define __swait_event_interruptible_timeout(wq, condition, timeout) \
219 ___swait_event(wq, ___wait_cond_timeout(condition), \
220 TASK_INTERRUPTIBLE, timeout, \
221 __ret = schedule_timeout(__ret))
222
223#define swait_event_interruptible_timeout_exclusive(wq, condition, timeout)\
224({ \
225 long __ret = timeout; \
226 if (!___wait_cond_timeout(condition)) \
227 __ret = __swait_event_interruptible_timeout(wq, \
228 condition, timeout); \
229 __ret; \
230})
231
232#define __swait_event_idle(wq, condition) \
233 (void)___swait_event(wq, condition, TASK_IDLE, 0, schedule())
234
235
236
237
238
239
240
241
242
243
244
245
246
247#define swait_event_idle_exclusive(wq, condition) \
248do { \
249 if (condition) \
250 break; \
251 __swait_event_idle(wq, condition); \
252} while (0)
253
254#define __swait_event_idle_timeout(wq, condition, timeout) \
255 ___swait_event(wq, ___wait_cond_timeout(condition), \
256 TASK_IDLE, timeout, \
257 __ret = schedule_timeout(__ret))
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278#define swait_event_idle_timeout_exclusive(wq, condition, timeout) \
279({ \
280 long __ret = timeout; \
281 if (!___wait_cond_timeout(condition)) \
282 __ret = __swait_event_idle_timeout(wq, \
283 condition, timeout); \
284 __ret; \
285})
286
287#endif
288