]> git.saurik.com Git - apple/libc.git/blob - threads/mig_support.c
Libc-583.tar.gz
[apple/libc.git] / threads / mig_support.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * Mach Operating System
25 * Copyright (c) 1989 Carnegie-Mellon University
26 * All rights reserved. The CMU software License Agreement specifies
27 * the terms and conditions for use and redistribution.
28 */
29 /*
30 * mig_support.c - by Mary Thompson
31 *
32 * Routines to set and deallocate the mig reply port for the current thread.
33 * Called from mig-generated interfaces.
34 */
35 #include <mach/mach.h>
36 #include <pthread_internals.h>
37 #include <pthread.h>
38
39 #include "cthreads.h"
40 #include "cthread_internals.h"
41
42 pthread_lock_t reply_port_lock;
43 extern mach_port_t _pthread_reply_port(pthread_t);
44 static mach_port_t _task_reply_port = MACH_PORT_NULL;
45
46 /*
47 * called in new child...
48 * clear lock to cover case where the parent had
49 * a thread holding this lock while another thread
50 * did the fork()
51 */
52 void mig_fork_child()
53 {
54 UNLOCK(reply_port_lock);
55 }
56
57 /*
58 * Called by mach_init with 0 before cthread_init is
59 * called and again with 1 at the end of cthread_init.
60 */
61 void
62 mig_init(init_done)
63 int init_done;
64 {
65 if (init_done == 0) {
66 LOCK_INIT(reply_port_lock);
67 _task_reply_port = mach_reply_port();
68 }
69 }
70
71 /*
72 * Called by mig interface code whenever a reply port is needed.
73 * Tracing is masked during this call; otherwise, a call to printf()
74 * can result in a call to malloc() which eventually reenters
75 * mig_get_reply_port() and deadlocks.
76 */
77 mach_port_t
78 mig_get_reply_port()
79 {
80 register cproc_t self;
81 pthread_t pself;
82 #ifdef CTHREADS_DEBUG
83 int d = cthread_debug;
84 #endif /* CTHREADS_DEBUG */
85
86 #ifdef CTHREADS_DEBUG
87 cthread_debug = FALSE;
88 #endif /* CTHREADS_DEBUG */
89 pself = pthread_self();
90 if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
91 if (pself->reply_port == MACH_PORT_NULL) {
92 pself->reply_port = mach_reply_port();
93 }
94 return pself->reply_port;
95 }
96 self = cproc_self();
97 if (self == NO_CPROC) {
98 #ifdef CTHREADS_DEBUG
99 cthread_debug = d;
100 #endif /* CTHREADS_DEBUG */
101 return(_task_reply_port);
102 }
103 if (self->reply_port == MACH_PORT_NULL) {
104 self->reply_port = mach_reply_port();
105 }
106 #ifdef CTHREADS_DEBUG
107 cthread_debug = d;
108 #endif /* CTHREADS_DEBUG */
109 return self->reply_port;
110 }
111
112 /*
113 * Called by mig interface code after a timeout on the reply port.
114 * May also be called by user. The new mig calls with port passed in
115 * We are ignoring this , so is osfmk cthreads code
116 */
117 void
118 mig_dealloc_reply_port(mach_port_t migport)
119 {
120 register cproc_t self;
121 pthread_t pself;
122 register mach_port_t port;
123 #ifdef CTHREADS_DEBUG
124 int d = cthread_debug;
125 #endif /* CTHREADS_DEBUG */
126
127 #ifdef CTHREADS_DEBUG
128 cthread_debug = FALSE;
129 #endif /* CTHREADS_DEBUG */
130 pself = pthread_self();
131 if ((pself != (pthread_t)NULL) && (pself->sig == _PTHREAD_SIG)) {
132 port = pself->reply_port;
133 if (port != MACH_PORT_NULL && port != _task_reply_port) {
134 LOCK(reply_port_lock);
135 pself->reply_port = _task_reply_port;
136 (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
137 pself->reply_port = MACH_PORT_NULL;
138 UNLOCK(reply_port_lock);
139 }
140 return;
141 }
142 self = cproc_self();
143 if (self == NO_CPROC) {
144 #ifdef CTHREADS_DEBUG
145 cthread_debug = d;
146 #endif /* CTHREADS_DEBUG */
147 return;
148 }
149 ASSERT(self != NO_CPROC);
150 port = self->reply_port;
151 if (port != MACH_PORT_NULL && port != _task_reply_port) {
152 LOCK(reply_port_lock);
153 self->reply_port = _task_reply_port;
154 (void) mach_port_mod_refs(mach_task_self(), port, MACH_PORT_RIGHT_RECEIVE, -1);
155 self->reply_port = MACH_PORT_NULL;
156 UNLOCK(reply_port_lock);
157 }
158 #ifdef CTHREADS_DEBUG
159 cthread_debug = d;
160 #endif /* CTHREADS_DEBUG */
161 }
162
163 /*************************************************************
164 * Called by mig interfaces after each RPC.
165 * Could be called by user.
166 ***********************************************************/
167
168 void
169 mig_put_reply_port(
170 mach_port_t reply_port)
171 {
172 }