]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/wait_queue.h
xnu-517.tar.gz
[apple/xnu.git] / osfmk / kern / wait_queue.h
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
43866e37 6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
1c79356b 7 *
43866e37
A
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
13 * file.
14 *
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
1c79356b
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
43866e37
A
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.
1c79356b
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25#ifndef _KERN_WAIT_QUEUE_H_
26#define _KERN_WAIT_QUEUE_H_
27
9bccf70c
A
28#include <sys/appleapiopts.h>
29
30#ifdef __APPLE_API_PRIVATE
31
1c79356b 32#include <mach/sync_policy.h>
0b4e3aa0 33#include <mach/kern_return.h> /* for kern_return_t */
1c79356b 34
9bccf70c
A
35#include <kern/kern_types.h> /* for wait_queue_t */
36
37#ifdef MACH_KERNEL_PRIVATE
1c79356b
A
38
39#include <kern/lock.h>
40#include <kern/queue.h>
41
9bccf70c 42
1c79356b
A
43/*
44 * wait_queue_t
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).
50 *
51 * It is not published to other kernel components. They
52 * can create wait queues by calling wait_queue_alloc.
53 *
54 * NOTE: Hardware locks are used to protect event wait
55 * queues since interrupt code is free to post events to
56 * them.
57 */
58typedef struct wait_queue {
9bccf70c
A
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 */
1c79356b 64 hw_lock_data_t wq_interlock; /* interlock */
9bccf70c 65 queue_head_t wq_queue; /* queue of elements */
1c79356b
A
66} WaitQueue;
67
68/*
9bccf70c
A
69 * wait_queue_set_t
70 * This is the common definition for a set wait queue.
1c79356b
A
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.
74 */
9bccf70c
A
75typedef struct wait_queue_set {
76 WaitQueue wqs_wait_queue; /* our wait queue */
77 queue_head_t wqs_setlinks; /* links from set perspective */
0b4e3aa0 78 unsigned int wqs_refcount; /* refcount for preposting */
9bccf70c 79} WaitQueueSet;
1c79356b 80
9bccf70c
A
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
1c79356b
A
85
86/*
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
9bccf70c 92 * to other (set) wait queues.
1c79356b 93 *
9bccf70c
A
94 * WARNING: These fields correspond to fields in the thread
95 * shuttle (run queue links and run queue pointer). Any change in
1c79356b
A
96 * the layout here will have to be matched with a change there.
97 */
98typedef struct wait_queue_element {
99 queue_chain_t wqe_links; /* link of elements on this queue */
9bccf70c 100 void * wqe_type; /* Identifies link vs. thread */
1c79356b 101 wait_queue_t wqe_queue; /* queue this element is on */
9bccf70c 102} WaitQueueElement;
1c79356b 103
9bccf70c 104typedef WaitQueueElement *wait_queue_element_t;
0b4e3aa0 105
1c79356b
A
106/*
107 * wait_queue_link_t
9bccf70c 108 * Specialized wait queue element type for linking set
1c79356b
A
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.
113 *
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.
120 */
121typedef struct wait_queue_link {
9bccf70c
A
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 */
0b4e3aa0
A
125} WaitQueueLink;
126
1c79356b 127#define wql_links wql_element.wqe_links
9bccf70c 128#define wql_type wql_element.wqe_type
1c79356b 129#define wql_queue wql_element.wqe_queue
0b4e3aa0 130
9bccf70c
A
131#define _WAIT_QUEUE_inited 0xf1d0
132#define _WAIT_QUEUE_SET_inited 0xf1d1
0b4e3aa0 133
9bccf70c
A
134#define wait_queue_is_queue(wq) \
135 ((wq)->wq_type == _WAIT_QUEUE_inited)
1c79356b 136
9bccf70c
A
137#define wait_queue_is_set(wqs) \
138 ((wqs)->wqs_type == _WAIT_QUEUE_SET_inited)
1c79356b 139
9bccf70c
A
140#define wait_queue_is_valid(wq) \
141 (((wq)->wq_type & ~1) == _WAIT_QUEUE_inited)
1c79356b 142
9bccf70c
A
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))
1c79356b 146
9bccf70c
A
147/*
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.
152 */
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))
1c79356b 157
9bccf70c
A
158#define wait_queue_unlock(wq) \
159 (assert(wait_queue_held(wq)), hw_lock_unlock(&(wq)->wq_interlock))
1c79356b 160
9bccf70c
A
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)
1c79356b
A
164
165#define wait_queue_assert_possible(thread) \
166 ((thread)->wait_queue == WAIT_QUEUE_NULL)
167
1c79356b
A
168/******** Decomposed interfaces (to build higher level constructs) ***********/
169
1c79356b 170/* assert intent to wait on a locked wait queue */
9bccf70c 171__private_extern__ wait_result_t wait_queue_assert_wait64_locked(
1c79356b 172 wait_queue_t wait_queue,
9bccf70c
A
173 event64_t wait_event,
174 wait_interrupt_t interruptible,
55e303ae 175 thread_t thread);
1c79356b
A
176
177/* peek to see which thread would be chosen for a wakeup - but keep on queue */
9bccf70c 178__private_extern__ void wait_queue_peek64_locked(
1c79356b 179 wait_queue_t wait_queue,
9bccf70c 180 event64_t event,
1c79356b
A
181 thread_t *thread,
182 wait_queue_t *found_queue);
183
184/* peek to see which thread would be chosen for a wakeup - but keep on queue */
9bccf70c 185__private_extern__ void wait_queue_pull_thread_locked(
1c79356b
A
186 wait_queue_t wait_queue,
187 thread_t thread,
188 boolean_t unlock);
189
190/* wakeup all threads waiting for a particular event on locked queue */
9bccf70c 191__private_extern__ kern_return_t wait_queue_wakeup64_all_locked(
1c79356b 192 wait_queue_t wait_queue,
9bccf70c
A
193 event64_t wake_event,
194 wait_result_t result,
1c79356b
A
195 boolean_t unlock);
196
197/* wakeup one thread waiting for a particular event on locked queue */
9bccf70c 198__private_extern__ kern_return_t wait_queue_wakeup64_one_locked(
1c79356b 199 wait_queue_t wait_queue,
9bccf70c
A
200 event64_t wake_event,
201 wait_result_t result,
1c79356b
A
202 boolean_t unlock);
203
1c79356b 204/* return identity of a thread awakened for a particular <wait_queue,event> */
9bccf70c 205__private_extern__ thread_t wait_queue_wakeup64_identity_locked(
1c79356b 206 wait_queue_t wait_queue,
9bccf70c
A
207 event64_t wake_event,
208 wait_result_t result,
1c79356b
A
209 boolean_t unlock);
210
211/* wakeup thread iff its still waiting for a particular event on locked queue */
9bccf70c 212__private_extern__ kern_return_t wait_queue_wakeup64_thread_locked(
1c79356b 213 wait_queue_t wait_queue,
9bccf70c 214 event64_t wake_event,
1c79356b 215 thread_t thread,
9bccf70c 216 wait_result_t result,
1c79356b
A
217 boolean_t unlock);
218
219#endif /* MACH_KERNEL_PRIVATE */
220
9bccf70c
A
221#ifdef __APPLE_API_UNSTABLE
222/******** Semi-Public interfaces (not a part of a higher construct) ************/
223
224extern kern_return_t wait_queue_init(
225 wait_queue_t wait_queue,
226 int policy);
227
228extern wait_queue_set_t wait_queue_set_alloc(
229 int policy);
230
231extern kern_return_t wait_queue_set_free(
232 wait_queue_set_t set_queue);
233
234extern wait_queue_link_t wait_queue_link_alloc(
235 int policy);
236
237extern kern_return_t wait_queue_link_free(
238 wait_queue_link_t link_element);
239
240#endif /* __APPLE_API_UNSTABLE */
241
242#ifdef __APPLE_API_EVOLVING
243
1c79356b 244extern wait_queue_t wait_queue_alloc(
9bccf70c
A
245 int policy);
246
247extern kern_return_t wait_queue_free(
248 wait_queue_t wait_queue);
1c79356b 249
9bccf70c
A
250extern kern_return_t wait_queue_link(
251 wait_queue_t wait_queue,
252 wait_queue_set_t set_queue);
253
254extern kern_return_t wait_queue_unlink(
255 wait_queue_t wait_queue,
256 wait_queue_set_t set_queue);
257
258extern kern_return_t wait_queue_unlink_all(
1c79356b
A
259 wait_queue_t wait_queue);
260
9bccf70c
A
261extern kern_return_t wait_queue_set_unlink_all(
262 wait_queue_set_t set_queue);
263
264/* assert intent to wait on <wait_queue,event64> pair */
265extern wait_result_t wait_queue_assert_wait64(
266 wait_queue_t wait_queue,
267 event64_t wait_event,
268 wait_interrupt_t interruptible);
269
270/* wakeup the most appropriate thread waiting on <wait_queue,event64> pair */
271extern kern_return_t wait_queue_wakeup64_one(
272 wait_queue_t wait_queue,
273 event64_t wake_event,
274 wait_result_t result);
275
276/* wakeup all the threads waiting on <wait_queue,event64> pair */
277extern kern_return_t wait_queue_wakeup64_all(
278 wait_queue_t wait_queue,
279 event64_t wake_event,
280 wait_result_t result);
281
282/* wakeup a specified thread waiting iff waiting on <wait_queue,event64> pair */
283extern kern_return_t wait_queue_wakeup64_thread(
284 wait_queue_t wait_queue,
285 event64_t wake_event,
286 thread_t thread,
287 wait_result_t result);
288
289#endif /* __APPLE_API_EVOLVING */
290
291/*
292 * Compatibility Wait Queue APIs based on pointer events instead of 64bit
293 * integer events.
294 */
1c79356b
A
295
296/* assert intent to wait on <wait_queue,event> pair */
9bccf70c 297extern wait_result_t wait_queue_assert_wait(
1c79356b
A
298 wait_queue_t wait_queue,
299 event_t wait_event,
9bccf70c 300 wait_interrupt_t interruptible);
1c79356b
A
301
302/* wakeup the most appropriate thread waiting on <wait_queue,event> pair */
9bccf70c 303extern kern_return_t wait_queue_wakeup_one(
1c79356b
A
304 wait_queue_t wait_queue,
305 event_t wake_event,
9bccf70c 306 wait_result_t result);
1c79356b
A
307
308/* wakeup all the threads waiting on <wait_queue,event> pair */
9bccf70c 309extern kern_return_t wait_queue_wakeup_all(
1c79356b
A
310 wait_queue_t wait_queue,
311 event_t wake_event,
9bccf70c 312 wait_result_t result);
1c79356b
A
313
314/* wakeup a specified thread waiting iff waiting on <wait_queue,event> pair */
9bccf70c 315extern kern_return_t wait_queue_wakeup_thread(
1c79356b
A
316 wait_queue_t wait_queue,
317 event_t wake_event,
318 thread_t thread,
9bccf70c
A
319 wait_result_t result);
320
321#endif /* __APPLE_API_PRIVATE */
1c79356b
A
322
323#endif /* _KERN_WAIT_QUEUE_H_ */