2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
25 #ifndef _KERN_WAIT_QUEUE_H_
26 #define _KERN_WAIT_QUEUE_H_
28 #include <sys/appleapiopts.h>
30 #ifdef __APPLE_API_PRIVATE
32 #include <mach/sync_policy.h>
33 #include <mach/kern_return.h> /* for kern_return_t */
35 #include <kern/kern_types.h> /* for wait_queue_t */
37 #ifdef MACH_KERNEL_PRIVATE
39 #include <kern/lock.h>
40 #include <kern/queue.h>
45 * This is the definition of the common event wait queue
46 * that the scheduler APIs understand. It is used
47 * internally by the gerneralized event waiting mechanism
48 * (assert_wait), and also for items that maintain their
49 * own wait queues (such as ports and semaphores).
51 * It is not published to other kernel components. They
52 * can create wait queues by calling wait_queue_alloc.
54 * NOTE: Hardware locks are used to protect event wait
55 * queues since interrupt code is free to post events to
58 typedef struct wait_queue
{
59 unsigned int /* flags */
60 /* boolean_t */ wq_type
:16, /* only public field */
61 wq_fifo
:1, /* fifo wakeup policy? */
62 wq_isprepost
:1, /* is waitq preposted? set only */
63 :0; /* force to long boundary */
64 hw_lock_data_t wq_interlock
; /* interlock */
65 queue_head_t wq_queue
; /* queue of elements */
70 * This is the common definition for a set wait queue.
71 * These can be linked as members/elements of multiple regular
72 * wait queues. They have an additional set of linkages to
73 * identify the linkage structures that point to them.
75 typedef struct wait_queue_set
{
76 WaitQueue wqs_wait_queue
; /* our wait queue */
77 queue_head_t wqs_setlinks
; /* links from set perspective */
78 unsigned int wqs_refcount
; /* refcount for preposting */
81 #define wqs_type wqs_wait_queue.wq_type
82 #define wqs_fifo wqs_wait_queue.wq_fifo
83 #define wqs_isprepost wqs_wait_queue.wq_isprepost
84 #define wqs_queue wqs_wait_queue.wq_queue
87 * wait_queue_element_t
88 * This structure describes the elements on an event wait
89 * queue. It is the common first fields in a thread shuttle
90 * and wait_queue_link_t. In that way, a wait queue can
91 * consist of both thread shuttle elements and links off of
92 * to other (set) wait queues.
94 * WARNING: These fields correspond to fields in the thread
95 * shuttle (run queue links and run queue pointer). Any change in
96 * the layout here will have to be matched with a change there.
98 typedef struct wait_queue_element
{
99 queue_chain_t wqe_links
; /* link of elements on this queue */
100 void * wqe_type
; /* Identifies link vs. thread */
101 wait_queue_t wqe_queue
; /* queue this element is on */
104 typedef WaitQueueElement
*wait_queue_element_t
;
108 * Specialized wait queue element type for linking set
109 * event waits queues onto a wait queue. In this way, an event
110 * can be constructed so that any thread waiting on any number
111 * of associated wait queues can handle the event, while letting
112 * the thread only be linked on the single wait queue it blocked on.
114 * One use: ports in multiple portsets. Each thread is queued up
115 * on the portset that it specifically blocked on during a receive
116 * operation. Each port's event queue links in all the portset
117 * event queues of which it is a member. An IPC event post associated
118 * with that port may wake up any thread from any of those portsets,
119 * or one that was waiting locally on the port itself.
121 typedef struct wait_queue_link
{
122 WaitQueueElement wql_element
; /* element on master */
123 queue_chain_t wql_setlinks
; /* element on set */
124 wait_queue_set_t wql_setqueue
; /* set queue */
127 #define wql_links wql_element.wqe_links
128 #define wql_type wql_element.wqe_type
129 #define wql_queue wql_element.wqe_queue
131 #define _WAIT_QUEUE_inited 0xf1d0
132 #define _WAIT_QUEUE_SET_inited 0xf1d1
134 #define wait_queue_is_queue(wq) \
135 ((wq)->wq_type == _WAIT_QUEUE_inited)
137 #define wait_queue_is_set(wqs) \
138 ((wqs)->wqs_type == _WAIT_QUEUE_SET_inited)
140 #define wait_queue_is_valid(wq) \
141 (((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
143 #define wait_queue_empty(wq) (queue_empty(&(wq)->wq_queue))
144 #define wait_queue_held(wq) (hw_lock_held(&(wq)->wq_interlock))
145 #define wait_queue_lock_try(wq) (hw_lock_try(&(wq)->wq_interlock))
148 * Double the standard lock timeout, because wait queues tend
149 * to iterate over a number of threads - locking each. If there is
150 * a problem with a thread lock, it normally times out at the wait
151 * queue level first, hiding the real problem.
153 #define wait_queue_lock(wq) \
154 ((void) (!hw_lock_to(&(wq)->wq_interlock, LockTimeOut * 2) ? \
155 panic("wait queue deadlock - wq=0x%x, cpu=%d\n", \
156 wq, cpu_number()) : 0))
158 #define wait_queue_unlock(wq) \
159 (assert(wait_queue_held(wq)), hw_lock_unlock(&(wq)->wq_interlock))
161 #define wqs_lock(wqs) wait_queue_lock(&(wqs)->wqs_wait_queue)
162 #define wqs_unlock(wqs) wait_queue_unlock(&(wqs)->wqs_wait_queue)
163 #define wqs_lock_try(wqs) wait_queue__try_lock(&(wqs)->wqs_wait_queue)
165 #define wait_queue_assert_possible(thread) \
166 ((thread)->wait_queue == WAIT_QUEUE_NULL)
168 /******** Decomposed interfaces (to build higher level constructs) ***********/
170 /* assert intent to wait on a locked wait queue */
171 __private_extern__ wait_result_t
wait_queue_assert_wait64_locked(
172 wait_queue_t wait_queue
,
173 event64_t wait_event
,
174 wait_interrupt_t interruptible
,
177 /* peek to see which thread would be chosen for a wakeup - but keep on queue */
178 __private_extern__
void wait_queue_peek64_locked(
179 wait_queue_t wait_queue
,
182 wait_queue_t
*found_queue
);
184 /* peek to see which thread would be chosen for a wakeup - but keep on queue */
185 __private_extern__
void wait_queue_pull_thread_locked(
186 wait_queue_t wait_queue
,
190 /* wakeup all threads waiting for a particular event on locked queue */
191 __private_extern__ kern_return_t
wait_queue_wakeup64_all_locked(
192 wait_queue_t wait_queue
,
193 event64_t wake_event
,
194 wait_result_t result
,
197 /* wakeup one thread waiting for a particular event on locked queue */
198 __private_extern__ kern_return_t
wait_queue_wakeup64_one_locked(
199 wait_queue_t wait_queue
,
200 event64_t wake_event
,
201 wait_result_t result
,
204 /* return identity of a thread awakened for a particular <wait_queue,event> */
205 __private_extern__ thread_t
wait_queue_wakeup64_identity_locked(
206 wait_queue_t wait_queue
,
207 event64_t wake_event
,
208 wait_result_t result
,
211 /* wakeup thread iff its still waiting for a particular event on locked queue */
212 __private_extern__ kern_return_t
wait_queue_wakeup64_thread_locked(
213 wait_queue_t wait_queue
,
214 event64_t wake_event
,
216 wait_result_t result
,
219 #endif /* MACH_KERNEL_PRIVATE */
221 #ifdef __APPLE_API_UNSTABLE
222 /******** Semi-Public interfaces (not a part of a higher construct) ************/
224 extern kern_return_t
wait_queue_init(
225 wait_queue_t wait_queue
,
228 extern wait_queue_set_t
wait_queue_set_alloc(
231 extern kern_return_t
wait_queue_set_free(
232 wait_queue_set_t set_queue
);
234 extern wait_queue_link_t
wait_queue_link_alloc(
237 extern kern_return_t
wait_queue_link_free(
238 wait_queue_link_t link_element
);
240 #endif /* __APPLE_API_UNSTABLE */
242 #ifdef __APPLE_API_EVOLVING
244 extern wait_queue_t
wait_queue_alloc(
247 extern kern_return_t
wait_queue_free(
248 wait_queue_t wait_queue
);
250 extern kern_return_t
wait_queue_link(
251 wait_queue_t wait_queue
,
252 wait_queue_set_t set_queue
);
254 extern kern_return_t
wait_queue_unlink(
255 wait_queue_t wait_queue
,
256 wait_queue_set_t set_queue
);
258 extern kern_return_t
wait_queue_unlink_all(
259 wait_queue_t wait_queue
);
261 extern kern_return_t
wait_queue_set_unlink_all(
262 wait_queue_set_t set_queue
);
264 /* assert intent to wait on <wait_queue,event64> pair */
265 extern wait_result_t
wait_queue_assert_wait64(
266 wait_queue_t wait_queue
,
267 event64_t wait_event
,
268 wait_interrupt_t interruptible
);
270 /* wakeup the most appropriate thread waiting on <wait_queue,event64> pair */
271 extern kern_return_t
wait_queue_wakeup64_one(
272 wait_queue_t wait_queue
,
273 event64_t wake_event
,
274 wait_result_t result
);
276 /* wakeup all the threads waiting on <wait_queue,event64> pair */
277 extern kern_return_t
wait_queue_wakeup64_all(
278 wait_queue_t wait_queue
,
279 event64_t wake_event
,
280 wait_result_t result
);
282 /* wakeup a specified thread waiting iff waiting on <wait_queue,event64> pair */
283 extern kern_return_t
wait_queue_wakeup64_thread(
284 wait_queue_t wait_queue
,
285 event64_t wake_event
,
287 wait_result_t result
);
289 #endif /* __APPLE_API_EVOLVING */
292 * Compatibility Wait Queue APIs based on pointer events instead of 64bit
296 /* assert intent to wait on <wait_queue,event> pair */
297 extern wait_result_t
wait_queue_assert_wait(
298 wait_queue_t wait_queue
,
300 wait_interrupt_t interruptible
);
302 /* wakeup the most appropriate thread waiting on <wait_queue,event> pair */
303 extern kern_return_t
wait_queue_wakeup_one(
304 wait_queue_t wait_queue
,
306 wait_result_t result
);
308 /* wakeup all the threads waiting on <wait_queue,event> pair */
309 extern kern_return_t
wait_queue_wakeup_all(
310 wait_queue_t wait_queue
,
312 wait_result_t result
);
314 /* wakeup a specified thread waiting iff waiting on <wait_queue,event> pair */
315 extern kern_return_t
wait_queue_wakeup_thread(
316 wait_queue_t wait_queue
,
319 wait_result_t result
);
321 #endif /* __APPLE_API_PRIVATE */
323 #endif /* _KERN_WAIT_QUEUE_H_ */