]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | #ifndef _KERN_WAIT_QUEUE_H_ | |
23 | #define _KERN_WAIT_QUEUE_H_ | |
24 | ||
25 | #include <kern/kern_types.h> /* for wait_queue_t */ | |
26 | #include <mach/sync_policy.h> | |
27 | ||
28 | #ifdef MACH_KERNEL_PRIVATE | |
29 | ||
30 | #include <kern/lock.h> | |
31 | #include <kern/queue.h> | |
32 | ||
33 | /* | |
34 | * wait_queue_t | |
35 | * This is the definition of the common event wait queue | |
36 | * that the scheduler APIs understand. It is used | |
37 | * internally by the gerneralized event waiting mechanism | |
38 | * (assert_wait), and also for items that maintain their | |
39 | * own wait queues (such as ports and semaphores). | |
40 | * | |
41 | * It is not published to other kernel components. They | |
42 | * can create wait queues by calling wait_queue_alloc. | |
43 | * | |
44 | * NOTE: Hardware locks are used to protect event wait | |
45 | * queues since interrupt code is free to post events to | |
46 | * them. | |
47 | */ | |
48 | typedef struct wait_queue { | |
49 | hw_lock_data_t wq_interlock; /* interlock */ | |
50 | unsigned int /* flags */ | |
51 | /* boolean_t */ wq_fifo:1, /* fifo wakeup policy? */ | |
52 | wq_issub:1, /* is waitq linked? */ | |
53 | :0; /* force to long boundary */ | |
54 | queue_head_t wq_queue; /* queue of elements */ | |
55 | } WaitQueue; | |
56 | ||
57 | /* | |
58 | * wait_queue_sub_t | |
59 | * This is the common definition for a subordinate wait queue. | |
60 | * These can be linked as members/elements of multiple regular | |
61 | * wait queues. They have an additional set of linkages to | |
62 | * identify the linkage structures that point to them. | |
63 | */ | |
64 | typedef struct wait_queue_sub { | |
65 | WaitQueue wqs_wait_queue; /* our wait queue */ | |
66 | queue_head_t wqs_sublinks; /* links from sub perspective */ | |
67 | } WaitQueueSub; | |
68 | ||
69 | typedef WaitQueueSub *wait_queue_sub_t; | |
70 | ||
71 | #define WAIT_QUEUE_SUB_NULL ((wait_queue_sub_t)0) | |
72 | ||
73 | ||
74 | /* | |
75 | * wait_queue_element_t | |
76 | * This structure describes the elements on an event wait | |
77 | * queue. It is the common first fields in a thread shuttle | |
78 | * and wait_queue_link_t. In that way, a wait queue can | |
79 | * consist of both thread shuttle elements and links off of | |
80 | * to other (subordinate) wait queues. | |
81 | * | |
82 | * WARNING: The first three fields of the thread shuttle | |
83 | * definition does not use this definition yet. Any change in | |
84 | * the layout here will have to be matched with a change there. | |
85 | */ | |
86 | typedef struct wait_queue_element { | |
87 | queue_chain_t wqe_links; /* link of elements on this queue */ | |
88 | wait_queue_t wqe_queue; /* queue this element is on */ | |
89 | event_t wqe_event; /* event this element is waiting for */ | |
90 | } *wait_queue_element_t; | |
91 | ||
92 | /* | |
93 | * wait_queue_link_t | |
94 | * Specialized wait queue element type for linking subordinate | |
95 | * event waits queues onto a wait queue. In this way, an event | |
96 | * can be constructed so that any thread waiting on any number | |
97 | * of associated wait queues can handle the event, while letting | |
98 | * the thread only be linked on the single wait queue it blocked on. | |
99 | * | |
100 | * One use: ports in multiple portsets. Each thread is queued up | |
101 | * on the portset that it specifically blocked on during a receive | |
102 | * operation. Each port's event queue links in all the portset | |
103 | * event queues of which it is a member. An IPC event post associated | |
104 | * with that port may wake up any thread from any of those portsets, | |
105 | * or one that was waiting locally on the port itself. | |
106 | */ | |
107 | typedef struct wait_queue_link { | |
108 | struct wait_queue_element wql_element; /* element on master */ | |
109 | wait_queue_sub_t wql_subqueue; /* sub queue */ | |
110 | queue_chain_t wql_sublinks; /* element on sub */ | |
111 | } *wait_queue_link_t; | |
112 | ||
113 | #define WAIT_QUEUE_LINK_NULL ((wait_queue_link_t)0) | |
114 | ||
115 | #define wql_links wql_element.wqe_links | |
116 | #define wql_queue wql_element.wqe_queue | |
117 | #define wql_event wql_element.wqe_event | |
118 | ||
119 | extern int wait_queue_subordinate; | |
120 | #define WAIT_QUEUE_SUBORDINATE &_wait_queue_subordinate | |
121 | ||
122 | extern void wait_queue_init( | |
123 | wait_queue_t wait_queue, | |
124 | int policy); | |
125 | ||
126 | extern kern_return_t wait_queue_link( | |
127 | wait_queue_t wait_queue, | |
128 | wait_queue_sub_t subordinate_queue); | |
129 | ||
130 | extern kern_return_t wait_queue_unlink( | |
131 | wait_queue_t wait_queue, | |
132 | wait_queue_sub_t subordinate_queue); | |
133 | extern void wait_queue_unlink_one( | |
134 | wait_queue_t wait_queue, | |
135 | wait_queue_sub_t *subordinate_queue_pointer); | |
136 | ||
137 | extern boolean_t wait_queue_member_queue( | |
138 | wait_queue_t wait_queue, | |
139 | wait_queue_sub_t subordinate_queue); | |
140 | ||
141 | extern kern_return_t clear_wait_queue_internal( | |
142 | thread_t thread, | |
143 | int result); | |
144 | ||
145 | extern kern_return_t wait_queue_remove( | |
146 | thread_t thread); | |
147 | ||
148 | #define wait_queue_assert_possible(thread) \ | |
149 | ((thread)->wait_queue == WAIT_QUEUE_NULL) | |
150 | ||
151 | ||
152 | #define wait_queue_empty(wq) (queue_empty(&(wq)->wq_queue)) | |
153 | ||
154 | #define wait_queue_held(wq) (hw_lock_held(&(wq)->wq_interlock)) | |
155 | ||
156 | #define wait_queue_is_sub(wqs) ((wqs)->wqs_wait_queue.wq_issub) | |
157 | #define wqs_lock(wqs) wait_queue_lock(&(wqs)->wqs_wait_queue) | |
158 | #define wqs_unlock(wqs) wait_queue_unlock(&(wqs)->wqs_wait_queue) | |
159 | #define wqs_lock_try(wqs) wait_queue__try_lock(&(wqs)->wqs_wait_queue) | |
160 | ||
161 | /******** Decomposed interfaces (to build higher level constructs) ***********/ | |
162 | ||
163 | extern void wait_queue_lock( | |
164 | wait_queue_t wait_queue); | |
165 | ||
166 | extern void wait_queue_unlock( | |
167 | wait_queue_t wait_queue); | |
168 | ||
169 | extern boolean_t wait_queue_lock_try( | |
170 | wait_queue_t wait_queue); | |
171 | ||
172 | /* assert intent to wait on a locked wait queue */ | |
173 | extern void wait_queue_assert_wait_locked( | |
174 | wait_queue_t wait_queue, | |
175 | event_t wait_event, | |
176 | int interruptible, | |
177 | boolean_t unlock); | |
178 | ||
179 | /* peek to see which thread would be chosen for a wakeup - but keep on queue */ | |
180 | extern void wait_queue_peek_locked( | |
181 | wait_queue_t wait_queue, | |
182 | event_t event, | |
183 | thread_t *thread, | |
184 | wait_queue_t *found_queue); | |
185 | ||
186 | /* peek to see which thread would be chosen for a wakeup - but keep on queue */ | |
187 | extern void wait_queue_pull_thread_locked( | |
188 | wait_queue_t wait_queue, | |
189 | thread_t thread, | |
190 | boolean_t unlock); | |
191 | ||
192 | /* wakeup all threads waiting for a particular event on locked queue */ | |
193 | extern kern_return_t wait_queue_wakeup_one_locked( | |
194 | wait_queue_t wait_queue, | |
195 | event_t wake_event, | |
196 | int result, | |
197 | boolean_t unlock); | |
198 | ||
199 | /* wakeup one thread waiting for a particular event on locked queue */ | |
200 | extern kern_return_t wait_queue_wakeup_one_locked( | |
201 | wait_queue_t wait_queue, | |
202 | event_t wake_event, | |
203 | int result, | |
204 | boolean_t unlock); | |
205 | ||
206 | /* return the identity of a thread that is waiting for <wait_queue, event> */ | |
207 | extern thread_t wait_queue_recommend_locked( | |
208 | wait_queue_t wait_queue, | |
209 | event_t wake_event); | |
210 | ||
211 | /* return identity of a thread awakened for a particular <wait_queue,event> */ | |
212 | extern thread_t wait_queue_wakeup_identity_locked( | |
213 | wait_queue_t wait_queue, | |
214 | event_t wake_event, | |
215 | int result, | |
216 | boolean_t unlock); | |
217 | ||
218 | /* wakeup thread iff its still waiting for a particular event on locked queue */ | |
219 | extern kern_return_t wait_queue_wakeup_thread_locked( | |
220 | wait_queue_t wait_queue, | |
221 | event_t wake_event, | |
222 | thread_t thread, | |
223 | int result, | |
224 | boolean_t unlock); | |
225 | ||
226 | #endif /* MACH_KERNEL_PRIVATE */ | |
227 | ||
228 | extern wait_queue_t wait_queue_alloc( | |
229 | int policy); | |
230 | ||
231 | extern void wait_queue_free( | |
232 | wait_queue_t wait_queue); | |
233 | ||
234 | /******** Standalone interfaces (not a part of a higher construct) ************/ | |
235 | ||
236 | /* assert intent to wait on <wait_queue,event> pair */ | |
237 | extern void wait_queue_assert_wait( | |
238 | wait_queue_t wait_queue, | |
239 | event_t wait_event, | |
240 | int interruptible); | |
241 | ||
242 | /* wakeup the most appropriate thread waiting on <wait_queue,event> pair */ | |
243 | extern kern_return_t wait_queue_wakeup_one( | |
244 | wait_queue_t wait_queue, | |
245 | event_t wake_event, | |
246 | int result); | |
247 | ||
248 | /* wakeup all the threads waiting on <wait_queue,event> pair */ | |
249 | extern kern_return_t wait_queue_wakeup_all( | |
250 | wait_queue_t wait_queue, | |
251 | event_t wake_event, | |
252 | int result); | |
253 | ||
254 | /* wakeup a specified thread waiting iff waiting on <wait_queue,event> pair */ | |
255 | extern kern_return_t wait_queue_wakeup_thread( | |
256 | wait_queue_t wait_queue, | |
257 | event_t wake_event, | |
258 | thread_t thread, | |
259 | int result); | |
260 | ||
261 | #endif /* _KERN_WAIT_QUEUE_H_ */ |