|
|
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;
1.1.1.4 ! root 484: ipc_port_flag_protected_payload_clear(port);
1.1 root 485: ip_unlock(port);
486: break;
487: }
488:
489: case MACH_MSG_TYPE_COPY_SEND: {
490: ipc_port_t port = (ipc_port_t) object;
491:
492: ip_lock(port);
493: if (ip_active(port)) {
494: assert(port->ip_srights > 0);
495: port->ip_srights++;
496: }
497: ip_reference(port);
498: ip_unlock(port);
499: break;
500: }
501:
502: case MACH_MSG_TYPE_MAKE_SEND: {
503: ipc_port_t port = (ipc_port_t) object;
504:
505: ip_lock(port);
506: assert(ip_active(port));
507: assert(port->ip_receiver_name != MACH_PORT_NULL);
508: assert(port->ip_receiver == ipc_space_kernel);
509:
510: ip_reference(port);
511: port->ip_mscount++;
512: port->ip_srights++;
513: ip_unlock(port);
514: break;
515: }
516:
517: case MACH_MSG_TYPE_MOVE_SEND:
518: /* move naked send right into the message */
519: break;
520:
521: case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
522: ipc_port_t port = (ipc_port_t) object;
523:
524: ip_lock(port);
525: assert(ip_active(port));
526: assert(port->ip_receiver_name != MACH_PORT_NULL);
527: assert(port->ip_receiver == ipc_space_kernel);
528:
529: ip_reference(port);
530: port->ip_sorights++;
531: ip_unlock(port);
532: break;
533: }
534:
535: case MACH_MSG_TYPE_MOVE_SEND_ONCE:
536: /* move naked send-once right into the message */
537: break;
538:
539: default:
540: #if MACH_ASSERT
541: assert(!"ipc_object_copyin_from_kernel: strange rights");
542: #else
543: panic("ipc_object_copyin_from_kernel: strange rights");
544: #endif
545: }
546: }
547:
548: /*
549: * Routine: ipc_object_destroy
550: * Purpose:
551: * Destroys a naked capability.
552: * Consumes a ref for the object.
553: *
554: * A receive right should be in limbo or in transit.
555: * Conditions:
556: * Nothing locked.
557: */
558:
559: void
560: ipc_object_destroy(
561: ipc_object_t object,
562: mach_msg_type_name_t msgt_name)
563: {
564: assert(IO_VALID(object));
565: assert(io_otype(object) == IOT_PORT);
566:
567: switch (msgt_name) {
568: case MACH_MSG_TYPE_PORT_SEND:
569: ipc_port_release_send((ipc_port_t) object);
570: break;
571:
572: case MACH_MSG_TYPE_PORT_SEND_ONCE:
573: ipc_notify_send_once((ipc_port_t) object);
574: break;
575:
576: case MACH_MSG_TYPE_PORT_RECEIVE:
577: ipc_port_release_receive((ipc_port_t) object);
578: break;
579:
580: default:
581: panic("ipc_object_destroy: strange rights");
582: }
583: }
584:
585: /*
586: * Routine: ipc_object_copyout
587: * Purpose:
588: * Copyout a capability, placing it into a space.
589: * If successful, consumes a ref for the object.
590: * Conditions:
591: * Nothing locked.
592: * Returns:
593: * KERN_SUCCESS Copied out object, consumed ref.
594: * KERN_INVALID_TASK The space is dead.
595: * KERN_INVALID_CAPABILITY The object is dead.
596: * KERN_NO_SPACE No room in space for another right.
597: * KERN_RESOURCE_SHORTAGE No memory available.
598: * KERN_UREFS_OVERFLOW Urefs limit exceeded
599: * and overflow wasn't specified.
600: */
601:
602: kern_return_t
603: ipc_object_copyout(
604: ipc_space_t space,
605: ipc_object_t object,
606: mach_msg_type_name_t msgt_name,
607: boolean_t overflow,
608: mach_port_t *namep)
609: {
610: mach_port_t name;
611: ipc_entry_t entry;
612: kern_return_t kr;
613:
614: assert(IO_VALID(object));
615: assert(io_otype(object) == IOT_PORT);
616:
617: is_write_lock(space);
618:
619: for (;;) {
620: if (!space->is_active) {
621: is_write_unlock(space);
622: return KERN_INVALID_TASK;
623: }
624:
625: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
626: ipc_right_reverse(space, object, &name, &entry)) {
627: /* object is locked and active */
628:
629: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
630: break;
631: }
632:
633: kr = ipc_entry_get(space, &name, &entry);
634: if (kr != KERN_SUCCESS) {
635: /* unlocks/locks space, so must start again */
636:
637: kr = ipc_entry_grow_table(space);
638: if (kr != KERN_SUCCESS)
639: return kr; /* space is unlocked */
640:
641: continue;
642: }
643:
644: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
645: assert(entry->ie_object == IO_NULL);
646:
647: io_lock(object);
648: if (!io_active(object)) {
649: io_unlock(object);
650: ipc_entry_dealloc(space, name, entry);
651: is_write_unlock(space);
652: return KERN_INVALID_CAPABILITY;
653: }
654:
655: entry->ie_object = object;
656: break;
657: }
658:
659: /* space is write-locked and active, object is locked and active */
660:
661: kr = ipc_right_copyout(space, name, entry,
662: msgt_name, overflow, object);
663: /* object is unlocked */
664: is_write_unlock(space);
665:
666: if (kr == KERN_SUCCESS)
667: *namep = name;
668: return kr;
669: }
670:
671: #if 0
672: /* XXX same, but don't check for already-existing send rights */
673: kern_return_t
674: ipc_object_copyout_multiname(space, object, namep)
675: ipc_space_t space;
676: ipc_object_t object;
677: mach_port_t *namep;
678: {
679: mach_port_t name;
680: ipc_entry_t entry;
681: kern_return_t kr;
682:
683: assert(IO_VALID(object));
684: assert(io_otype(object) == IOT_PORT);
685:
686: is_write_lock(space);
687:
688: for (;;) {
689: if (!space->is_active) {
690: is_write_unlock(space);
691: return KERN_INVALID_TASK;
692: }
693:
694: kr = ipc_entry_get(space, &name, &entry);
695: if (kr != KERN_SUCCESS) {
696: /* unlocks/locks space, so must start again */
697:
698: kr = ipc_entry_grow_table(space);
699: if (kr != KERN_SUCCESS)
700: return kr; /* space is unlocked */
701:
702: continue;
703: }
704:
705: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
706: assert(entry->ie_object == IO_NULL);
707:
708: io_lock(object);
709: if (!io_active(object)) {
710: io_unlock(object);
711: ipc_entry_dealloc(space, name, entry);
712: is_write_unlock(space);
713: return KERN_INVALID_CAPABILITY;
714: }
715:
716: entry->ie_object = object;
717: break;
718: }
719:
720: /* space is write-locked and active, object is locked and active */
721:
722: kr = ipc_right_copyout_multiname(space, name, entry, object);
723: /* object is unlocked */
724: is_write_unlock(space);
725:
726: if (kr == KERN_SUCCESS)
727: *namep = name;
728: return kr;
729: }
1.1.1.2 root 730: #endif /* 0 */
1.1 root 731:
732: /*
733: * Routine: ipc_object_copyout_name
734: * Purpose:
735: * Copyout a capability, placing it into a space.
736: * The specified name is used for the capability.
737: * If successful, consumes a ref for the object.
738: * Conditions:
739: * Nothing locked.
740: * Returns:
741: * KERN_SUCCESS Copied out object, consumed ref.
742: * KERN_INVALID_TASK The space is dead.
743: * KERN_INVALID_CAPABILITY The object is dead.
744: * KERN_RESOURCE_SHORTAGE No memory available.
745: * KERN_UREFS_OVERFLOW Urefs limit exceeded
746: * and overflow wasn't specified.
747: * KERN_RIGHT_EXISTS Space has rights under another name.
748: * KERN_NAME_EXISTS Name is already used.
749: */
750:
751: kern_return_t
752: ipc_object_copyout_name(
753: ipc_space_t space,
754: ipc_object_t object,
755: mach_msg_type_name_t msgt_name,
756: boolean_t overflow,
757: mach_port_t name)
758: {
759: mach_port_t oname;
760: ipc_entry_t oentry;
761: ipc_entry_t entry;
762: kern_return_t kr;
763:
764: assert(IO_VALID(object));
765: assert(io_otype(object) == IOT_PORT);
766:
767: kr = ipc_entry_alloc_name(space, name, &entry);
768: if (kr != KERN_SUCCESS)
769: return kr;
770: /* space is write-locked and active */
771:
772: if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
773: ipc_right_reverse(space, object, &oname, &oentry)) {
774: /* object is locked and active */
775:
776: if (name != oname) {
777: io_unlock(object);
778:
779: if (IE_BITS_TYPE(entry->ie_bits)
780: == MACH_PORT_TYPE_NONE)
781: ipc_entry_dealloc(space, name, entry);
782:
783: is_write_unlock(space);
784: return KERN_RIGHT_EXISTS;
785: }
786:
787: assert(entry == oentry);
788: assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
789: } else {
790: if (ipc_right_inuse(space, name, entry))
791: return KERN_NAME_EXISTS;
792:
793: assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
794: assert(entry->ie_object == IO_NULL);
795:
796: io_lock(object);
797: if (!io_active(object)) {
798: io_unlock(object);
799: ipc_entry_dealloc(space, name, entry);
800: is_write_unlock(space);
801: return KERN_INVALID_CAPABILITY;
802: }
803:
804: entry->ie_object = object;
805: }
806:
807: /* space is write-locked and active, object is locked and active */
808:
809: kr = ipc_right_copyout(space, name, entry,
810: msgt_name, overflow, object);
811: /* object is unlocked */
812: is_write_unlock(space);
813: return kr;
814: }
815:
816: /*
817: * Routine: ipc_object_copyout_dest
818: * Purpose:
819: * Translates/consumes the destination right of a message.
820: * This is unlike normal copyout because the right is consumed
821: * in a funny way instead of being given to the receiving space.
822: * The receiver gets his name for the port, if he has receive
823: * rights, otherwise MACH_PORT_NULL.
824: * Conditions:
825: * The object is locked and active. Nothing else locked.
826: * The object is unlocked and loses a reference.
827: */
828:
829: void
830: ipc_object_copyout_dest(
831: ipc_space_t space,
832: ipc_object_t object,
833: mach_msg_type_name_t msgt_name,
834: mach_port_t *namep)
835: {
836: mach_port_t name;
837:
838: assert(IO_VALID(object));
839: assert(io_active(object));
840:
841: io_release(object);
842:
843: /*
844: * If the space is the receiver/owner of the object,
845: * then we quietly consume the right and return
846: * the space's name for the object. Otherwise
847: * we destroy the right and return MACH_PORT_NULL.
848: */
849:
850: switch (msgt_name) {
851: case MACH_MSG_TYPE_PORT_SEND: {
852: ipc_port_t port = (ipc_port_t) object;
853: ipc_port_t nsrequest = IP_NULL;
854: mach_port_mscount_t mscount = 0; /* '=0' to shut up lint */
855:
856: assert(port->ip_srights > 0);
857: if (--port->ip_srights == 0) {
858: nsrequest = port->ip_nsrequest;
859: if (nsrequest != IP_NULL) {
860: port->ip_nsrequest = IP_NULL;
861: mscount = port->ip_mscount;
862: }
863: }
864:
865: if (port->ip_receiver == space)
866: name = port->ip_receiver_name;
867: else
868: name = MACH_PORT_NULL;
869:
870: ip_unlock(port);
871:
872: if (nsrequest != IP_NULL)
873: ipc_notify_no_senders(nsrequest, mscount);
874:
875: break;
876: }
877:
878: case MACH_MSG_TYPE_PORT_SEND_ONCE: {
879: ipc_port_t port = (ipc_port_t) object;
880:
881: assert(port->ip_sorights > 0);
882:
883: if (port->ip_receiver == space) {
884: /* quietly consume the send-once right */
885:
886: port->ip_sorights--;
887: name = port->ip_receiver_name;
888: ip_unlock(port);
889: } else {
890: /*
891: * A very bizarre case. The message
892: * was received, but before this copyout
893: * happened the space lost receive rights.
894: * We can't quietly consume the soright
895: * out from underneath some other task,
896: * so generate a send-once notification.
897: */
898:
899: ip_reference(port); /* restore ref */
900: ip_unlock(port);
901:
902: ipc_notify_send_once(port);
903: name = MACH_PORT_NULL;
904: }
905:
906: break;
907: }
908:
909: default:
910: #if MACH_ASSERT
911: assert(!"ipc_object_copyout_dest: strange rights");
912: #else
913: panic("ipc_object_copyout_dest: strange rights");
914: #endif
915:
916: }
917:
918: *namep = name;
919: }
920:
921: /*
922: * Routine: ipc_object_rename
923: * Purpose:
924: * Rename an entry in a space.
925: * Conditions:
926: * Nothing locked.
927: * Returns:
928: * KERN_SUCCESS Renamed the entry.
929: * KERN_INVALID_TASK The space was dead.
930: * KERN_INVALID_NAME oname didn't denote an entry.
931: * KERN_NAME_EXISTS nname already denoted an entry.
932: * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
933: */
934:
935: kern_return_t
936: ipc_object_rename(
937: ipc_space_t space,
938: mach_port_t oname,
939: mach_port_t nname)
940: {
941: ipc_entry_t oentry, nentry;
942: kern_return_t kr;
943:
944: kr = ipc_entry_alloc_name(space, nname, &nentry);
945: if (kr != KERN_SUCCESS)
946: return kr;
947: /* space is write-locked and active */
948:
949: if (ipc_right_inuse(space, nname, nentry)) {
950: /* space is unlocked */
951: return KERN_NAME_EXISTS;
952: }
953:
954: /* don't let ipc_entry_lookup see the uninitialized new entry */
955:
956: if ((oname == nname) ||
957: ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
958: ipc_entry_dealloc(space, nname, nentry);
959: is_write_unlock(space);
960: return KERN_INVALID_NAME;
961: }
962:
963: kr = ipc_right_rename(space, oname, oentry, nname, nentry);
964: /* space is unlocked */
965: return kr;
966: }
967:
968: #if MACH_KDB
969: #define printf kdbprintf
970:
971: /*
972: * Routine: ipc_object_print
973: * Purpose:
974: * Pretty-print an object for kdb.
975: */
976:
977: char *ikot_print_array[IKOT_MAX_TYPE] = {
978: "(NONE) ",
979: "(THREAD) ",
980: "(TASK) ",
981: "(HOST) ",
982: "(HOST_PRIV) ",
983: "(PROCESSOR) ",
984: "(PSET) ",
985: "(PSET_NAME) ",
986: "(PAGER) ",
987: "(PAGER_REQUEST) ",
988: "(DEVICE) ", /* 10 */
989: "(XMM_OBJECT) ",
990: "(XMM_PAGER) ",
991: "(XMM_KERNEL) ",
992: "(XMM_REPLY) ",
993: "(PAGER_TERMINATING)",
994: "(PAGING_NAME) ",
995: "(HOST_SECURITY) ",
996: "(LEDGER) ",
997: "(MASTER_DEVICE) ",
998: "(ACTIVATION) ", /* 20 */
999: "(SUBSYSTEM) ",
1000: "(IO_DONE_QUEUE) ",
1001: "(SEMAPHORE) ",
1002: "(LOCK_SET) ",
1003: "(CLOCK) ",
1004: "(CLOCK_CTRL) ", /* 26 */
1005: /* << new entries here */
1006: "(UNKNOWN) " /* magic catchall */
1007: }; /* Please keep in sync with kern/ipc_kobject.h */
1008:
1009: void
1010: ipc_object_print(
1.1.1.4 ! root 1011: const ipc_object_t object)
1.1 root 1012: {
1013: int kotype;
1014:
1015: iprintf("%s", io_active(object) ? "active" : "dead");
1016: printf(", refs=%d", object->io_references);
1017: printf(", otype=%d", io_otype(object));
1018: kotype = io_kotype(object);
1019: if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
1020: printf(", kotype=%d %s\n", io_kotype(object),
1021: ikot_print_array[kotype]);
1022: else
1023: printf(", kotype=0x%x %s\n", io_kotype(object),
1024: ikot_print_array[IKOT_UNKNOWN]);
1025: }
1026:
1027: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.