|
|
1.1.1.2 root 1: /*
1.1 root 2: * Mach Operating System
3: * Copyright (c) 1991,1990,1989 Carnegie Mellon University
4: * All Rights Reserved.
1.1.1.2 root 5: *
1.1 root 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.
1.1.1.2 root 11: *
1.1 root 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.
1.1.1.2 root 15: *
1.1 root 16: * Carnegie Mellon requests users of this software to return to
1.1.1.2 root 17: *
1.1 root 18: * Software Distribution Coordinator or [email protected]
19: * School of Computer Science
20: * Carnegie Mellon University
21: * Pittsburgh PA 15213-3890
1.1.1.2 root 22: *
1.1 root 23: * any improvements or extensions that they make and grant Carnegie Mellon
24: * the rights to redistribute these changes.
25: */
26: /*
27: * File: ipc/ipc_object.c
28: * Author: Rich Draves
29: * Date: 1989
30: *
31: * Functions to manipulate IPC objects.
32: */
33:
1.1.1.3 ! root 34: #include <string.h>
1.1 root 35:
36: #include <mach/boolean.h>
37: #include <mach/kern_return.h>
38: #include <mach/port.h>
39: #include <mach/message.h>
40: #include <ipc/port.h>
41: #include <ipc/ipc_space.h>
42: #include <ipc/ipc_entry.h>
43: #include <ipc/ipc_object.h>
44: #include <ipc/ipc_hash.h>
45: #include <ipc/ipc_right.h>
46: #include <ipc/ipc_notify.h>
47: #include <ipc/ipc_pset.h>
1.1.1.3 ! root 48: #include <kern/debug.h>
! 49: #include <kern/printf.h>
! 50: #include <kern/slab.h>
1.1 root 51:
1.1.1.3 ! root 52: #if MACH_KDB
! 53: #include <ddb/db_output.h>
! 54: #endif /* MACH_KDB */
! 55:
! 56:
! 57: struct kmem_cache ipc_object_caches[IOT_NUMBER];
1.1 root 58:
59:
60:
61: /*
62: * Routine: ipc_object_reference
63: * Purpose:
64: * Take a reference to an object.
65: */
66:
67: void
68: ipc_object_reference(
69: ipc_object_t object)
70: {
71: io_lock(object);
72: assert(object->io_references > 0);
73: io_reference(object);
74: io_unlock(object);
75: }
76:
77: /*
78: * Routine: ipc_object_release
79: * Purpose:
80: * Release a reference to an object.
81: */
82:
83: void
84: ipc_object_release(
85: ipc_object_t object)
86: {
87: io_lock(object);
88: assert(object->io_references > 0);
89: io_release(object);
90: io_check_unlock(object);
91: }
92:
93: /*
94: * Routine: ipc_object_translate
95: * Purpose:
96: * Look up an object in a space.
97: * Conditions:
98: * Nothing locked before. If successful, the object
99: * is returned locked. The caller doesn't get a ref.
100: * Returns:
101: * KERN_SUCCESS Objected returned locked.
102: * KERN_INVALID_TASK The space is dead.
103: * KERN_INVALID_NAME The name doesn't denote a right.
104: * KERN_INVALID_RIGHT Name doesn't denote the correct right.
105: */
106:
107: kern_return_t
108: ipc_object_translate(
109: ipc_space_t space,
110: mach_port_t name,
111: mach_port_right_t right,
112: ipc_object_t *objectp)
113: {
114: ipc_entry_t entry;
115: ipc_object_t object;
116: kern_return_t kr;
117:
118: kr = ipc_right_lookup_read(space, name, &entry);
119: if (kr != KERN_SUCCESS)
120: return kr;
121: /* space is read-locked and active */
122:
123: if ((entry->ie_bits & MACH_PORT_TYPE(right)) == (mach_port_right_t) 0) {
124: is_read_unlock(space);
125: return KERN_INVALID_RIGHT;
126: }
127:
128: object = entry->ie_object;
129: assert(object != IO_NULL);
130:
131: io_lock(object);
132: is_read_unlock(space);
133:
134: *objectp = object;
135: return KERN_SUCCESS;
136: }
137:
138: /*
139: * Routine: ipc_object_alloc_dead
140: * Purpose:
141: * Allocate a dead-name entry.
142: * Conditions:
143: * Nothing locked.
144: * Returns:
145: * KERN_SUCCESS The dead name is allocated.
146: * KERN_INVALID_TASK The space is dead.
147: * KERN_NO_SPACE No room for an entry in the space.
148: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
149: */
150:
151: kern_return_t
152: ipc_object_alloc_dead(
153: ipc_space_t space,
154: mach_port_t *namep)
155: {
156: ipc_entry_t entry;
157: kern_return_t kr;
158:
159:
160: kr = ipc_entry_alloc(space, namep, &entry);
161: if (kr != KERN_SUCCESS)
162: return kr;
163: /* space is write-locked */
164:
165: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
166:
167: assert(entry->ie_object == IO_NULL);
168: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
169:
170: is_write_unlock(space);
171: return KERN_SUCCESS;
172: }
173:
174: /*
175: * Routine: ipc_object_alloc_dead_name
176: * Purpose:
177: * Allocate a dead-name entry, with a specific name.
178: * Conditions:
179: * Nothing locked.
180: * Returns:
181: * KERN_SUCCESS The dead name is allocated.
182: * KERN_INVALID_TASK The space is dead.
183: * KERN_NAME_EXISTS The name already denotes a right.
184: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
185: */
186:
187: kern_return_t
188: ipc_object_alloc_dead_name(
189: ipc_space_t space,
190: mach_port_t name)
191: {
192: ipc_entry_t entry;
193: kern_return_t kr;
194:
195:
196: kr = ipc_entry_alloc_name(space, name, &entry);
197: if (kr != KERN_SUCCESS)
198: return kr;
199: /* space is write-locked */
200:
201: if (ipc_right_inuse(space, name, entry))
202: return KERN_NAME_EXISTS;
203:
204: /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
205:
206: assert(entry->ie_object == IO_NULL);
207: entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
208:
209: is_write_unlock(space);
210: return KERN_SUCCESS;
211: }
212:
213: /*
214: * Routine: ipc_object_alloc
215: * Purpose:
216: * Allocate an object.
217: * Conditions:
218: * Nothing locked. If successful, the object is returned locked.
219: * The caller doesn't get a reference for the object.
220: * Returns:
221: * KERN_SUCCESS The object is allocated.
222: * KERN_INVALID_TASK The space is dead.
223: * KERN_NO_SPACE No room for an entry in the space.
224: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
225: */
226:
227: kern_return_t
228: ipc_object_alloc(
229: ipc_space_t space,
230: ipc_object_type_t otype,
231: mach_port_type_t type,
232: mach_port_urefs_t urefs,
233: mach_port_t *namep,
234: ipc_object_t *objectp)
235: {
236: ipc_object_t object;
237: ipc_entry_t entry;
238: kern_return_t kr;
239:
240: assert(otype < IOT_NUMBER);
241: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
242: assert(type != MACH_PORT_TYPE_NONE);
243: assert(urefs <= MACH_PORT_UREFS_MAX);
244:
245: object = io_alloc(otype);
246: if (object == IO_NULL)
247: return KERN_RESOURCE_SHORTAGE;
248:
249: if (otype == IOT_PORT) {
250: ipc_port_t port = (ipc_port_t)object;
251:
1.1.1.3 ! root 252: memset(port, 0, sizeof(*port));
1.1 root 253: } else if (otype == IOT_PORT_SET) {
254: ipc_pset_t pset = (ipc_pset_t)object;
255:
1.1.1.3 ! root 256: memset(pset, 0, sizeof(*pset));
1.1 root 257: }
258: kr = ipc_entry_alloc(space, namep, &entry);
259: if (kr != KERN_SUCCESS) {
260: io_free(otype, object);
261: return kr;
262: }
263: /* space is write-locked */
264:
265: entry->ie_bits |= type | urefs;
266: entry->ie_object = object;
267:
268: io_lock_init(object);
269: io_lock(object);
270: is_write_unlock(space);
271:
272: object->io_references = 1; /* for entry, not caller */
273: object->io_bits = io_makebits(TRUE, otype, 0);
274:
275: *objectp = object;
276: return KERN_SUCCESS;
277: }
278:
279: /*
280: * Routine: ipc_object_alloc_name
281: * Purpose:
282: * Allocate an object, with a specific name.
283: * Conditions:
284: * Nothing locked. If successful, the object is returned locked.
285: * The caller doesn't get a reference for the object.
286: * Returns:
287: * KERN_SUCCESS The object is allocated.
288: * KERN_INVALID_TASK The space is dead.
289: * KERN_NAME_EXISTS The name already denotes a right.
290: * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
291: */
292:
293: kern_return_t
294: ipc_object_alloc_name(
295: ipc_space_t space,
296: ipc_object_type_t otype,
297: mach_port_type_t type,
298: mach_port_urefs_t urefs,
299: mach_port_t name,
300: ipc_object_t *objectp)
301: {
302: ipc_object_t object;
303: ipc_entry_t entry;
304: kern_return_t kr;
305:
306: assert(otype < IOT_NUMBER);
307: assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
308: assert(type != MACH_PORT_TYPE_NONE);
309: assert(urefs <= MACH_PORT_UREFS_MAX);
310:
311: object = io_alloc(otype);
312: if (object == IO_NULL)
313: return KERN_RESOURCE_SHORTAGE;
314:
315: if (otype == IOT_PORT) {
316: ipc_port_t port = (ipc_port_t)object;
317:
1.1.1.3 ! root 318: memset(port, 0, sizeof(*port));
1.1 root 319: } else if (otype == IOT_PORT_SET) {
320: ipc_pset_t pset = (ipc_pset_t)object;
321:
1.1.1.3 ! root 322: memset(pset, 0, sizeof(*pset));
1.1 root 323: }
324:
325: kr = ipc_entry_alloc_name(space, name, &entry);
326: if (kr != KERN_SUCCESS) {
327: io_free(otype, object);
328: return kr;
329: }
330: /* space is write-locked */
331:
332: if (ipc_right_inuse(space, name, entry)) {
333: io_free(otype, object);
334: return KERN_NAME_EXISTS;
335: }
336:
337: entry->ie_bits |= type | urefs;
338: entry->ie_object = object;
339:
340: io_lock_init(object);
341: io_lock(object);
342: is_write_unlock(space);
343:
344: object->io_references = 1; /* for entry, not caller */
345: object->io_bits = io_makebits(TRUE, otype, 0);
346:
347: *objectp = object;
348: return KERN_SUCCESS;
349: }
350:
351: /*
352: * Routine: ipc_object_copyin_type
353: * Purpose:
354: * Convert a send type name to a received type name.
355: */
356:
357: mach_msg_type_name_t
358: ipc_object_copyin_type(
359: mach_msg_type_name_t msgt_name)
360: {
361: switch (msgt_name) {
362: case 0:
363: return 0;
364:
365: case MACH_MSG_TYPE_MOVE_RECEIVE:
366: return MACH_MSG_TYPE_PORT_RECEIVE;
367:
368: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
369: case MACH_MSG_TYPE_MAKE_SEND_ONCE:
370: return MACH_MSG_TYPE_PORT_SEND_ONCE;
371:
372: case MACH_MSG_TYPE_MOVE_SEND:
373: case MACH_MSG_TYPE_MAKE_SEND:
374: case MACH_MSG_TYPE_COPY_SEND:
375: return MACH_MSG_TYPE_PORT_SEND;
376:
377: default:
378: #if MACH_ASSERT
379: assert(!"ipc_object_copyin_type: strange rights");
380: #else
381: panic("ipc_object_copyin_type: strange rights");
382: #endif
383: return 0; /* in case assert/panic returns */
384: }
385: }
386:
387: /*
388: * Routine: ipc_object_copyin
389: * Purpose:
390: * Copyin a capability from a space.
391: * If successful, the caller gets a ref
392: * for the resulting object, unless it is IO_DEAD.
393: * Conditions:
394: * Nothing locked.
395: * Returns:
396: * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
397: * KERN_INVALID_TASK The space is dead.
398: * KERN_INVALID_NAME Name doesn't exist in space.
399: * KERN_INVALID_RIGHT Name doesn't denote correct right.
400: */
401:
402: kern_return_t
403: ipc_object_copyin(
404: ipc_space_t space,
405: mach_port_t name,
406: mach_msg_type_name_t msgt_name,
407: ipc_object_t *objectp)
408: {
409: ipc_entry_t entry;
410: ipc_port_t soright;
411: kern_return_t kr;
412:
413: /*
414: * Could first try a read lock when doing
415: * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
416: * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
417: */
418:
419: kr = ipc_right_lookup_write(space, name, &entry);
420: if (kr != KERN_SUCCESS)
421: return kr;
422: /* space is write-locked and active */
423:
424: kr = ipc_right_copyin(space, name, entry,
425: msgt_name, TRUE,
426: objectp, &soright);
427: if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
428: ipc_entry_dealloc(space, name, entry);
429: is_write_unlock(space);
430:
431: if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
432: ipc_notify_port_deleted(soright, name);
433:
434: return kr;
435: }
436:
437: /*
438: * Routine: ipc_object_copyin_from_kernel
439: * Purpose:
440: * Copyin a naked capability from the kernel.
441: *
442: * MACH_MSG_TYPE_MOVE_RECEIVE
443: * The receiver must be ipc_space_kernel.
444: * Consumes the naked receive right.
445: * MACH_MSG_TYPE_COPY_SEND
446: * A naked send right must be supplied.
447: * The port gains a reference, and a send right
448: * if the port is still active.
449: * MACH_MSG_TYPE_MAKE_SEND
450: * The receiver must be ipc_space_kernel.
451: * The port gains a reference and a send right.
452: * MACH_MSG_TYPE_MOVE_SEND
453: * Consumes a naked send right.
454: * MACH_MSG_TYPE_MAKE_SEND_ONCE
455: * The receiver must be ipc_space_kernel.
456: * The port gains a reference and a send-once right.
457: * MACH_MSG_TYPE_MOVE_SEND_ONCE
458: * Consumes a naked send-once right.
459: * Conditions:
460: * Nothing locked.
461: */
462:
463: void
464: ipc_object_copyin_from_kernel(
465: ipc_object_t object,
466: mach_msg_type_name_t msgt_name)
467: {
468: assert(IO_VALID(object));
469:
470: switch (msgt_name) {
471: case MACH_MSG_TYPE_MOVE_RECEIVE: {
472: ipc_port_t port = (ipc_port_t) object;
473:
474: ip_lock(port);
475: assert(ip_active(port));
476: assert(port->ip_receiver_name != MACH_PORT_NULL);
477: assert(port->ip_receiver == ipc_space_kernel);
478:
479: /* relevant part of ipc_port_clear_receiver */
480: ipc_port_set_mscount(port, 0);
481:
482: port->ip_receiver_name = MACH_PORT_NULL;
483: port->ip_destination = IP_NULL;
484: ip_unlock(port);
485: break;
486: }
487:
488: case MACH_MSG_TYPE_COPY_SEND: {
489: ipc_port_t port = (ipc_port_t) object;
490:
491: ip_lock(port);
492: if (ip_active(port)) {
493: assert(port->ip_srights > 0);
494: port->ip_srights++;
495: }
496: ip_reference(port);
497: ip_unlock(port);
498: break;
499: }
500:
501: case MACH_MSG_TYPE_MAKE_SEND: {
502: ipc_port_t port = (ipc_port_t) object;
503:
504: ip_lock(port);
505: assert(ip_active(port));
506: assert(port->ip_receiver_name != MACH_PORT_NULL);
507: assert(port->ip_receiver == ipc_space_kernel);
508:
509: ip_reference(port);
510: port->ip_mscount++;
511: port->ip_srights++;
512: ip_unlock(port);
513: break;
514: }
515:
516: case MACH_MSG_TYPE_MOVE_SEND:
517: /* move naked send right into the message */
518: break;
519:
520: case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
521: ipc_port_t port = (ipc_port_t) object;
522:
523: ip_lock(port);
524: assert(ip_active(port));
525: assert(port->ip_receiver_name != MACH_PORT_NULL);
526: assert(port->ip_receiver == ipc_space_kernel);
527:
528: ip_reference(port);
529: port->ip_sorights++;
530: ip_unlock(port);
531: break;
532: }
533:
534: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
535: /* move naked send-once right into the message */
536: break;
537:
538: default:
539: #if MACH_ASSERT
540: assert(!"ipc_object_copyin_from_kernel: strange rights");
541: #else
542: panic("ipc_object_copyin_from_kernel: strange rights");
543: #endif
544: }
545: }
546:
547: /*
548: * Routine: ipc_object_destroy
549: * Purpose:
550: * Destroys a naked capability.
551: * Consumes a ref for the object.
552: *
553: * A receive right should be in limbo or in transit.
554: * Conditions:
555: * Nothing locked.
556: */
557:
558: void
559: ipc_object_destroy(
560: ipc_object_t object,
561: mach_msg_type_name_t msgt_name)
562: {
563: assert(IO_VALID(object));
564: assert(io_otype(object) == IOT_PORT);
565:
566: switch (msgt_name) {
567: case MACH_MSG_TYPE_PORT_SEND:
568: ipc_port_release_send((ipc_port_t) object);
569: break;
570:
571: case MACH_MSG_TYPE_PORT_SEND_ONCE:
572: ipc_notify_send_once((ipc_port_t) object);
573: break;
574:
575: case MACH_MSG_TYPE_PORT_RECEIVE:
576: ipc_port_release_receive((ipc_port_t) object);
577: break;
578:
579: default:
580: panic("ipc_object_destroy: strange rights");
581: }
582: }
583:
584: /*
585: * Routine: ipc_object_copyout
586: * Purpose:
587: * Copyout a capability, placing it into a space.
588: * If successful, consumes a ref for the object.
589: * Conditions:
590: * Nothing locked.
591: * Returns:
592: * KERN_SUCCESS Copied out object, consumed ref.
593: * KERN_INVALID_TASK The space is dead.
594: * KERN_INVALID_CAPABILITY The object is dead.
595: * KERN_NO_SPACE No room in space for another right.
596: * KERN_RESOURCE_SHORTAGE No memory available.
597: * KERN_UREFS_OVERFLOW Urefs limit exceeded
598: * and overflow wasn't specified.
599: */
600:
601: kern_return_t
602: ipc_object_copyout(
603: ipc_space_t space,
604: ipc_object_t object,
605: mach_msg_type_name_t msgt_name,
606: boolean_t overflow,
607: mach_port_t *namep)
608: {
609: mach_port_t name;
610: ipc_entry_t entry;
611: kern_return_t kr;
612:
613: assert(IO_VALID(object));
614: assert(io_otype(object) == IOT_PORT);
615:
616: is_write_lock(space);
617:
618: for (;;) {
619: if (!space->is_active) {
620: is_write_unlock(space);
621: return KERN_INVALID_TASK;
622: }
623:
624: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
625: ipc_right_reverse(space, object, &name, &entry)) {
626: /* object is locked and active */
627:
628: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
629: break;
630: }
631:
632: kr = ipc_entry_get(space, &name, &entry);
633: if (kr != KERN_SUCCESS) {
634: /* unlocks/locks space, so must start again */
635:
636: kr = ipc_entry_grow_table(space);
637: if (kr != KERN_SUCCESS)
638: return kr; /* space is unlocked */
639:
640: continue;
641: }
642:
643: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
644: assert(entry->ie_object == IO_NULL);
645:
646: io_lock(object);
647: if (!io_active(object)) {
648: io_unlock(object);
649: ipc_entry_dealloc(space, name, entry);
650: is_write_unlock(space);
651: return KERN_INVALID_CAPABILITY;
652: }
653:
654: entry->ie_object = object;
655: break;
656: }
657:
658: /* space is write-locked and active, object is locked and active */
659:
660: kr = ipc_right_copyout(space, name, entry,
661: msgt_name, overflow, object);
662: /* object is unlocked */
663: is_write_unlock(space);
664:
665: if (kr == KERN_SUCCESS)
666: *namep = name;
667: return kr;
668: }
669:
670: #if 0
671: /* XXX same, but don't check for already-existing send rights */
672: kern_return_t
673: ipc_object_copyout_multiname(space, object, namep)
674: ipc_space_t space;
675: ipc_object_t object;
676: mach_port_t *namep;
677: {
678: mach_port_t name;
679: ipc_entry_t entry;
680: kern_return_t kr;
681:
682: assert(IO_VALID(object));
683: assert(io_otype(object) == IOT_PORT);
684:
685: is_write_lock(space);
686:
687: for (;;) {
688: if (!space->is_active) {
689: is_write_unlock(space);
690: return KERN_INVALID_TASK;
691: }
692:
693: kr = ipc_entry_get(space, &name, &entry);
694: if (kr != KERN_SUCCESS) {
695: /* unlocks/locks space, so must start again */
696:
697: kr = ipc_entry_grow_table(space);
698: if (kr != KERN_SUCCESS)
699: return kr; /* space is unlocked */
700:
701: continue;
702: }
703:
704: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
705: assert(entry->ie_object == IO_NULL);
706:
707: io_lock(object);
708: if (!io_active(object)) {
709: io_unlock(object);
710: ipc_entry_dealloc(space, name, entry);
711: is_write_unlock(space);
712: return KERN_INVALID_CAPABILITY;
713: }
714:
715: entry->ie_object = object;
716: break;
717: }
718:
719: /* space is write-locked and active, object is locked and active */
720:
721: kr = ipc_right_copyout_multiname(space, name, entry, object);
722: /* object is unlocked */
723: is_write_unlock(space);
724:
725: if (kr == KERN_SUCCESS)
726: *namep = name;
727: return kr;
728: }
1.1.1.2 root 729: #endif /* 0 */
1.1 root 730:
731: /*
732: * Routine: ipc_object_copyout_name
733: * Purpose:
734: * Copyout a capability, placing it into a space.
735: * The specified name is used for the capability.
736: * If successful, consumes a ref for the object.
737: * Conditions:
738: * Nothing locked.
739: * Returns:
740: * KERN_SUCCESS Copied out object, consumed ref.
741: * KERN_INVALID_TASK The space is dead.
742: * KERN_INVALID_CAPABILITY The object is dead.
743: * KERN_RESOURCE_SHORTAGE No memory available.
744: * KERN_UREFS_OVERFLOW Urefs limit exceeded
745: * and overflow wasn't specified.
746: * KERN_RIGHT_EXISTS Space has rights under another name.
747: * KERN_NAME_EXISTS Name is already used.
748: */
749:
750: kern_return_t
751: ipc_object_copyout_name(
752: ipc_space_t space,
753: ipc_object_t object,
754: mach_msg_type_name_t msgt_name,
755: boolean_t overflow,
756: mach_port_t name)
757: {
758: mach_port_t oname;
759: ipc_entry_t oentry;
760: ipc_entry_t entry;
761: kern_return_t kr;
762:
763: assert(IO_VALID(object));
764: assert(io_otype(object) == IOT_PORT);
765:
766: kr = ipc_entry_alloc_name(space, name, &entry);
767: if (kr != KERN_SUCCESS)
768: return kr;
769: /* space is write-locked and active */
770:
771: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
772: ipc_right_reverse(space, object, &oname, &oentry)) {
773: /* object is locked and active */
774:
775: if (name != oname) {
776: io_unlock(object);
777:
778: if (IE_BITS_TYPE(entry->ie_bits)
779: == MACH_PORT_TYPE_NONE)
780: ipc_entry_dealloc(space, name, entry);
781:
782: is_write_unlock(space);
783: return KERN_RIGHT_EXISTS;
784: }
785:
786: assert(entry == oentry);
787: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
788: } else {
789: if (ipc_right_inuse(space, name, entry))
790: return KERN_NAME_EXISTS;
791:
792: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
793: assert(entry->ie_object == IO_NULL);
794:
795: io_lock(object);
796: if (!io_active(object)) {
797: io_unlock(object);
798: ipc_entry_dealloc(space, name, entry);
799: is_write_unlock(space);
800: return KERN_INVALID_CAPABILITY;
801: }
802:
803: entry->ie_object = object;
804: }
805:
806: /* space is write-locked and active, object is locked and active */
807:
808: kr = ipc_right_copyout(space, name, entry,
809: msgt_name, overflow, object);
810: /* object is unlocked */
811: is_write_unlock(space);
812: return kr;
813: }
814:
815: /*
816: * Routine: ipc_object_copyout_dest
817: * Purpose:
818: * Translates/consumes the destination right of a message.
819: * This is unlike normal copyout because the right is consumed
820: * in a funny way instead of being given to the receiving space.
821: * The receiver gets his name for the port, if he has receive
822: * rights, otherwise MACH_PORT_NULL.
823: * Conditions:
824: * The object is locked and active. Nothing else locked.
825: * The object is unlocked and loses a reference.
826: */
827:
828: void
829: ipc_object_copyout_dest(
830: ipc_space_t space,
831: ipc_object_t object,
832: mach_msg_type_name_t msgt_name,
833: mach_port_t *namep)
834: {
835: mach_port_t name;
836:
837: assert(IO_VALID(object));
838: assert(io_active(object));
839:
840: io_release(object);
841:
842: /*
843: * If the space is the receiver/owner of the object,
844: * then we quietly consume the right and return
845: * the space's name for the object. Otherwise
846: * we destroy the right and return MACH_PORT_NULL.
847: */
848:
849: switch (msgt_name) {
850: case MACH_MSG_TYPE_PORT_SEND: {
851: ipc_port_t port = (ipc_port_t) object;
852: ipc_port_t nsrequest = IP_NULL;
853: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
854:
855: assert(port->ip_srights > 0);
856: if (--port->ip_srights == 0) {
857: nsrequest = port->ip_nsrequest;
858: if (nsrequest != IP_NULL) {
859: port->ip_nsrequest = IP_NULL;
860: mscount = port->ip_mscount;
861: }
862: }
863:
864: if (port->ip_receiver == space)
865: name = port->ip_receiver_name;
866: else
867: name = MACH_PORT_NULL;
868:
869: ip_unlock(port);
870:
871: if (nsrequest != IP_NULL)
872: ipc_notify_no_senders(nsrequest, mscount);
873:
874: break;
875: }
876:
877: case MACH_MSG_TYPE_PORT_SEND_ONCE: {
878: ipc_port_t port = (ipc_port_t) object;
879:
880: assert(port->ip_sorights > 0);
881:
882: if (port->ip_receiver == space) {
883: /* quietly consume the send-once right */
884:
885: port->ip_sorights--;
886: name = port->ip_receiver_name;
887: ip_unlock(port);
888: } else {
889: /*
890: * A very bizarre case. The message
891: * was received, but before this copyout
892: * happened the space lost receive rights.
893: * We can't quietly consume the soright
894: * out from underneath some other task,
895: * so generate a send-once notification.
896: */
897:
898: ip_reference(port); /* restore ref */
899: ip_unlock(port);
900:
901: ipc_notify_send_once(port);
902: name = MACH_PORT_NULL;
903: }
904:
905: break;
906: }
907:
908: default:
909: #if MACH_ASSERT
910: assert(!"ipc_object_copyout_dest: strange rights");
911: #else
912: panic("ipc_object_copyout_dest: strange rights");
913: #endif
914:
915: }
916:
917: *namep = name;
918: }
919:
920: /*
921: * Routine: ipc_object_rename
922: * Purpose:
923: * Rename an entry in a space.
924: * Conditions:
925: * Nothing locked.
926: * Returns:
927: * KERN_SUCCESS Renamed the entry.
928: * KERN_INVALID_TASK The space was dead.
929: * KERN_INVALID_NAME oname didn't denote an entry.
930: * KERN_NAME_EXISTS nname already denoted an entry.
931: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
932: */
933:
934: kern_return_t
935: ipc_object_rename(
936: ipc_space_t space,
937: mach_port_t oname,
938: mach_port_t nname)
939: {
940: ipc_entry_t oentry, nentry;
941: kern_return_t kr;
942:
943: kr = ipc_entry_alloc_name(space, nname, &nentry);
944: if (kr != KERN_SUCCESS)
945: return kr;
946: /* space is write-locked and active */
947:
948: if (ipc_right_inuse(space, nname, nentry)) {
949: /* space is unlocked */
950: return KERN_NAME_EXISTS;
951: }
952:
953: /* don't let ipc_entry_lookup see the uninitialized new entry */
954:
955: if ((oname == nname) ||
956: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
957: ipc_entry_dealloc(space, nname, nentry);
958: is_write_unlock(space);
959: return KERN_INVALID_NAME;
960: }
961:
962: kr = ipc_right_rename(space, oname, oentry, nname, nentry);
963: /* space is unlocked */
964: return kr;
965: }
966:
967: #if MACH_KDB
968: #define printf kdbprintf
969:
970: /*
971: * Routine: ipc_object_print
972: * Purpose:
973: * Pretty-print an object for kdb.
974: */
975:
976: char *ikot_print_array[IKOT_MAX_TYPE] = {
977: "(NONE) ",
978: "(THREAD) ",
979: "(TASK) ",
980: "(HOST) ",
981: "(HOST_PRIV) ",
982: "(PROCESSOR) ",
983: "(PSET) ",
984: "(PSET_NAME) ",
985: "(PAGER) ",
986: "(PAGER_REQUEST) ",
987: "(DEVICE) ", /* 10 */
988: "(XMM_OBJECT) ",
989: "(XMM_PAGER) ",
990: "(XMM_KERNEL) ",
991: "(XMM_REPLY) ",
992: "(PAGER_TERMINATING)",
993: "(PAGING_NAME) ",
994: "(HOST_SECURITY) ",
995: "(LEDGER) ",
996: "(MASTER_DEVICE) ",
997: "(ACTIVATION) ", /* 20 */
998: "(SUBSYSTEM) ",
999: "(IO_DONE_QUEUE) ",
1000: "(SEMAPHORE) ",
1001: "(LOCK_SET) ",
1002: "(CLOCK) ",
1003: "(CLOCK_CTRL) ", /* 26 */
1004: /* << new entries here */
1005: "(UNKNOWN) " /* magic catchall */
1006: }; /* Please keep in sync with kern/ipc_kobject.h */
1007:
1008: void
1009: ipc_object_print(
1010: ipc_object_t object)
1011: {
1012: int kotype;
1013:
1014: iprintf("%s", io_active(object) ? "active" : "dead");
1015: printf(", refs=%d", object->io_references);
1016: printf(", otype=%d", io_otype(object));
1017: kotype = io_kotype(object);
1018: if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
1019: printf(", kotype=%d %s\n", io_kotype(object),
1020: ikot_print_array[kotype]);
1021: else
1022: printf(", kotype=0x%x %s\n", io_kotype(object),
1023: ikot_print_array[IKOT_UNKNOWN]);
1024: }
1025:
1026: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.