xref: /xnu-12377.41.6/libsyscall/mach/mig_reply_port.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
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 
35 #pragma mark Utilities
36 #define _mach_assert(__op, __kr) \
37 	do { \
38 	        if (kr != KERN_SUCCESS) { \
39 	                __builtin_trap(); \
40 	        } \
41 	} while (0)
42 
43 __XNU_PRIVATE_EXTERN mach_port_t _task_reply_port = MACH_PORT_NULL;
44 
45 static inline mach_port_t
_mig_get_reply_port(void)46 _mig_get_reply_port(void)
47 {
48 	return (mach_port_t)(uintptr_t)_os_tsd_get_direct(__TSD_MIG_REPLY);
49 }
50 
51 static inline void
_mig_set_reply_port(mach_port_t port)52 _mig_set_reply_port(mach_port_t port)
53 {
54 	_os_tsd_set_direct(__TSD_MIG_REPLY, (void *)(uintptr_t)port);
55 }
56 
57 /*
58  * Called by mig interface code whenever a reply port is needed.
59  * Tracing is masked during this call; otherwise, a call to printf()
60  * can result in a call to malloc() which eventually reenters
61  * mig_get_reply_port() and deadlocks.
62  */
63 mach_port_t
mig_get_reply_port(void)64 mig_get_reply_port(void)
65 {
66 	mach_port_t port = _mig_get_reply_port();
67 	if (port == MACH_PORT_NULL) {
68 		kern_return_t kr;
69 		mach_port_options_t opts = {
70 			.flags = MPO_REPLY_PORT,
71 		};
72 
73 		kr = mach_port_construct(mach_task_self(), &opts, NULL, &port);
74 		_mach_assert("mach_port_construct for mig_get_reply_port", kr);
75 		_mig_set_reply_port(port);
76 	}
77 	return port;
78 }
79 
80 /*
81  * Called by mig interface code after a timeout on the reply port.
82  * May also be called by user. The new mig calls with port passed in.
83  */
84 void
mig_dealloc_reply_port(mach_port_t migport)85 mig_dealloc_reply_port(mach_port_t migport)
86 {
87 	mach_port_t port = _mig_get_reply_port();
88 	if (port != MACH_PORT_NULL && port != _task_reply_port) {
89 		_mig_set_reply_port(_task_reply_port);
90 		(void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
91 		if (migport != port) {
92 			(void) mach_port_deallocate(mach_task_self(), migport);
93 		}
94 		_mig_set_reply_port(MACH_PORT_NULL);
95 	}
96 }
97 
98 /*************************************************************
99  *  Called by mig interfaces after each RPC.
100  *  Could be called by user.
101  ***********************************************************/
102 
103 void
mig_put_reply_port(mach_port_t reply_port __unused)104 mig_put_reply_port(mach_port_t reply_port __unused)
105 {
106 }
107