FreeBSD/Linux Kernel Cross Reference
sys/norma/ipc_clean.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: ipc_clean.c,v $
29 * Revision 2.2 92/03/10 16:27:19 jsb
30 * Merged in norma branch changes as of NORMA_MK7.
31 * [92/03/09 12:48:39 jsb]
32 *
33 * Revision 2.1.2.3 92/02/21 11:24:11 jsb
34 * Moved ipc_kmsg_uncopyout_to_network here from ipc/ipc_kmsg.c.
35 * Separated norma_ipc_uncopyout_all_kmsgs out from
36 * norma_ipc_dead_destination (renamed from norma_ipc_destroy_proxy).
37 * [92/02/21 10:38:49 jsb]
38 *
39 * Eliminated norma_ipc_unsend_*_dest, since norma_ipc_send_*_dest
40 * is no longer called until and unless message is successfully
41 * received. Added check to ensure that destroyed proxy has queued
42 * messages. Added call to norma_port_remove before call to
43 * ipc_port_destroy. Removed zeroing of ip_seqno.
44 * [92/02/18 08:44:28 jsb]
45 *
46 * Revision 2.1.2.2 92/01/21 21:51:00 jsb
47 * De-linted.
48 * [92/01/16 21:31:56 jsb]
49 *
50 * Revision 2.1.2.1 92/01/03 08:57:08 jsb
51 * First NORMA branch checkin.
52 *
53 * Revision 2.1.1.3 91/12/31 21:36:40 jsb
54 * Changed ndproxy macros to nsproxy.
55 *
56 * Revision 2.1.1.2 91/12/31 12:11:04 jsb
57 * Changed remote_port handling in norma_ipc_destroy_proxy to account
58 * for remote consumption of send-once right (if any) in first kmsg.
59 * Added ipc_kmsg_uncopyout_to_network, which is given remote_port which
60 * it in turn hands to norma_ipc_unsend{_migrating,}_dest, which now
61 * use this port instead of trying to look it up based on uid.
62 * Changes for IP_NORMA_REQUEST macros being renamed to ip_ndproxy{,m,p}.
63 *
64 * Revision 2.1.1.1 91/12/29 21:42:51 jsb
65 * First checkin.
66 *
67 */
68 /*
69 * File: norma/ipc_clean.c
70 * Author: Joseph S. Barrera III
71 * Date: 1991
72 *
73 * Routines to clean messages sent to the network.
74 */
75
76 #include <ipc/ipc_port.h>
77 #include <ipc/ipc_kmsg.h>
78
79 extern ipc_port_t norma_port_lookup();
80 extern ipc_port_t norma_ipc_receive_soright();
81 extern ipc_port_t norma_ipc_receive_sright();
82
83 extern ipc_port_t norma_ipc_unsend_port();
84 extern ipc_port_t norma_ipc_unsend_soright();
85 extern ipc_port_t norma_ipc_unsend_sright();
86 extern ipc_port_t norma_ipc_unsend_rright();
87 extern void norma_ipc_unsend_dest();
88 extern void norma_ipc_unsend_migrating_dest();
89
90 /*
91 * These unsend routines should undo the effects of the send routines above.
92 */
93
94 ipc_port_t
95 norma_ipc_unsend_port(uid, type_name)
96 unsigned long uid;
97 mach_msg_type_name_t type_name;
98 {
99 if (type_name == MACH_MSG_TYPE_PORT_SEND_ONCE) {
100 return norma_ipc_unsend_soright(uid);
101 } else if (type_name == MACH_MSG_TYPE_PORT_SEND) {
102 return norma_ipc_unsend_sright(uid);
103 } else if (type_name == MACH_MSG_TYPE_PORT_RECEIVE) {
104 return norma_ipc_unsend_rright(uid);
105 } else {
106 panic("norma_ipc_unsend_port: bad type %d\n", type_name);
107 /* NOTREACHED */
108 }
109 }
110
111 ipc_port_t
112 norma_ipc_unsend_soright(uid)
113 unsigned long uid;
114 {
115 return norma_ipc_receive_soright(uid);
116 }
117
118 ipc_port_t
119 norma_ipc_unsend_sright(uid)
120 unsigned long uid;
121 {
122 return norma_ipc_receive_sright(uid);
123 }
124
125 ipc_port_t
126 norma_ipc_unsend_rright(uid)
127 unsigned long uid;
128 {
129 ipc_port_t port;
130
131 port = norma_port_lookup(uid);
132 if (port == IP_NULL) {
133 return IP_NULL;
134 }
135 if (! ip_active(port)) {
136 return IP_DEAD;
137 }
138 assert(! port->ip_norma_is_proxy);
139 ip_reference(port);
140 return port;
141 }
142
143 void
144 ipc_kmsg_uncopyout_header_to_network(msgh, dest)
145 mach_msg_header_t *msgh;
146 ipc_port_t dest;
147 {
148 /*
149 * Uncopy local port
150 */
151 if (msgh->msgh_local_port) {
152 register mach_msg_type_name_t type;
153
154 type = MACH_MSGH_BITS_LOCAL(msgh->msgh_bits);
155 type = ipc_object_copyin_type(type);
156 msgh->msgh_local_port = (mach_port_t)
157 norma_ipc_unsend_port((unsigned long)msgh->msgh_local_port,
158 type);
159 }
160
161 /*
162 * Uncopy remote port
163 */
164 assert(msgh->msgh_remote_port == (mach_port_t) dest->ip_norma_uid);
165 msgh->msgh_remote_port = (mach_port_t) dest;
166 }
167
168 void
169 ipc_kmsg_uncopyout_to_network(kmsg)
170 ipc_kmsg_t kmsg;
171 {
172 vm_offset_t saddr, eaddr;
173
174 if ((kmsg->ikm_header.msgh_bits & MACH_MSGH_BITS_COMPLEX) == 0) {
175 return;
176 }
177
178 kmsg->ikm_header.msgh_bits &= ~ (MACH_MSGH_BITS_COMPLEX_DATA |
179 MACH_MSGH_BITS_COMPLEX_PORTS |
180 MACH_MSGH_BITS_MIGRATED);
181
182 saddr = (vm_offset_t) (&kmsg->ikm_header + 1);
183 eaddr = (vm_offset_t) &kmsg->ikm_header + kmsg->ikm_header.msgh_size;
184
185 while (saddr < eaddr) {
186 mach_msg_type_long_t *type;
187 mach_msg_type_name_t name;
188 mach_msg_type_size_t size;
189 mach_msg_type_number_t number;
190 boolean_t is_inline, longform, is_port;
191 vm_offset_t data;
192 vm_size_t length;
193
194 type = (mach_msg_type_long_t *) saddr;
195 is_inline = type->msgtl_header.msgt_inline;
196 longform = type->msgtl_header.msgt_longform;
197 /* type->msgtl_header.msgt_deallocate not used */
198 if (longform) {
199 name = type->msgtl_name;
200 size = type->msgtl_size;
201 number = type->msgtl_number;
202 saddr += sizeof(mach_msg_type_long_t);
203 } else {
204 name = type->msgtl_header.msgt_name;
205 size = type->msgtl_header.msgt_size;
206 number = type->msgtl_header.msgt_number;
207 saddr += sizeof(mach_msg_type_t);
208 }
209
210 /* calculate length of data in bytes, rounding up */
211
212 length = ((number * size) + 7) >> 3;
213
214 is_port = MACH_MSG_TYPE_PORT_ANY(name);
215
216 if (is_inline) {
217 /* inline data sizes round up to int boundaries */
218
219 data = saddr;
220 saddr += (length + 3) &~ 3;
221 } else if (is_port) {
222 /*
223 * Not a copy object, just a kernel address.
224 */
225 data = * (vm_offset_t *) saddr;
226 saddr += sizeof(vm_offset_t);
227 } else {
228 /*
229 * This is a copy object.
230 * It is okay to leave copy objects in page-list form.
231 * The netipc module is responsible for leaving them
232 * in a sane state.
233 */
234 saddr += sizeof(vm_offset_t);
235 }
236
237 if (is_port) {
238 ipc_port_t *ports = (ipc_port_t *) data;
239 mach_msg_type_number_t i;
240
241 /*
242 * Convert uids into ports and undo refcount action.
243 */
244 for (i = 0; i < number; i++) {
245 ports[i] =
246 norma_ipc_unsend_port((unsigned long)
247 ports[i], name);
248 }
249 }
250 }
251 }
252
253 /*
254 * Convert all kmsgs queued on port from network to internal format.
255 */
256 void
257 norma_ipc_uncopyout_all_kmsgs(port)
258 ipc_port_t port;
259 {
260 register ipc_kmsg_t kmsg;
261 register ipc_kmsg_queue_t kmsgs;
262
263 kmsgs = &port->ip_messages.imq_messages;
264 kmsg = ipc_kmsg_queue_first(kmsgs);
265 if (kmsg != IKM_NULL) do {
266 printf1("uncopyout ksmg=0x%x msgh_id=%d; was s=%d so=%d\n",
267 kmsg, kmsg->ikm_header.msgh_id,
268 port->ip_srights, port->ip_sorights);
269
270 /*
271 * Uncopy header
272 */
273 ipc_kmsg_uncopyout_header_to_network(&kmsg->ikm_header, port);
274
275 /*
276 * Uncopy body
277 */
278 ipc_kmsg_uncopyout_to_network(kmsg);
279
280 /*
281 * Move to next kmsg
282 */
283 kmsg = kmsg->ikm_next;
284 } while (kmsg != ipc_kmsg_queue_first(kmsgs));
285 }
286
287 /*
288 * Called when a send to a remote port returns a notification that
289 * the port is dead.
290 */
291 norma_ipc_dead_destination(port)
292 ipc_port_t port;
293 {
294 ipc_kmsg_t kmsg;
295 mach_port_rights_t sorights;
296
297 printf1("norma_ipc_dead_destination: 0x%x:%x refs %d\n",
298 port, port->ip_norma_uid, port->ip_references);
299
300 assert(port->ip_norma_is_proxy);
301 assert(port->ip_references > 0);
302
303 /*
304 * Convert all kmsgs from network to internal format.
305 * XXX
306 * We need to lock to prevent anyone else from
307 * queueing ports from this point.
308 */
309 norma_ipc_uncopyout_all_kmsgs(port);
310
311 /*
312 * The remote kernel counts us as having consumed one send-once
313 * right, if our destination right was a send-once right.
314 * This reduces how often we need to call norma_ipc_yield_rights.
315 */
316 kmsg = ipc_kmsg_queue_first(&port->ip_messages.imq_messages);
317 assert(kmsg != IKM_NULL);
318 if (MACH_MSGH_BITS_REMOTE(kmsg->ikm_header.msgh_bits) ==
319 MACH_MSG_TYPE_PORT_SEND_ONCE) {
320 sorights = port->ip_sorights - 1;
321 } else {
322 sorights = port->ip_sorights;
323 }
324
325 printf1("*** That's really s=%d so=%d\n", port->ip_srights, sorights);
326
327 if (port->ip_srights > 0 || sorights > 0) {
328 printf("dead_destination(0x%x) s=%d so=%d st=%d (leak)\n",
329 port,
330 port->ip_srights,
331 port->ip_sorights,
332 - port->ip_norma_stransit);
333 #if 0
334 /* XXX */
335 norma_ipc_yield_rights(0, -port->ip_stransit, sorights);
336 #endif
337 }
338
339 /*
340 * Remove port from proxy list before destroying it.
341 */
342 norma_port_remove(port);
343
344 /*
345 * Fiddle with fields to make ipc_port_destroy happy, then call it.
346 */
347 assert(ip_nsproxyp(port->ip_nsrequest));
348 port->ip_nsrequest = IP_NULL;
349 printf1("dead_destination: 0x%x:%x: about to destroy port\n",
350 port, port->ip_norma_uid);
351 ipc_port_destroy(port);
352 printf1("dead_destination: 0x%x:%x: destroyed port\n",
353 port, port->ip_norma_uid);
354 }
Cache object: 5ecdd7b603bf68ed05199e79cd88b056
|