- Stephen Rothwell: APM updates
[davej-history.git] / include / linux / wait.h
blob6b281ccad3f47be9ff167df45732d81b099f98a8
1 #ifndef _LINUX_WAIT_H
2 #define _LINUX_WAIT_H
4 #define WNOHANG 0x00000001
5 #define WUNTRACED 0x00000002
7 #define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads in this group */
8 #define __WALL 0x40000000 /* Wait on all children, regardless of type */
9 #define __WCLONE 0x80000000 /* Wait only on non-SIGCHLD children */
11 #ifdef __KERNEL__
13 #include <linux/kernel.h>
14 #include <linux/list.h>
15 #include <linux/stddef.h>
16 #include <linux/spinlock.h>
18 #include <asm/page.h>
19 #include <asm/processor.h>
22 * Temporary debugging help until all code is converted to the new
23 * waitqueue usage.
25 #define WAITQUEUE_DEBUG 0
27 #if WAITQUEUE_DEBUG
28 extern int printk(const char *fmt, ...);
29 #define WQ_BUG() do { \
30 printk("wq bug, forcing oops.\n"); \
31 BUG(); \
32 } while (0)
34 #define CHECK_MAGIC(x) if (x != (long)&(x)) \
35 { printk("bad magic %lx (should be %lx), ", (long)x, (long)&(x)); WQ_BUG(); }
37 #define CHECK_MAGIC_WQHEAD(x) do { \
38 if (x->__magic != (long)&(x->__magic)) { \
39 printk("bad magic %lx (should be %lx, creator %lx), ", \
40 x->__magic, (long)&(x->__magic), x->__creator); \
41 WQ_BUG(); \
42 } \
43 } while (0)
44 #endif
46 struct __wait_queue {
47 unsigned int flags;
48 #define WQ_FLAG_EXCLUSIVE 0x01
49 struct task_struct * task;
50 struct list_head task_list;
51 #if WAITQUEUE_DEBUG
52 long __magic;
53 long __waker;
54 #endif
56 typedef struct __wait_queue wait_queue_t;
59 * 'dual' spinlock architecture. Can be switched between spinlock_t and
60 * rwlock_t locks via changing this define. Since waitqueues are quite
61 * decoupled in the new architecture, lightweight 'simple' spinlocks give
62 * us slightly better latencies and smaller waitqueue structure size.
64 #define USE_RW_WAIT_QUEUE_SPINLOCK 0
66 #if USE_RW_WAIT_QUEUE_SPINLOCK
67 # define wq_lock_t rwlock_t
68 # define WAITQUEUE_RW_LOCK_UNLOCKED RW_LOCK_UNLOCKED
70 # define wq_read_lock read_lock
71 # define wq_read_lock_irqsave read_lock_irqsave
72 # define wq_read_unlock_irqrestore read_unlock_irqrestore
73 # define wq_read_unlock read_unlock
74 # define wq_write_lock_irq write_lock_irq
75 # define wq_write_lock_irqsave write_lock_irqsave
76 # define wq_write_unlock_irqrestore write_unlock_irqrestore
77 # define wq_write_unlock write_unlock
78 #else
79 # define wq_lock_t spinlock_t
80 # define WAITQUEUE_RW_LOCK_UNLOCKED SPIN_LOCK_UNLOCKED
82 # define wq_read_lock spin_lock
83 # define wq_read_lock_irqsave spin_lock_irqsave
84 # define wq_read_unlock spin_unlock
85 # define wq_read_unlock_irqrestore spin_unlock_irqrestore
86 # define wq_write_lock_irq spin_lock_irq
87 # define wq_write_lock_irqsave spin_lock_irqsave
88 # define wq_write_unlock_irqrestore spin_unlock_irqrestore
89 # define wq_write_unlock spin_unlock
90 #endif
92 struct __wait_queue_head {
93 wq_lock_t lock;
94 struct list_head task_list;
95 #if WAITQUEUE_DEBUG
96 long __magic;
97 long __creator;
98 #endif
100 typedef struct __wait_queue_head wait_queue_head_t;
102 #if WAITQUEUE_DEBUG
103 # define __WAITQUEUE_DEBUG_INIT(name) \
104 , (long)&(name).__magic, 0
105 # define __WAITQUEUE_HEAD_DEBUG_INIT(name) \
106 , (long)&(name).__magic, (long)&(name).__magic
107 #else
108 # define __WAITQUEUE_DEBUG_INIT(name)
109 # define __WAITQUEUE_HEAD_DEBUG_INIT(name)
110 #endif
112 #define __WAITQUEUE_INITIALIZER(name,task) \
113 { 0x0, task, { NULL, NULL } __WAITQUEUE_DEBUG_INIT(name)}
114 #define DECLARE_WAITQUEUE(name,task) \
115 wait_queue_t name = __WAITQUEUE_INITIALIZER(name,task)
117 #define __WAIT_QUEUE_HEAD_INITIALIZER(name) \
118 { WAITQUEUE_RW_LOCK_UNLOCKED, { &(name).task_list, &(name).task_list } \
119 __WAITQUEUE_HEAD_DEBUG_INIT(name)}
121 #define DECLARE_WAIT_QUEUE_HEAD(name) \
122 wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
124 static inline void init_waitqueue_head(wait_queue_head_t *q)
126 #if WAITQUEUE_DEBUG
127 if (!q)
128 WQ_BUG();
129 #endif
130 q->lock = WAITQUEUE_RW_LOCK_UNLOCKED;
131 INIT_LIST_HEAD(&q->task_list);
132 #if WAITQUEUE_DEBUG
133 q->__magic = (long)&q->__magic;
134 q->__creator = (long)current_text_addr();
135 #endif
138 static inline void init_waitqueue_entry(wait_queue_t *q,
139 struct task_struct *p)
141 #if WAITQUEUE_DEBUG
142 if (!q || !p)
143 WQ_BUG();
144 #endif
145 q->flags = 0;
146 q->task = p;
147 #if WAITQUEUE_DEBUG
148 q->__magic = (long)&q->__magic;
149 #endif
152 static inline int waitqueue_active(wait_queue_head_t *q)
154 #if WAITQUEUE_DEBUG
155 if (!q)
156 WQ_BUG();
157 CHECK_MAGIC_WQHEAD(q);
158 #endif
160 return !list_empty(&q->task_list);
163 static inline void __add_wait_queue(wait_queue_head_t *head, wait_queue_t *new)
165 #if WAITQUEUE_DEBUG
166 if (!head || !new)
167 WQ_BUG();
168 CHECK_MAGIC_WQHEAD(head);
169 CHECK_MAGIC(new->__magic);
170 if (!head->task_list.next || !head->task_list.prev)
171 WQ_BUG();
172 #endif
173 list_add(&new->task_list, &head->task_list);
177 * Used for wake-one threads:
179 static inline void __add_wait_queue_tail(wait_queue_head_t *head,
180 wait_queue_t *new)
182 #if WAITQUEUE_DEBUG
183 if (!head || !new)
184 WQ_BUG();
185 CHECK_MAGIC_WQHEAD(head);
186 CHECK_MAGIC(new->__magic);
187 if (!head->task_list.next || !head->task_list.prev)
188 WQ_BUG();
189 #endif
190 list_add_tail(&new->task_list, &head->task_list);
193 static inline void __remove_wait_queue(wait_queue_head_t *head,
194 wait_queue_t *old)
196 #if WAITQUEUE_DEBUG
197 if (!old)
198 WQ_BUG();
199 CHECK_MAGIC(old->__magic);
200 #endif
201 list_del(&old->task_list);
204 #endif /* __KERNEL__ */
206 #endif