FreeBSD/Linux Kernel Cross Reference
sys/kern/ipc_host.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1992,1991,1990,1989,1988 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_host.c,v $
29 * Revision 2.14 93/05/15 18:55:15 mrt
30 * machparam.h -> machspl.h
31 *
32 * Revision 2.13 93/01/14 17:34:21 danner
33 * Added function prototypes. Combined ipc_processor_init and
34 * ipc_processor_enable. Removed ipc_processor_disable and
35 * ipc_processor_terminate; processor ports are never removed.
36 * Fixed lock ordering bugs in processor and processor_set code.
37 * [92/11/17 dbg]
38 * Added function prototypes. Combined ipc_processor_init and
39 * ipc_processor_enable. Removed ipc_processor_disable and
40 * ipc_processor_terminate; processor ports are never removed.
41 * Fixed lock ordering bugs in processor and processor_set code.
42 * [92/11/17 dbg]
43 *
44 * Revision 2.12 92/08/03 17:37:13 jfriedl
45 * removed silly prototypes
46 * [92/08/02 jfriedl]
47 *
48 * Revision 2.11 92/05/21 17:13:39 jfriedl
49 * tried prototypes.
50 * [92/05/20 jfriedl]
51 *
52 * Revision 2.10 91/08/03 18:18:50 jsb
53 * Removed NORMA hooks.
54 * [91/07/17 23:05:10 jsb]
55 *
56 * Revision 2.9 91/06/25 10:28:20 rpd
57 * Changed the convert_foo_to_bar functions
58 * to use ipc_port_t instead of mach_port_t.
59 * [91/05/27 rpd]
60 *
61 * Revision 2.8 91/06/17 15:46:59 jsb
62 * Renamed NORMA conditionals.
63 * [91/06/17 10:49:34 jsb]
64 *
65 * Revision 2.7 91/06/06 17:06:59 jsb
66 * Redid host port initialization under NORMA_IPC.
67 * [91/05/13 17:37:21 jsb]
68 *
69 * Revision 2.6 91/05/14 16:41:36 mrt
70 * Correcting copyright
71 *
72 * Revision 2.5 91/02/05 17:26:24 mrt
73 * Changed to new Mach copyright
74 * [91/02/01 16:12:32 mrt]
75 *
76 * Revision 2.4 90/09/09 14:32:08 rpd
77 * Don't take out extra references in ipc_pset_init.
78 * [90/08/30 rpd]
79 *
80 * Revision 2.3 90/06/19 22:58:46 rpd
81 * Changed convert_port_to_pset_name to allow
82 * both IKOT_PSET and IKOT_PSET_NAME ports.
83 * Changed convert_port_to_host to allow
84 * both IKOT_HOST and IKOT_HOST_PRIV ports.
85 * [90/06/18 rpd]
86 *
87 * Fixed bug in convert_processor_to_port.
88 * [90/06/16 rpd]
89 *
90 * Revision 2.2 90/06/02 14:53:59 rpd
91 * Created for new IPC.
92 * [90/03/26 23:46:28 rpd]
93 *
94 * Move includes.
95 * [89/08/02 dlb]
96 * Remove interrupt protection from pset locks.
97 * [89/06/14 dlb]
98 * Use port_alloc instead of xxx_port_allocate.
99 * [89/02/21 dlb]
100 * Reformat includes.
101 * [89/01/26 dlb]
102 *
103 * Break processor_set_default into two pieces.
104 * [88/12/21 dlb]
105 *
106 * Move host_self, host_priv_self to ipc_ptraps.c
107 * Rewrite processor_set_default to return both ports
108 * [88/11/30 dlb]
109 *
110 * Created.
111 * [88/10/29 dlb]
112 *
113 * Revision 2.4 89/12/22 15:52:20 rpd
114 * Take out extra reference on new processor set ports in
115 * ipc_pset_init for reply message; these ports are now
116 * returned untranslated. Assume caller of ipc_pset_disable
117 * has pset locked as well as referenced.
118 * [89/12/15 dlb]
119 *
120 * Revision 2.3 89/10/15 02:04:29 rpd
121 * Minor cleanups.
122 *
123 * Revision 2.2 89/10/11 14:07:11 dlb
124 * Fix includes.
125 * Remove interrupt protection from pset locks.
126 *
127 */
128
129 /*
130 * kern/ipc_host.c
131 *
132 * Routines to implement host ports.
133 */
134
135 #include <mach/message.h>
136 #include <kern/host.h>
137 #include <kern/processor.h>
138 #include <kern/task.h>
139 #include <kern/thread.h>
140 #include <kern/ipc_host.h>
141 #include <kern/ipc_kobject.h>
142 #include <ipc/ipc_port.h>
143 #include <ipc/ipc_space.h>
144
145 #include <machine/machspl.h> /* for spl */
146
147
148
149 /*
150 * ipc_host_init: set up various things.
151 */
152
153 void ipc_host_init(void)
154 {
155 ipc_port_t port;
156 /*
157 * Allocate and set up the two host ports.
158 */
159 port = ipc_port_alloc_kernel();
160 if (port == IP_NULL)
161 panic("ipc_host_init");
162
163 ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST);
164 realhost.host_self = port;
165
166 port = ipc_port_alloc_kernel();
167 if (port == IP_NULL)
168 panic("ipc_host_init");
169
170 ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST_PRIV);
171 realhost.host_priv_self = port;
172
173 /*
174 * Set up ipc for default processor set.
175 */
176 ipc_pset_init(&default_pset);
177 ipc_pset_enable(&default_pset);
178
179 /*
180 * And for master processor
181 */
182 ipc_processor_init(master_processor);
183 }
184
185 /*
186 * Routine: mach_host_self [mach trap]
187 * Purpose:
188 * Give the caller send rights for his own host port.
189 * Conditions:
190 * Nothing locked.
191 * Returns:
192 * MACH_PORT_NULL if there are any resource failures
193 * or other errors.
194 */
195
196 mach_port_t
197 mach_host_self(void)
198 {
199 ipc_port_t sright;
200
201 sright = ipc_port_make_send(realhost.host_self);
202 return ipc_port_copyout_send(sright, current_space());
203 }
204
205 #if MACH_IPC_COMPAT
206
207 /*
208 * Routine: host_self [mach trap]
209 * Purpose:
210 * Give the caller send rights for his own host port.
211 * If new, the send right is marked with IE_BITS_COMPAT.
212 * Conditions:
213 * Nothing locked.
214 * Returns:
215 * MACH_PORT_NULL if there are any resource failures
216 * or other errors.
217 */
218
219 port_name_t
220 host_self(void)
221 {
222 ipc_port_t sright;
223
224 sright = ipc_port_make_send(realhost.host_self);
225 return (port_name_t)
226 ipc_port_copyout_send_compat(sright, current_space());
227 }
228
229 #endif MACH_IPC_COMPAT
230
231 /*
232 * ipc_processor_init:
233 *
234 * Initialize ipc access to processor by allocating port.
235 * Enable ipc control of processor by setting port object.
236 */
237
238 void
239 ipc_processor_init(
240 processor_t processor)
241 {
242 ipc_port_t port;
243
244 port = ipc_port_alloc_kernel();
245 if (port == IP_NULL)
246 panic("ipc_processor_init");
247 processor->processor_self = port;
248 ipc_kobject_set(port, (ipc_kobject_t) processor, IKOT_PROCESSOR);
249 }
250
251
252 /*
253 * ipc_pset_init:
254 *
255 * Initialize ipc control of a processor set by allocating its ports.
256 */
257
258 void
259 ipc_pset_init(
260 processor_set_t pset)
261 {
262 ipc_port_t port;
263
264 port = ipc_port_alloc_kernel();
265 if (port == IP_NULL)
266 panic("ipc_pset_init");
267 pset->pset_self = port;
268
269 port = ipc_port_alloc_kernel();
270 if (port == IP_NULL)
271 panic("ipc_pset_init");
272 pset->pset_name_self = port;
273 }
274
275 /*
276 * ipc_pset_enable:
277 *
278 * Enable ipc access to a processor set.
279 */
280 void
281 ipc_pset_enable(
282 processor_set_t pset)
283 {
284 pset_lock(pset);
285 if (pset->active) {
286 ipc_kobject_set(pset->pset_self,
287 (ipc_kobject_t) pset, IKOT_PSET);
288 ipc_kobject_set(pset->pset_name_self,
289 (ipc_kobject_t) pset, IKOT_PSET_NAME);
290 pset_ref_lock(pset);
291 pset->ref_count += 2;
292 pset_ref_unlock(pset);
293 }
294 pset_unlock(pset);
295 }
296
297 /*
298 * ipc_pset_disable:
299 *
300 * Disable ipc access to a processor set by clearing the port objects.
301 * Caller must hold pset lock and a reference to the pset. Ok to
302 * just decrement pset reference count as a result.
303 */
304 void
305 ipc_pset_disable(
306 processor_set_t pset)
307 {
308 ipc_kobject_set(pset->pset_self, IKO_NULL, IKOT_NONE);
309 ipc_kobject_set(pset->pset_name_self, IKO_NULL, IKOT_NONE);
310
311 pset_ref_lock(pset);
312 pset->ref_count -= 2;
313 pset_ref_unlock(pset);
314 }
315
316 /*
317 * ipc_pset_terminate:
318 *
319 * Processor set is dead. Deallocate the ipc control structures.
320 */
321 void
322 ipc_pset_terminate(
323 processor_set_t pset)
324 {
325 ipc_port_dealloc_kernel(pset->pset_self);
326 ipc_port_dealloc_kernel(pset->pset_name_self);
327 }
328
329 /*
330 * processor_set_default, processor_set_default_priv:
331 *
332 * Return ports for manipulating default_processor set. MiG code
333 * differentiates between these two routines.
334 */
335 kern_return_t
336 processor_set_default(
337 host_t host,
338 processor_set_t *pset)
339 {
340 if (host == HOST_NULL)
341 return KERN_INVALID_ARGUMENT;
342
343 *pset = &default_pset;
344 pset_reference(*pset);
345 return KERN_SUCCESS;
346 }
347
348 kern_return_t
349 xxx_processor_set_default_priv(
350 host_t host,
351 processor_set_t *pset)
352 {
353 if (host == HOST_NULL)
354 return KERN_INVALID_ARGUMENT;
355
356 *pset = &default_pset;
357 pset_reference(*pset);
358 return KERN_SUCCESS;
359 }
360
361 /*
362 * Routine: convert_port_to_host
363 * Purpose:
364 * Convert from a port to a host.
365 * Doesn't consume the port ref; the host produced may be null.
366 * Conditions:
367 * Nothing locked.
368 */
369
370 host_t
371 convert_port_to_host(ipc_port_t port)
372 {
373 host_t host = HOST_NULL;
374
375 if (IP_VALID(port)) {
376 ip_lock(port);
377 if (ip_active(port) &&
378 ((ip_kotype(port) == IKOT_HOST) ||
379 (ip_kotype(port) == IKOT_HOST_PRIV)))
380 host = (host_t) port->ip_kobject;
381 ip_unlock(port);
382 }
383
384 return host;
385 }
386
387 /*
388 * Routine: convert_port_to_host_priv
389 * Purpose:
390 * Convert from a port to a host.
391 * Doesn't consume the port ref; the host produced may be null.
392 * Conditions:
393 * Nothing locked.
394 */
395
396 host_t
397 convert_port_to_host_priv(ipc_port_t port)
398 {
399 host_t host = HOST_NULL;
400
401 if (IP_VALID(port)) {
402 ip_lock(port);
403 if (ip_active(port) &&
404 (ip_kotype(port) == IKOT_HOST_PRIV))
405 host = (host_t) port->ip_kobject;
406 ip_unlock(port);
407 }
408
409 return host;
410 }
411
412 /*
413 * Routine: convert_port_to_processor
414 * Purpose:
415 * Convert from a port to a processor.
416 * Doesn't consume the port ref;
417 * the processor produced may be null.
418 * Conditions:
419 * Nothing locked.
420 */
421
422 processor_t
423 convert_port_to_processor(ipc_port_t port)
424 {
425 processor_t processor = PROCESSOR_NULL;
426
427 if (IP_VALID(port)) {
428 ip_lock(port);
429 if (ip_active(port) &&
430 (ip_kotype(port) == IKOT_PROCESSOR))
431 processor = (processor_t) port->ip_kobject;
432 ip_unlock(port);
433 }
434
435 return processor;
436 }
437
438 /*
439 * Routine: convert_port_to_pset
440 * Purpose:
441 * Convert from a port to a pset.
442 * Doesn't consume the port ref; produces a pset ref,
443 * which may be null.
444 * Conditions:
445 * Nothing locked.
446 */
447
448 processor_set_t
449 convert_port_to_pset(ipc_port_t port)
450 {
451 processor_set_t pset = PROCESSOR_SET_NULL;
452
453 if (IP_VALID(port)) {
454 ip_lock(port);
455 if (ip_active(port) &&
456 (ip_kotype(port) == IKOT_PSET)) {
457 pset = (processor_set_t) port->ip_kobject;
458 pset_reference(pset);
459 }
460 ip_unlock(port);
461 }
462
463 return pset;
464 }
465
466 /*
467 * Routine: convert_port_to_pset_name
468 * Purpose:
469 * Convert from a port to a pset.
470 * Doesn't consume the port ref; produces a pset ref,
471 * which may be null.
472 * Conditions:
473 * Nothing locked.
474 */
475
476 processor_set_t
477 convert_port_to_pset_name(ipc_port_t port)
478 {
479 processor_set_t pset = PROCESSOR_SET_NULL;
480
481 if (IP_VALID(port)) {
482 ip_lock(port);
483 if (ip_active(port) &&
484 ((ip_kotype(port) == IKOT_PSET) ||
485 (ip_kotype(port) == IKOT_PSET_NAME))) {
486 pset = (processor_set_t) port->ip_kobject;
487 pset_reference(pset);
488 }
489 ip_unlock(port);
490 }
491
492 return pset;
493 }
494
495 /*
496 * Routine: convert_host_to_port
497 * Purpose:
498 * Convert from a host to a port.
499 * Produces a naked send right which is always valid.
500 * Conditions:
501 * Nothing locked.
502 */
503
504 ipc_port_t
505 convert_host_to_port(host_t host)
506 {
507 ipc_port_t port;
508
509 port = ipc_port_make_send(host->host_self);
510
511 return port;
512 }
513
514 /*
515 * Routine: convert_processor_to_port
516 * Purpose:
517 * Convert from a processor to a port.
518 * Produces a naked send right which is always valid.
519 * Conditions:
520 * Nothing locked.
521 */
522
523 ipc_port_t
524 convert_processor_to_port(processor_t processor)
525 {
526 ipc_port_t port;
527
528 port = ipc_port_make_send(processor->processor_self);
529
530 return port;
531 }
532
533 /*
534 * Routine: convert_pset_to_port
535 * Purpose:
536 * Convert from a pset to a port.
537 * Consumes a pset ref; produces a naked send right
538 * which may be invalid.
539 * Conditions:
540 * Nothing locked.
541 */
542
543 ipc_port_t
544 convert_pset_to_port(processor_set_t pset)
545 {
546 ipc_port_t port;
547
548 pset_lock(pset);
549 if (pset->active)
550 port = ipc_port_make_send(pset->pset_self);
551 else
552 port = IP_NULL;
553 pset_unlock(pset);
554
555 pset_deallocate(pset);
556 return port;
557 }
558
559 /*
560 * Routine: convert_pset_name_to_port
561 * Purpose:
562 * Convert from a pset to a port.
563 * Consumes a pset ref; produces a naked send right
564 * which may be invalid.
565 * Conditions:
566 * Nothing locked.
567 */
568
569 ipc_port_t
570 convert_pset_name_to_port(processor_set_t pset)
571 {
572 ipc_port_t port;
573
574 pset_lock(pset);
575 if (pset->active)
576 port = ipc_port_make_send(pset->pset_name_self);
577 else
578 port = IP_NULL;
579 pset_unlock(pset);
580
581 pset_deallocate(pset);
582 return port;
583 }
Cache object: f2abb07a7d055f3cf2734916551c66be
|