1 | /* |
2 | * Copyright (c) 2000-2016 Apple Computer, Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | /* |
29 | * @OSF_COPYRIGHT@ |
30 | */ |
31 | /* |
32 | * Mach Operating System |
33 | * Copyright (c) 1991,1990,1989 Carnegie Mellon University |
34 | * All Rights Reserved. |
35 | * |
36 | * Permission to use, copy, modify and distribute this software and its |
37 | * documentation is hereby granted, provided that both the copyright |
38 | * notice and this permission notice appear in all copies of the |
39 | * software, derivative works or modified versions, and any portions |
40 | * thereof, and that both notices appear in supporting documentation. |
41 | * |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
45 | * |
46 | * Carnegie Mellon requests users of this software to return to |
47 | * |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
49 | * School of Computer Science |
50 | * Carnegie Mellon University |
51 | * Pittsburgh PA 15213-3890 |
52 | * |
53 | * any improvements or extensions that they make and grant Carnegie Mellon |
54 | * the rights to redistribute these changes. |
55 | */ |
56 | /* |
57 | * NOTICE: This file was modified by McAfee Research in 2004 to introduce |
58 | * support for mandatory and extensible security protections. This notice |
59 | * is included in support of clause 2.2 (b) of the Apple Public License, |
60 | * Version 2.0. |
61 | */ |
62 | /* |
63 | */ |
64 | /* |
65 | * File: ipc/ipc_port.h |
66 | * Author: Rich Draves |
67 | * Date: 1989 |
68 | * |
69 | * Definitions for ports. |
70 | */ |
71 | |
72 | #ifndef _IPC_IPC_PORT_H_ |
73 | #define _IPC_IPC_PORT_H_ |
74 | |
75 | #ifdef MACH_KERNEL_PRIVATE |
76 | |
77 | #include <mach_assert.h> |
78 | #include <mach_debug.h> |
79 | |
80 | #include <mach/mach_types.h> |
81 | #include <mach/boolean.h> |
82 | #include <mach/kern_return.h> |
83 | #include <mach/port.h> |
84 | |
85 | #include <kern/assert.h> |
86 | #include <kern/kern_types.h> |
87 | #include <kern/turnstile.h> |
88 | |
89 | #include <ipc/ipc_types.h> |
90 | #include <ipc/ipc_object.h> |
91 | #include <ipc/ipc_mqueue.h> |
92 | #include <ipc/ipc_space.h> |
93 | |
94 | #include <security/_label.h> |
95 | |
96 | /* |
97 | * A receive right (port) can be in four states: |
98 | * 1) dead (not active, ip_timestamp has death time) |
99 | * 2) in a space (ip_receiver_name != 0, ip_receiver points |
100 | * to the space but doesn't hold a ref for it) |
101 | * 3) in transit (ip_receiver_name == 0, ip_destination points |
102 | * to the destination port and holds a ref for it) |
103 | * 4) in limbo (ip_receiver_name == 0, ip_destination == IP_NULL) |
104 | * |
105 | * If the port is active, and ip_receiver points to some space, |
106 | * then ip_receiver_name != 0, and that space holds receive rights. |
107 | * If the port is not active, then ip_timestamp contains a timestamp |
108 | * taken when the port was destroyed. |
109 | */ |
110 | |
111 | typedef unsigned int ipc_port_timestamp_t; |
112 | |
113 | struct ipc_port { |
114 | |
115 | /* |
116 | * Initial sub-structure in common with ipc_pset |
117 | * First element is an ipc_object second is a |
118 | * message queue |
119 | */ |
120 | struct ipc_object ip_object; |
121 | struct ipc_mqueue ip_messages; |
122 | |
123 | union { |
124 | struct ipc_space *receiver; |
125 | struct ipc_port *destination; |
126 | ipc_port_timestamp_t timestamp; |
127 | } data; |
128 | |
129 | union { |
130 | ipc_kobject_t kobject; |
131 | ipc_importance_task_t imp_task; |
132 | ipc_port_t sync_inheritor_port; |
133 | struct knote *sync_inheritor_knote; |
134 | struct turnstile *sync_inheritor_ts; |
135 | } kdata; |
136 | |
137 | struct ipc_port *ip_nsrequest; |
138 | struct ipc_port *ip_pdrequest; |
139 | struct ipc_port_request *ip_requests; |
140 | union { |
141 | struct ipc_kmsg *premsg; |
142 | struct turnstile *send_turnstile; |
143 | SLIST_ENTRY(ipc_port) dealloc_elm; |
144 | } kdata2; |
145 | |
146 | mach_vm_address_t ip_context; |
147 | |
148 | natural_t ip_sprequests:1, /* send-possible requests outstanding */ |
149 | ip_spimportant:1, /* ... at least one is importance donating */ |
150 | ip_impdonation:1, /* port supports importance donation */ |
151 | ip_tempowner:1, /* dont give donations to current receiver */ |
152 | ip_guarded:1, /* port guarded (use context value as guard) */ |
153 | ip_strict_guard:1, /* Strict guarding; Prevents user manipulation of context values directly */ |
154 | ip_specialreply:1, /* port is a special reply port */ |
155 | ip_sync_link_state:3, /* link the special reply port to destination port/ Workloop */ |
156 | ip_impcount:22; /* number of importance donations in nested queue */ |
157 | |
158 | mach_port_mscount_t ip_mscount; |
159 | mach_port_rights_t ip_srights; |
160 | mach_port_rights_t ip_sorights; |
161 | |
162 | #if MACH_ASSERT |
163 | #define IP_NSPARES 4 |
164 | #define IP_CALLSTACK_MAX 16 |
165 | /* queue_chain_t ip_port_links;*//* all allocated ports */ |
166 | thread_t ip_thread; /* who made me? thread context */ |
167 | unsigned long ip_timetrack; /* give an idea of "when" created */ |
168 | uintptr_t ip_callstack[IP_CALLSTACK_MAX]; /* stack trace */ |
169 | unsigned long ip_spares[IP_NSPARES]; /* for debugging */ |
170 | #endif /* MACH_ASSERT */ |
171 | #if DEVELOPMENT || DEBUG |
172 | uint8_t ip_srp_lost_link:1, /* special reply port turnstile link chain broken */ |
173 | ip_srp_msg_sent:1; /* special reply port msg sent */ |
174 | #endif |
175 | }; |
176 | |
177 | |
178 | #define ip_references ip_object.io_references |
179 | #define ip_bits ip_object.io_bits |
180 | |
181 | #define ip_receiver_name ip_messages.imq_receiver_name |
182 | #define ip_in_pset ip_messages.imq_in_pset |
183 | |
184 | #define ip_receiver data.receiver |
185 | #define ip_destination data.destination |
186 | #define ip_timestamp data.timestamp |
187 | |
188 | #define ip_kobject kdata.kobject |
189 | #define ip_imp_task kdata.imp_task |
190 | #define ip_sync_inheritor_port kdata.sync_inheritor_port |
191 | #define ip_sync_inheritor_knote kdata.sync_inheritor_knote |
192 | #define ip_sync_inheritor_ts kdata.sync_inheritor_ts |
193 | |
194 | #define ip_premsg kdata2.premsg |
195 | #define ip_send_turnstile kdata2.send_turnstile |
196 | #define ip_dealloc_elm kdata2.dealloc_elm |
197 | |
198 | #define port_send_turnstile(port) (IP_PREALLOC(port) ? (port)->ip_premsg->ikm_turnstile : (port)->ip_send_turnstile) |
199 | |
200 | #define set_port_send_turnstile(port, value) \ |
201 | MACRO_BEGIN \ |
202 | if (IP_PREALLOC(port)) { \ |
203 | (port)->ip_premsg->ikm_turnstile = (value); \ |
204 | } else { \ |
205 | (port)->ip_send_turnstile = (value); \ |
206 | } \ |
207 | MACRO_END |
208 | |
209 | #define port_send_turnstile_address(port) \ |
210 | (IP_PREALLOC(port) ? &((port)->ip_premsg->ikm_turnstile) : &((port)->ip_send_turnstile)) |
211 | |
212 | #define port_rcv_turnstile_address(port) (NULL) |
213 | |
214 | |
215 | /* |
216 | * SYNC IPC state flags for special reply port. |
217 | * |
218 | * PORT_SYNC_LINK_ANY |
219 | * Special reply port is not linked to any other port |
220 | * or WL and linkage should be allowed. |
221 | * |
222 | * PORT_SYNC_LINK_PORT |
223 | * Special reply port is linked to the port and |
224 | * ip_sync_inheritor_port contains the inheritor |
225 | * port. |
226 | * |
227 | * PORT_SYNC_LINK_WORKLOOP_KNOTE |
228 | * Special reply port is linked to a WL (via a knote). |
229 | * ip_sync_inheritor_knote contains a pointer to the knote |
230 | * the port is stashed on. |
231 | * |
232 | * PORT_SYNC_LINK_WORKLOOP_STASH |
233 | * Special reply port is linked to a WL (via a knote stash). |
234 | * ip_sync_inheritor_ts contains a pointer to the turnstile with a +1 |
235 | * the port is stashed on. |
236 | * |
237 | * PORT_SYNC_LINK_NO_LINKAGE |
238 | * Message sent to special reply port, do |
239 | * not allow any linkages till receive is |
240 | * complete. |
241 | */ |
242 | #define PORT_SYNC_LINK_ANY (0) |
243 | #define PORT_SYNC_LINK_PORT (0x1) |
244 | #define PORT_SYNC_LINK_WORKLOOP_KNOTE (0x2) |
245 | #define PORT_SYNC_LINK_WORKLOOP_STASH (0x3) |
246 | #define PORT_SYNC_LINK_NO_LINKAGE (0x4) |
247 | |
248 | #define IP_NULL IPC_PORT_NULL |
249 | #define IP_DEAD IPC_PORT_DEAD |
250 | #define IP_VALID(port) IPC_PORT_VALID(port) |
251 | |
252 | #define ip_active(port) io_active(&(port)->ip_object) |
253 | #define ip_lock_init(port) io_lock_init(&(port)->ip_object) |
254 | #define ip_lock(port) io_lock(&(port)->ip_object) |
255 | #define ip_lock_try(port) io_lock_try(&(port)->ip_object) |
256 | #define ip_lock_held_kdp(port) io_lock_held_kdp(&(port)->ip_object) |
257 | #define ip_unlock(port) io_unlock(&(port)->ip_object) |
258 | |
259 | #define ip_reference(port) io_reference(&(port)->ip_object) |
260 | #define ip_release(port) io_release(&(port)->ip_object) |
261 | |
262 | /* get an ipc_port pointer from an ipc_mqueue pointer */ |
263 | #define ip_from_mq(mq) \ |
264 | __container_of(mq, struct ipc_port, ip_messages) |
265 | |
266 | #define ip_reference_mq(mq) ip_reference(ip_from_mq(mq)) |
267 | #define ip_release_mq(mq) ip_release(ip_from_mq(mq)) |
268 | |
269 | #define ip_kotype(port) io_kotype(&(port)->ip_object) |
270 | |
271 | #define ip_full_kernel(port) imq_full_kernel(&(port)->ip_messages) |
272 | #define ip_full(port) imq_full(&(port)->ip_messages) |
273 | |
274 | /* |
275 | * JMM - Preallocation flag |
276 | * This flag indicates that there is a message buffer preallocated for this |
277 | * port and we should use that when sending (from the kernel) rather than |
278 | * allocate a new one. This avoids deadlocks during notification message |
279 | * sends by critical system threads (which may be needed to free memory and |
280 | * therefore cannot be blocked waiting for memory themselves). |
281 | */ |
282 | #define IP_BIT_PREALLOC 0x00008000 /* preallocated mesg */ |
283 | #define IP_PREALLOC(port) ((port)->ip_bits & IP_BIT_PREALLOC) |
284 | |
285 | #define IP_SET_PREALLOC(port, kmsg) \ |
286 | MACRO_BEGIN \ |
287 | (port)->ip_bits |= IP_BIT_PREALLOC; \ |
288 | (port)->ip_premsg = (kmsg); \ |
289 | MACRO_END |
290 | |
291 | #define IP_CLEAR_PREALLOC(port, kmsg) \ |
292 | MACRO_BEGIN \ |
293 | assert((port)->ip_premsg == kmsg); \ |
294 | (port)->ip_bits &= ~IP_BIT_PREALLOC; \ |
295 | (port)->ip_premsg = IKM_NULL; \ |
296 | MACRO_END |
297 | |
298 | /* JMM - address alignment/packing for LP64 */ |
299 | struct ipc_port_request { |
300 | union { |
301 | struct ipc_port *port; |
302 | ipc_port_request_index_t index; |
303 | } notify; |
304 | |
305 | union { |
306 | mach_port_name_t name; |
307 | struct ipc_table_size *size; |
308 | } name; |
309 | }; |
310 | |
311 | #define ipr_next notify.index |
312 | #define ipr_size name.size |
313 | |
314 | #define ipr_soright notify.port |
315 | #define ipr_name name.name |
316 | |
317 | /* |
318 | * Use the low bits in the ipr_soright to specify the request type |
319 | */ |
320 | #define IPR_SOR_SPARM_MASK 1 /* send-possible armed */ |
321 | #define IPR_SOR_SPREQ_MASK 2 /* send-possible requested */ |
322 | #define IPR_SOR_SPBIT_MASK 3 /* combo */ |
323 | #define IPR_SOR_SPARMED(sor) (((uintptr_t)(sor) & IPR_SOR_SPARM_MASK) != 0) |
324 | #define IPR_SOR_SPREQ(sor) (((uintptr_t)(sor) & IPR_SOR_SPREQ_MASK) != 0) |
325 | #define IPR_SOR_PORT(sor) ((ipc_port_t)((uintptr_t)(sor) & ~IPR_SOR_SPBIT_MASK)) |
326 | #define IPR_SOR_MAKE(p,m) ((ipc_port_t)((uintptr_t)(p) | (m))) |
327 | |
328 | extern lck_grp_t ipc_lck_grp; |
329 | extern lck_attr_t ipc_lck_attr; |
330 | |
331 | /* |
332 | * Taking the ipc_port_multiple lock grants the privilege |
333 | * to lock multiple ports at once. No ports must locked |
334 | * when it is taken. |
335 | */ |
336 | |
337 | extern lck_spin_t ipc_port_multiple_lock_data; |
338 | |
339 | #define ipc_port_multiple_lock_init() \ |
340 | lck_spin_init(&ipc_port_multiple_lock_data, &ipc_lck_grp, &ipc_lck_attr) |
341 | |
342 | #define ipc_port_multiple_lock() \ |
343 | lck_spin_lock(&ipc_port_multiple_lock_data) |
344 | |
345 | #define ipc_port_multiple_unlock() \ |
346 | lck_spin_unlock(&ipc_port_multiple_lock_data) |
347 | |
348 | /* |
349 | * The port timestamp facility provides timestamps |
350 | * for port destruction. It is used to serialize |
351 | * mach_port_names with port death. |
352 | */ |
353 | |
354 | extern ipc_port_timestamp_t ipc_port_timestamp_data; |
355 | |
356 | /* Retrieve a port timestamp value */ |
357 | extern ipc_port_timestamp_t ipc_port_timestamp(void); |
358 | |
359 | /* |
360 | * Compares two timestamps, and returns TRUE if one |
361 | * happened before two. Note that this formulation |
362 | * works when the timestamp wraps around at 2^32, |
363 | * as long as one and two aren't too far apart. |
364 | */ |
365 | |
366 | #define IP_TIMESTAMP_ORDER(one, two) ((int) ((one) - (two)) < 0) |
367 | |
368 | #define ipc_port_translate_receive(space, name, portp) \ |
369 | ipc_object_translate((space), (name), \ |
370 | MACH_PORT_RIGHT_RECEIVE, \ |
371 | (ipc_object_t *) (portp)) |
372 | |
373 | #define ipc_port_translate_send(space, name, portp) \ |
374 | ipc_object_translate((space), (name), \ |
375 | MACH_PORT_RIGHT_SEND, \ |
376 | (ipc_object_t *) (portp)) |
377 | |
378 | /* Allocate a notification request slot */ |
379 | #if IMPORTANCE_INHERITANCE |
380 | extern kern_return_t |
381 | ipc_port_request_alloc( |
382 | ipc_port_t port, |
383 | mach_port_name_t name, |
384 | ipc_port_t soright, |
385 | boolean_t send_possible, |
386 | boolean_t immediate, |
387 | ipc_port_request_index_t *indexp, |
388 | boolean_t *importantp); |
389 | #else |
390 | extern kern_return_t |
391 | ipc_port_request_alloc( |
392 | ipc_port_t port, |
393 | mach_port_name_t name, |
394 | ipc_port_t soright, |
395 | boolean_t send_possible, |
396 | boolean_t immediate, |
397 | ipc_port_request_index_t *indexp); |
398 | #endif /* IMPORTANCE_INHERITANCE */ |
399 | |
400 | /* Grow one of a port's tables of notifcation requests */ |
401 | extern kern_return_t ipc_port_request_grow( |
402 | ipc_port_t port, |
403 | ipc_table_elems_t target_size); |
404 | |
405 | /* Return the type(s) of notification requests outstanding */ |
406 | extern mach_port_type_t ipc_port_request_type( |
407 | ipc_port_t port, |
408 | mach_port_name_t name, |
409 | ipc_port_request_index_t index); |
410 | |
411 | /* Cancel a notification request and return the send-once right */ |
412 | extern ipc_port_t ipc_port_request_cancel( |
413 | ipc_port_t port, |
414 | mach_port_name_t name, |
415 | ipc_port_request_index_t index); |
416 | |
417 | /* Arm any delayed send-possible notification */ |
418 | extern boolean_t ipc_port_request_sparm( |
419 | ipc_port_t port, |
420 | mach_port_name_t name, |
421 | ipc_port_request_index_t index, |
422 | mach_msg_option_t option, |
423 | mach_msg_priority_t override); |
424 | |
425 | /* Macros for manipulating a port's dead name notificaiton requests */ |
426 | #define ipc_port_request_rename(port, index, oname, nname) \ |
427 | MACRO_BEGIN \ |
428 | ipc_port_request_t ipr, table; \ |
429 | \ |
430 | assert(ip_active(port)); \ |
431 | \ |
432 | table = port->ip_requests; \ |
433 | assert(table != IPR_NULL); \ |
434 | \ |
435 | ipr = &table[index]; \ |
436 | assert(ipr->ipr_name == oname); \ |
437 | \ |
438 | ipr->ipr_name = nname; \ |
439 | MACRO_END |
440 | |
441 | |
442 | /* Make a port-deleted request */ |
443 | extern void ipc_port_pdrequest( |
444 | ipc_port_t port, |
445 | ipc_port_t notify, |
446 | ipc_port_t *previousp); |
447 | |
448 | /* Make a no-senders request */ |
449 | extern void ipc_port_nsrequest( |
450 | ipc_port_t port, |
451 | mach_port_mscount_t sync, |
452 | ipc_port_t notify, |
453 | ipc_port_t *previousp); |
454 | |
455 | #define ipc_port_set_mscount(port, mscount) \ |
456 | MACRO_BEGIN \ |
457 | assert(ip_active(port)); \ |
458 | \ |
459 | (port)->ip_mscount = (mscount); \ |
460 | MACRO_END |
461 | |
462 | /* Prepare a receive right for transmission/destruction */ |
463 | extern boolean_t ipc_port_clear_receiver( |
464 | ipc_port_t port, |
465 | boolean_t should_destroy); |
466 | |
467 | /* Initialize a newly-allocated port */ |
468 | extern void ipc_port_init( |
469 | ipc_port_t port, |
470 | ipc_space_t space, |
471 | mach_port_name_t name); |
472 | |
473 | /* Allocate a port */ |
474 | extern kern_return_t ipc_port_alloc( |
475 | ipc_space_t space, |
476 | mach_port_name_t *namep, |
477 | ipc_port_t *portp); |
478 | |
479 | /* Allocate a port, with a specific name */ |
480 | extern kern_return_t ipc_port_alloc_name( |
481 | ipc_space_t space, |
482 | mach_port_name_t name, |
483 | ipc_port_t *portp); |
484 | |
485 | /* Generate dead name notifications */ |
486 | extern void ipc_port_dnnotify( |
487 | ipc_port_t port); |
488 | |
489 | /* Generate send-possible notifications */ |
490 | extern void ipc_port_spnotify( |
491 | ipc_port_t port); |
492 | |
493 | /* Destroy a port */ |
494 | extern void ipc_port_destroy( |
495 | ipc_port_t port); |
496 | |
497 | /* Check if queueing "port" in a message for "dest" would create a circular |
498 | group of ports and messages */ |
499 | extern boolean_t |
500 | ipc_port_check_circularity( |
501 | ipc_port_t port, |
502 | ipc_port_t dest); |
503 | |
504 | #if IMPORTANCE_INHERITANCE |
505 | |
506 | enum { |
507 | IPID_OPTION_NORMAL = 0, /* normal boost */ |
508 | IPID_OPTION_SENDPOSSIBLE = 1, /* send-possible induced boost */ |
509 | }; |
510 | |
511 | /* link the destination port with special reply port */ |
512 | void |
513 | ipc_port_link_special_reply_port( |
514 | ipc_port_t special_reply_port, |
515 | ipc_port_t dest_port); |
516 | |
517 | #define IPC_PORT_ADJUST_SR_NONE 0 |
518 | #define IPC_PORT_ADJUST_SR_CLEAR_SPECIAL_REPLY 0x1 |
519 | #define IPC_PORT_ADJUST_SR_ALLOW_SYNC_LINKAGE 0x2 |
520 | #define IPC_PORT_ADJUST_SR_LINK_WORKLOOP 0x4 |
521 | |
522 | #define IPC_PORT_ADJUST_SR_RECEIVED_MSG 0x8 |
523 | #define IPC_PORT_ADJUST_SR_ENABLE_EVENT 0x10 |
524 | |
525 | void |
526 | reset_ip_srp_bits(ipc_port_t special_reply_port); |
527 | |
528 | void |
529 | reset_ip_srp_msg_sent(ipc_port_t special_reply_port); |
530 | |
531 | void |
532 | set_ip_srp_msg_sent(ipc_port_t special_reply_port); |
533 | |
534 | void |
535 | set_ip_srp_lost_link(ipc_port_t special_reply_port); |
536 | |
537 | /* Adjust special reply port linkage */ |
538 | void ipc_port_adjust_special_reply_port_locked( |
539 | ipc_port_t special_reply_port, |
540 | struct knote *kn, |
541 | uint8_t flags, |
542 | boolean_t get_turnstile); |
543 | |
544 | /* Adjust special reply port linkage */ |
545 | void |
546 | ipc_port_adjust_special_reply_port( |
547 | ipc_port_t special_reply_port, |
548 | uint8_t flags, |
549 | boolean_t get_turnstile); |
550 | |
551 | turnstile_inheritor_t |
552 | ipc_port_get_special_reply_port_inheritor( |
553 | ipc_port_t special_reply_port); |
554 | |
555 | void |
556 | ipc_port_send_turnstile_prepare(ipc_port_t port); |
557 | |
558 | void |
559 | ipc_port_send_turnstile_complete(ipc_port_t port); |
560 | |
561 | struct waitq * |
562 | ipc_port_rcv_turnstile_waitq(struct waitq *waitq); |
563 | |
564 | struct turnstile * |
565 | ipc_port_rcv_turnstile(ipc_port_t port); |
566 | |
567 | /* apply importance delta to port only */ |
568 | extern mach_port_delta_t |
569 | ipc_port_impcount_delta( |
570 | ipc_port_t port, |
571 | mach_port_delta_t delta, |
572 | ipc_port_t base); |
573 | |
574 | /* apply importance delta to port, and return task importance for update */ |
575 | extern boolean_t |
576 | ipc_port_importance_delta_internal( |
577 | ipc_port_t port, |
578 | natural_t options, |
579 | mach_port_delta_t *deltap, |
580 | ipc_importance_task_t *imp_task); |
581 | |
582 | /* Apply an importance delta to a port and reflect change in receiver task */ |
583 | extern boolean_t |
584 | ipc_port_importance_delta( |
585 | ipc_port_t port, |
586 | natural_t options, |
587 | mach_port_delta_t delta); |
588 | #endif /* IMPORTANCE_INHERITANCE */ |
589 | |
590 | /* Make a send-once notify port from a receive right */ |
591 | extern ipc_port_t ipc_port_lookup_notify( |
592 | ipc_space_t space, |
593 | mach_port_name_t name); |
594 | |
595 | /* Make a naked send right from a receive right - port locked and active */ |
596 | extern ipc_port_t ipc_port_make_send_locked( |
597 | ipc_port_t port); |
598 | |
599 | /* Make a naked send right from a receive right */ |
600 | extern ipc_port_t ipc_port_make_send( |
601 | ipc_port_t port); |
602 | |
603 | /* Make a naked send right from another naked send right */ |
604 | extern ipc_port_t ipc_port_copy_send( |
605 | ipc_port_t port); |
606 | |
607 | /* Copyout a naked send right */ |
608 | extern mach_port_name_t ipc_port_copyout_send( |
609 | ipc_port_t sright, |
610 | ipc_space_t space); |
611 | |
612 | /* Copyout a naked send right to given name */ |
613 | extern mach_port_name_t ipc_port_copyout_name_send( |
614 | ipc_port_t sright, |
615 | ipc_space_t space, |
616 | mach_port_name_t name); |
617 | |
618 | #endif /* MACH_KERNEL_PRIVATE */ |
619 | |
620 | #if KERNEL_PRIVATE |
621 | |
622 | /* Release a (valid) naked send right */ |
623 | extern void ipc_port_release_send( |
624 | ipc_port_t port); |
625 | |
626 | extern void ipc_port_reference( |
627 | ipc_port_t port); |
628 | |
629 | extern void ipc_port_release( |
630 | ipc_port_t port); |
631 | |
632 | #endif /* KERNEL_PRIVATE */ |
633 | |
634 | #ifdef MACH_KERNEL_PRIVATE |
635 | |
636 | /* Make a naked send-once right from a locked and active receive right */ |
637 | extern ipc_port_t ipc_port_make_sonce_locked( |
638 | ipc_port_t port); |
639 | |
640 | /* Make a naked send-once right from a receive right */ |
641 | extern ipc_port_t ipc_port_make_sonce( |
642 | ipc_port_t port); |
643 | |
644 | /* Release a naked send-once right */ |
645 | extern void ipc_port_release_sonce( |
646 | ipc_port_t port); |
647 | |
648 | /* Release a naked (in limbo or in transit) receive right */ |
649 | extern void ipc_port_release_receive( |
650 | ipc_port_t port); |
651 | |
652 | /* finalize the destruction of a port before it gets freed */ |
653 | extern void ipc_port_finalize( |
654 | ipc_port_t port); |
655 | |
656 | /* Allocate a port in a special space */ |
657 | extern ipc_port_t ipc_port_alloc_special( |
658 | ipc_space_t space); |
659 | |
660 | /* Deallocate a port in a special space */ |
661 | extern void ipc_port_dealloc_special( |
662 | ipc_port_t port, |
663 | ipc_space_t space); |
664 | |
665 | #if MACH_ASSERT |
666 | /* Track low-level port deallocation */ |
667 | extern void ipc_port_track_dealloc( |
668 | ipc_port_t port); |
669 | |
670 | /* Initialize general port debugging state */ |
671 | extern void ipc_port_debug_init(void); |
672 | #endif /* MACH_ASSERT */ |
673 | |
674 | extern struct turnstile *ipc_port_get_inheritor( |
675 | ipc_port_t port); |
676 | |
677 | #define ipc_port_alloc_kernel() \ |
678 | ipc_port_alloc_special(ipc_space_kernel) |
679 | #define ipc_port_dealloc_kernel(port) \ |
680 | ipc_port_dealloc_special((port), ipc_space_kernel) |
681 | |
682 | #define ipc_port_alloc_reply() \ |
683 | ipc_port_alloc_special(ipc_space_reply) |
684 | #define ipc_port_dealloc_reply(port) \ |
685 | ipc_port_dealloc_special((port), ipc_space_reply) |
686 | |
687 | #endif /* MACH_KERNEL_PRIVATE */ |
688 | |
689 | #endif /* _IPC_IPC_PORT_H_ */ |
690 | |