xref: /xnu-8020.121.3/libsyscall/mach/mig_reply_port.c (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
1 /*
2  * Copyright (c) 2010 Apple 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 #include <mach/mach.h>
30 #include <mach/mach_init.h>
31 #include <sys/cdefs.h>
32 #include "tsd.h"
33 
34 __XNU_PRIVATE_EXTERN mach_port_t _task_reply_port = MACH_PORT_NULL;
35 
36 static inline mach_port_t
_mig_get_reply_port()37 _mig_get_reply_port()
38 {
39 	return (mach_port_t)(uintptr_t)_os_tsd_get_direct(__TSD_MIG_REPLY);
40 }
41 
42 static inline void
_mig_set_reply_port(mach_port_t port)43 _mig_set_reply_port(mach_port_t port)
44 {
45 	_os_tsd_set_direct(__TSD_MIG_REPLY, (void *)(uintptr_t)port);
46 }
47 
48 /*
49  * Called by mig interface code whenever a reply port is needed.
50  * Tracing is masked during this call; otherwise, a call to printf()
51  * can result in a call to malloc() which eventually reenters
52  * mig_get_reply_port() and deadlocks.
53  */
54 mach_port_t
mig_get_reply_port(void)55 mig_get_reply_port(void)
56 {
57 	mach_port_t port = _mig_get_reply_port();
58 	if (port == MACH_PORT_NULL) {
59 		port = mach_reply_port();
60 		_mig_set_reply_port(port);
61 	}
62 	return port;
63 }
64 
65 /*
66  * Called by mig interface code after a timeout on the reply port.
67  * May also be called by user. The new mig calls with port passed in.
68  */
69 void
mig_dealloc_reply_port(mach_port_t migport)70 mig_dealloc_reply_port(mach_port_t migport)
71 {
72 	mach_port_t port = _mig_get_reply_port();
73 	if (port != MACH_PORT_NULL && port != _task_reply_port) {
74 		_mig_set_reply_port(_task_reply_port);
75 		(void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
76 		if (migport != port) {
77 			(void) mach_port_deallocate(mach_task_self(), migport);
78 		}
79 		_mig_set_reply_port(MACH_PORT_NULL);
80 	}
81 }
82 
83 /*************************************************************
84  *  Called by mig interfaces after each RPC.
85  *  Could be called by user.
86  ***********************************************************/
87 
88 void
mig_put_reply_port(mach_port_t reply_port __unused)89 mig_put_reply_port(mach_port_t reply_port __unused)
90 {
91 }
92