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