2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * @OSF_FREE_COPYRIGHT@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 * File: ipc/ipc_right.c
57 * Functions to manipulate IPC capabilities.
60 #include <mach/boolean.h>
61 #include <mach/kern_return.h>
62 #include <mach/port.h>
63 #include <mach/message.h>
64 #include <kern/assert.h>
65 #include <kern/misc_protos.h>
66 #include <kern/ipc_subsystem.h>
68 #include <ipc/ipc_entry.h>
69 #include <ipc/ipc_space.h>
70 #include <ipc/ipc_object.h>
71 #include <ipc/ipc_hash.h>
72 #include <ipc/ipc_port.h>
73 #include <ipc/ipc_pset.h>
74 #include <ipc/ipc_right.h>
75 #include <ipc/ipc_notify.h>
76 #include <ipc/ipc_table.h>
79 * Routine: ipc_right_lookup_write
81 * Finds an entry in a space, given the name.
83 * Nothing locked. If successful, the space is write-locked.
85 * KERN_SUCCESS Found an entry.
86 * KERN_INVALID_TASK The space is dead.
87 * KERN_INVALID_NAME Name doesn't exist in space.
91 ipc_right_lookup_write(
93 mach_port_name_t name
,
98 assert(space
!= IS_NULL
);
100 is_write_lock(space
);
102 if (!space
->is_active
) {
103 is_write_unlock(space
);
104 return KERN_INVALID_TASK
;
107 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
108 is_write_unlock(space
);
109 return KERN_INVALID_NAME
;
117 * Routine: ipc_right_lookup_two_write
119 * Like ipc_right_lookup except that it returns two
120 * entries for two different names that were looked
121 * up under the same space lock.
123 * Nothing locked. If successful, the space is write-locked.
125 * KERN_INVALID_TASK The space is dead.
126 * KERN_INVALID_NAME Name doesn't exist in space.
130 ipc_right_lookup_two_write(
132 mach_port_name_t name1
,
133 ipc_entry_t
*entryp1
,
134 mach_port_name_t name2
,
135 ipc_entry_t
*entryp2
)
140 assert(space
!= IS_NULL
);
142 is_write_lock(space
);
144 if (!space
->is_active
) {
145 is_write_unlock(space
);
146 return KERN_INVALID_TASK
;
149 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
150 is_write_unlock(space
);
151 return KERN_INVALID_NAME
;
153 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
154 is_write_unlock(space
);
155 return KERN_INVALID_NAME
;
163 * Routine: ipc_right_reverse
165 * Translate (space, object) -> (name, entry).
166 * Only finds send/receive rights.
167 * Returns TRUE if an entry is found; if so,
168 * the object is locked and active.
170 * The space must be locked (read or write) and active.
171 * Nothing else locked.
178 mach_port_name_t
*namep
,
182 mach_port_name_t name
;
185 /* would switch on io_otype to handle multiple types of object */
187 assert(space
->is_active
);
188 assert(io_otype(object
) == IOT_PORT
);
190 port
= (ipc_port_t
) object
;
193 if (!ip_active(port
)) {
199 if (port
->ip_receiver
== space
) {
200 name
= port
->ip_receiver_name
;
201 assert(name
!= MACH_PORT_NULL
);
203 entry
= ipc_entry_lookup(space
, name
);
205 assert(entry
!= IE_NULL
);
206 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
207 assert(port
== (ipc_port_t
) entry
->ie_object
);
214 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
215 assert((entry
= *entryp
) != IE_NULL
);
216 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
217 assert(port
== (ipc_port_t
) entry
->ie_object
);
227 * Routine: ipc_right_dnrequest
229 * Make a dead-name request, returning the previously
230 * registered send-once right. If notify is IP_NULL,
231 * just cancels the previously registered request.
233 * This interacts with the IE_BITS_COMPAT, because they
234 * both use ie_request. If this is a compat entry, then
235 * previous always gets IP_NULL. If notify is IP_NULL,
236 * then the entry remains a compat entry. Otherwise
237 * the real dead-name request is registered and the entry
238 * is no longer a compat entry.
240 * Nothing locked. May allocate memory.
241 * Only consumes/returns refs if successful.
243 * KERN_SUCCESS Made/canceled dead-name request.
244 * KERN_INVALID_TASK The space is dead.
245 * KERN_INVALID_NAME Name doesn't exist in space.
246 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
247 * KERN_INVALID_ARGUMENT Name denotes dead name, but
248 * immediate is FALSE or notify is IP_NULL.
249 * KERN_UREFS_OVERFLOW Name denotes dead name, but
250 * generating immediate notif. would overflow urefs.
251 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
257 mach_port_name_t name
,
260 ipc_port_t
*previousp
)
266 ipc_entry_bits_t bits
;
269 kr
= ipc_right_lookup_write(space
, name
, &entry
);
270 if (kr
!= KERN_SUCCESS
)
272 /* space is write-locked and active */
273 bits
= entry
->ie_bits
;
274 if (bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
276 ipc_port_request_index_t request
;
278 port
= (ipc_port_t
) entry
->ie_object
;
279 assert(port
!= IP_NULL
);
281 if (!ipc_right_check(space
, port
, name
, entry
)) {
282 /* port is locked and active */
284 if (notify
== IP_NULL
) {
285 previous
= ipc_right_dncancel_macro(
286 space
, port
, name
, entry
);
289 is_write_unlock(space
);
294 * If a registered soright exists,
295 * want to atomically switch with it.
296 * If ipc_port_dncancel finds us a
297 * soright, then the following
298 * ipc_port_dnrequest will reuse
299 * that slot, so we are guaranteed
300 * not to unlock and retry.
303 previous
= ipc_right_dncancel_macro(space
,
306 kr
= ipc_port_dnrequest(port
, name
, notify
,
308 if (kr
!= KERN_SUCCESS
) {
309 assert(previous
== IP_NULL
);
310 is_write_unlock(space
);
312 kr
= ipc_port_dngrow(port
,
314 /* port is unlocked */
315 if (kr
!= KERN_SUCCESS
)
321 assert(request
!= 0);
324 entry
->ie_request
= request
;
325 is_write_unlock(space
);
330 * Our capability bits were changed by ipc_right_check
331 * because it found an inactive port and removed our
332 * references to it (converting our entry into a dead
333 * one). Reload the bits (and obviously we can't use
334 * the port name anymore).
336 bits
= entry
->ie_bits
;
340 assert(bits
& MACH_PORT_TYPE_DEAD_NAME
);
343 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) &&
344 immediate
&& (notify
!= IP_NULL
)) {
345 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
347 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
350 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
351 is_write_unlock(space
);
352 return KERN_UREFS_OVERFLOW
;
355 (entry
->ie_bits
)++; /* increment urefs */
356 is_write_unlock(space
);
358 ipc_notify_dead_name(notify
, name
);
363 is_write_unlock(space
);
364 if (bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
365 return KERN_INVALID_ARGUMENT
;
367 return KERN_INVALID_RIGHT
;
370 *previousp
= previous
;
375 * Routine: ipc_right_dncancel
377 * Cancel a dead-name request and return the send-once right.
378 * Afterwards, entry->ie_request == 0.
380 * The space must be write-locked; the port must be locked.
381 * The port must be active; the space doesn't have to be.
388 mach_port_name_t name
,
391 ipc_port_t dnrequest
;
393 assert(ip_active(port
));
394 assert(port
== (ipc_port_t
) entry
->ie_object
);
396 dnrequest
= ipc_port_dncancel(port
, name
, entry
->ie_request
);
397 entry
->ie_request
= 0;
403 * Routine: ipc_right_inuse
405 * Check if an entry is being used.
406 * Returns TRUE if it is.
408 * The space is write-locked and active.
409 * It is unlocked if the entry is inuse.
415 mach_port_name_t name
,
418 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
419 is_write_unlock(space
);
426 * Routine: ipc_right_check
428 * Check if the port has died. If it has,
429 * clean up the entry and return TRUE.
431 * The space is write-locked; the port is not locked.
432 * If returns FALSE, the port is also locked and active.
433 * Otherwise, entry is converted to a dead name, freeing
434 * a reference to port.
441 mach_port_name_t name
,
444 ipc_entry_bits_t bits
;
446 assert(space
->is_active
);
447 assert(port
== (ipc_port_t
) entry
->ie_object
);
454 /* this was either a pure send right or a send-once right */
456 bits
= entry
->ie_bits
;
457 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
458 assert(IE_BITS_UREFS(bits
) > 0);
460 if (bits
& MACH_PORT_TYPE_SEND
) {
461 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
463 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
464 assert(IE_BITS_UREFS(bits
) == 1);
468 ipc_port_release(port
);
470 /* convert entry to dead name */
472 if ((bits
& MACH_PORT_TYPE_SEND
) && !(bits
& MACH_PORT_TYPE_RECEIVE
))
473 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
475 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
478 * If there was a notification request outstanding on this
479 * name, and since the port went dead, that notification
480 * must already be on its way up from the port layer. We
481 * don't need the index of the notification port anymore.
483 * JMM - We also add a reference to the entry since the
484 * notification only carries the name and NOT a reference
485 * (or right). This makes for pretty loose reference
486 * counting, since it is only happenstance that we
487 * detected the notification in progress like this.
488 * But most (all?) calls that try to deal with this entry
489 * will also come through here, so the reference gets added
490 * before the entry gets used eventually (I would rather it
491 * be explicit in the notification generation, though)
493 if (entry
->ie_request
!= 0) {
494 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
495 entry
->ie_request
= 0;
498 entry
->ie_bits
= bits
;
499 entry
->ie_object
= IO_NULL
;
504 * Routine: ipc_right_clean
506 * Cleans up an entry in a dead space.
507 * The entry isn't deallocated or removed
508 * from reverse hash tables.
510 * The space is dead and unlocked.
516 mach_port_name_t name
,
519 ipc_entry_bits_t bits
;
520 mach_port_type_t type
;
522 bits
= entry
->ie_bits
;
523 type
= IE_BITS_TYPE(bits
);
525 assert(!space
->is_active
);
528 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
529 * problem, because we check that the port is active. If
530 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
531 * would still work, but dead space refs would accumulate
532 * in ip_dnrequests. They would use up slots in
533 * ip_dnrequests and keep the spaces from being freed.
537 case MACH_PORT_TYPE_DEAD_NAME
:
538 assert(entry
->ie_request
== 0);
539 assert(entry
->ie_object
== IO_NULL
);
542 case MACH_PORT_TYPE_PORT_SET
: {
543 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
545 assert(entry
->ie_request
== 0);
546 assert(pset
!= IPS_NULL
);
549 assert(ips_active(pset
));
551 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
555 case MACH_PORT_TYPE_SEND
:
556 case MACH_PORT_TYPE_RECEIVE
:
557 case MACH_PORT_TYPE_SEND_RECEIVE
:
558 case MACH_PORT_TYPE_SEND_ONCE
: {
559 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
560 ipc_port_t dnrequest
;
561 ipc_port_t nsrequest
= IP_NULL
;
562 mach_port_mscount_t mscount
;
564 assert(port
!= IP_NULL
);
567 if (!ip_active(port
)) {
569 ip_check_unlock(port
);
573 dnrequest
= ipc_right_dncancel_macro(space
, port
,
576 if (type
& MACH_PORT_TYPE_SEND
) {
577 assert(port
->ip_srights
> 0);
578 if (--port
->ip_srights
== 0
580 nsrequest
= port
->ip_nsrequest
;
581 if (nsrequest
!= IP_NULL
) {
582 port
->ip_nsrequest
= IP_NULL
;
583 mscount
= port
->ip_mscount
;
588 if (type
& MACH_PORT_TYPE_RECEIVE
) {
589 assert(port
->ip_receiver_name
== name
);
590 assert(port
->ip_receiver
== space
);
592 ipc_port_clear_receiver(port
);
593 ipc_port_destroy(port
); /* consumes our ref, unlocks */
594 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
595 assert(port
->ip_sorights
> 0);
598 ipc_notify_send_once(port
); /* consumes our ref */
600 assert(port
->ip_receiver
!= space
);
603 ip_unlock(port
); /* port is active */
606 if (nsrequest
!= IP_NULL
)
607 ipc_notify_no_senders(nsrequest
, mscount
);
609 if (dnrequest
!= IP_NULL
)
610 ipc_notify_port_deleted(dnrequest
, name
);
615 panic("ipc_right_clean: strange type");
620 * Routine: ipc_right_destroy
622 * Destroys an entry in a space.
624 * The space is write-locked.
625 * The space must be active.
627 * KERN_SUCCESS The entry was destroyed.
633 mach_port_name_t name
,
636 ipc_entry_bits_t bits
;
637 mach_port_type_t type
;
639 bits
= entry
->ie_bits
;
640 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
641 type
= IE_BITS_TYPE(bits
);
643 assert(space
->is_active
);
646 case MACH_PORT_TYPE_DEAD_NAME
:
647 assert(entry
->ie_request
== 0);
648 assert(entry
->ie_object
== IO_NULL
);
650 ipc_entry_dealloc(space
, name
, entry
);
653 case MACH_PORT_TYPE_PORT_SET
: {
654 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
656 assert(entry
->ie_request
== 0);
657 assert(pset
!= IPS_NULL
);
659 entry
->ie_object
= IO_NULL
;
660 /* port sets are not sharable entries on a subspace basis */
661 /* so there is no need to check the subspace array here */
662 ipc_entry_dealloc(space
, name
, entry
);
665 assert(ips_active(pset
));
667 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
671 case MACH_PORT_TYPE_SEND
:
672 case MACH_PORT_TYPE_RECEIVE
:
673 case MACH_PORT_TYPE_SEND_RECEIVE
:
674 case MACH_PORT_TYPE_SEND_ONCE
: {
675 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
676 ipc_port_t nsrequest
= IP_NULL
;
677 mach_port_mscount_t mscount
;
678 ipc_port_t dnrequest
;
680 assert(port
!= IP_NULL
);
682 if (type
== MACH_PORT_TYPE_SEND
)
683 ipc_hash_delete(space
, (ipc_object_t
) port
,
688 if (!ip_active(port
)) {
689 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
691 ip_check_unlock(port
);
693 entry
->ie_request
= 0;
694 entry
->ie_object
= IO_NULL
;
695 ipc_entry_dealloc(space
, name
, entry
);
700 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
702 entry
->ie_object
= IO_NULL
;
703 ipc_entry_dealloc(space
, name
, entry
);
705 if (type
& MACH_PORT_TYPE_SEND
) {
706 assert(port
->ip_srights
> 0);
707 if (--port
->ip_srights
== 0) {
708 nsrequest
= port
->ip_nsrequest
;
709 if (nsrequest
!= IP_NULL
) {
710 port
->ip_nsrequest
= IP_NULL
;
711 mscount
= port
->ip_mscount
;
716 if (type
& MACH_PORT_TYPE_RECEIVE
) {
717 assert(ip_active(port
));
718 assert(port
->ip_receiver
== space
);
720 if (port
->ip_subsystem
)
721 subsystem_deallocate(
722 port
->ip_subsystem
->subsystem
);
723 ipc_port_clear_receiver(port
);
724 ipc_port_destroy(port
); /* consumes our ref, unlocks */
725 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
726 assert(port
->ip_sorights
> 0);
729 ipc_notify_send_once(port
); /* consumes our ref */
731 assert(port
->ip_receiver
!= space
);
737 if (nsrequest
!= IP_NULL
)
738 ipc_notify_no_senders(nsrequest
, mscount
);
740 if (dnrequest
!= IP_NULL
)
741 ipc_notify_port_deleted(dnrequest
, name
);
746 panic("ipc_right_destroy: strange type");
753 * Routine: ipc_right_dealloc
755 * Releases a send/send-once/dead-name user ref.
756 * Like ipc_right_delta with a delta of -1,
757 * but looks at the entry to determine the right.
759 * The space is write-locked, and is unlocked upon return.
760 * The space must be active.
762 * KERN_SUCCESS A user ref was released.
763 * KERN_INVALID_RIGHT Entry has wrong type.
769 mach_port_name_t name
,
773 ipc_entry_bits_t bits
;
774 mach_port_type_t type
;
776 bits
= entry
->ie_bits
;
777 type
= IE_BITS_TYPE(bits
);
780 assert(space
->is_active
);
783 case MACH_PORT_TYPE_DEAD_NAME
: {
786 assert(IE_BITS_UREFS(bits
) > 0);
787 assert(entry
->ie_request
== 0);
788 assert(entry
->ie_object
== IO_NULL
);
790 if (IE_BITS_UREFS(bits
) == 1) {
791 ipc_entry_dealloc(space
, name
, entry
);
794 entry
->ie_bits
= bits
-1; /* decrement urefs */
796 is_write_unlock(space
);
800 case MACH_PORT_TYPE_SEND_ONCE
: {
801 ipc_port_t port
, dnrequest
;
803 assert(IE_BITS_UREFS(bits
) == 1);
805 port
= (ipc_port_t
) entry
->ie_object
;
806 assert(port
!= IP_NULL
);
808 if (ipc_right_check(space
, port
, name
, entry
)) {
810 bits
= entry
->ie_bits
;
811 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
814 /* port is locked and active */
816 assert(port
->ip_sorights
> 0);
818 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
821 entry
->ie_object
= IO_NULL
;
822 ipc_entry_dealloc(space
, name
, entry
);
824 is_write_unlock(space
);
826 ipc_notify_send_once(port
);
828 if (dnrequest
!= IP_NULL
)
829 ipc_notify_port_deleted(dnrequest
, name
);
833 case MACH_PORT_TYPE_SEND
: {
835 ipc_port_t dnrequest
= IP_NULL
;
836 ipc_port_t nsrequest
= IP_NULL
;
837 mach_port_mscount_t mscount
;
840 assert(IE_BITS_UREFS(bits
) > 0);
842 port
= (ipc_port_t
) entry
->ie_object
;
843 assert(port
!= IP_NULL
);
845 if (ipc_right_check(space
, port
, name
, entry
)) {
846 bits
= entry
->ie_bits
;
847 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
850 /* port is locked and active */
852 assert(port
->ip_srights
> 0);
854 if (IE_BITS_UREFS(bits
) == 1) {
855 if (--port
->ip_srights
== 0) {
856 nsrequest
= port
->ip_nsrequest
;
857 if (nsrequest
!= IP_NULL
) {
858 port
->ip_nsrequest
= IP_NULL
;
859 mscount
= port
->ip_mscount
;
863 dnrequest
= ipc_right_dncancel_macro(space
, port
,
865 ipc_hash_delete(space
, (ipc_object_t
) port
,
869 entry
->ie_object
= IO_NULL
;
870 ipc_entry_dealloc(space
, name
, entry
);
873 entry
->ie_bits
= bits
-1; /* decrement urefs */
875 /* even if dropped a ref, port is active */
877 is_write_unlock(space
);
879 if (nsrequest
!= IP_NULL
)
880 ipc_notify_no_senders(nsrequest
, mscount
);
882 if (dnrequest
!= IP_NULL
)
883 ipc_notify_port_deleted(dnrequest
, name
);
887 case MACH_PORT_TYPE_SEND_RECEIVE
: {
889 ipc_port_t nsrequest
= IP_NULL
;
890 mach_port_mscount_t mscount
;
892 assert(IE_BITS_UREFS(bits
) > 0);
894 port
= (ipc_port_t
) entry
->ie_object
;
895 assert(port
!= IP_NULL
);
898 assert(ip_active(port
));
899 assert(port
->ip_receiver_name
== name
);
900 assert(port
->ip_receiver
== space
);
901 assert(port
->ip_srights
> 0);
903 if (IE_BITS_UREFS(bits
) == 1) {
904 if (--port
->ip_srights
== 0) {
905 nsrequest
= port
->ip_nsrequest
;
906 if (nsrequest
!= IP_NULL
) {
907 port
->ip_nsrequest
= IP_NULL
;
908 mscount
= port
->ip_mscount
;
912 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
913 MACH_PORT_TYPE_SEND
);
915 entry
->ie_bits
= bits
-1; /* decrement urefs */
918 is_write_unlock(space
);
920 if (nsrequest
!= IP_NULL
)
921 ipc_notify_no_senders(nsrequest
, mscount
);
926 is_write_unlock(space
);
927 return KERN_INVALID_RIGHT
;
934 * Routine: ipc_right_delta
936 * Modifies the user-reference count for a right.
937 * May deallocate the right, if the count goes to zero.
939 * The space is write-locked, and is unlocked upon return.
940 * The space must be active.
942 * KERN_SUCCESS Count was modified.
943 * KERN_INVALID_RIGHT Entry has wrong type.
944 * KERN_INVALID_VALUE Bad delta for the right.
945 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
951 mach_port_name_t name
,
953 mach_port_right_t right
,
954 mach_port_delta_t delta
)
956 ipc_entry_bits_t bits
;
958 bits
= entry
->ie_bits
;
962 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
963 * switch below. It is used to keep track of those cases (in DIPC)
964 * where we have postponed the dropping of a port reference. Since
965 * the dropping of the reference could cause the port to disappear
966 * we postpone doing so when we are holding the space lock.
969 assert(space
->is_active
);
970 assert(right
< MACH_PORT_RIGHT_NUMBER
);
972 /* Rights-specific restrictions and operations. */
975 case MACH_PORT_RIGHT_PORT_SET
: {
978 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
981 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
982 assert(IE_BITS_UREFS(bits
) == 0);
983 assert(entry
->ie_request
== 0);
991 pset
= (ipc_pset_t
) entry
->ie_object
;
992 assert(pset
!= IPS_NULL
);
996 entry
->ie_object
= IO_NULL
;
997 ipc_entry_dealloc(space
, name
, entry
);
1001 assert(ips_active(pset
));
1002 is_write_unlock(space
);
1004 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1008 case MACH_PORT_RIGHT_RECEIVE
: {
1010 ipc_port_t dnrequest
= IP_NULL
;
1012 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1021 port
= (ipc_port_t
) entry
->ie_object
;
1022 assert(port
!= IP_NULL
);
1025 * The port lock is needed for ipc_right_dncancel;
1026 * otherwise, we wouldn't have to take the lock
1027 * until just before dropping the space lock.
1031 assert(ip_active(port
));
1032 assert(port
->ip_receiver_name
== name
);
1033 assert(port
->ip_receiver
== space
);
1035 if (bits
& MACH_PORT_TYPE_SEND
) {
1036 assert(IE_BITS_TYPE(bits
) ==
1037 MACH_PORT_TYPE_SEND_RECEIVE
);
1038 assert(IE_BITS_UREFS(bits
) > 0);
1039 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1040 assert(port
->ip_srights
> 0);
1043 * The remaining send right turns into a
1044 * dead name. Notice we don't decrement
1045 * ip_srights, generate a no-senders notif,
1046 * or use ipc_right_dncancel, because the
1047 * port is destroyed "first".
1049 bits
&= ~IE_BITS_TYPE_MASK
;
1050 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1051 if (entry
->ie_request
) {
1052 entry
->ie_request
= 0;
1055 entry
->ie_bits
= bits
;
1056 entry
->ie_object
= IO_NULL
;
1058 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1059 assert(IE_BITS_UREFS(bits
) == 0);
1061 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1063 entry
->ie_object
= IO_NULL
;
1064 ipc_entry_dealloc(space
, name
, entry
);
1066 is_write_unlock(space
);
1068 ipc_port_clear_receiver(port
);
1069 ipc_port_destroy(port
); /* consumes ref, unlocks */
1071 if (dnrequest
!= IP_NULL
)
1072 ipc_notify_port_deleted(dnrequest
, name
);
1076 case MACH_PORT_RIGHT_SEND_ONCE
: {
1077 ipc_port_t port
, dnrequest
;
1079 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1082 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1083 assert(IE_BITS_UREFS(bits
) == 1);
1085 port
= (ipc_port_t
) entry
->ie_object
;
1086 assert(port
!= IP_NULL
);
1088 if (ipc_right_check(space
, port
, name
, entry
)) {
1089 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1092 /* port is locked and active */
1094 assert(port
->ip_sorights
> 0);
1096 if ((delta
> 0) || (delta
< -1)) {
1106 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1109 entry
->ie_object
= IO_NULL
;
1110 ipc_entry_dealloc(space
, name
, entry
);
1112 is_write_unlock(space
);
1114 ipc_notify_send_once(port
);
1116 if (dnrequest
!= IP_NULL
)
1117 ipc_notify_port_deleted(dnrequest
, name
);
1121 case MACH_PORT_RIGHT_DEAD_NAME
: {
1122 mach_port_urefs_t urefs
;
1124 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1127 port
= (ipc_port_t
) entry
->ie_object
;
1128 assert(port
!= IP_NULL
);
1130 if (!ipc_right_check(space
, port
, name
, entry
)) {
1131 /* port is locked and active */
1135 bits
= entry
->ie_bits
;
1136 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1139 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1140 assert(IE_BITS_UREFS(bits
) > 0);
1141 assert(entry
->ie_object
== IO_NULL
);
1142 assert(entry
->ie_request
== 0);
1144 urefs
= IE_BITS_UREFS(bits
);
1145 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1147 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1148 goto urefs_overflow
;
1150 if ((urefs
+ delta
) == 0) {
1151 ipc_entry_dealloc(space
, name
, entry
);
1154 entry
->ie_bits
= bits
+ delta
;
1156 is_write_unlock(space
);
1161 case MACH_PORT_RIGHT_SEND
: {
1162 mach_port_urefs_t urefs
;
1164 ipc_port_t dnrequest
= IP_NULL
;
1165 ipc_port_t nsrequest
= IP_NULL
;
1166 mach_port_mscount_t mscount
;
1168 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1171 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1173 port
= (ipc_port_t
) entry
->ie_object
;
1174 assert(port
!= IP_NULL
);
1176 if (ipc_right_check(space
, port
, name
, entry
)) {
1177 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1180 /* port is locked and active */
1182 assert(port
->ip_srights
> 0);
1184 urefs
= IE_BITS_UREFS(bits
);
1185 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1189 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1191 goto urefs_overflow
;
1194 if ((urefs
+ delta
) == 0) {
1195 if (--port
->ip_srights
== 0) {
1196 nsrequest
= port
->ip_nsrequest
;
1197 if (nsrequest
!= IP_NULL
) {
1198 port
->ip_nsrequest
= IP_NULL
;
1199 mscount
= port
->ip_mscount
;
1203 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1204 assert(port
->ip_receiver_name
== name
);
1205 assert(port
->ip_receiver
== space
);
1206 assert(IE_BITS_TYPE(bits
) ==
1207 MACH_PORT_TYPE_SEND_RECEIVE
);
1209 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1210 MACH_PORT_TYPE_SEND
);
1212 assert(IE_BITS_TYPE(bits
) ==
1213 MACH_PORT_TYPE_SEND
);
1215 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1217 ipc_hash_delete(space
, (ipc_object_t
) port
,
1222 entry
->ie_object
= IO_NULL
;
1223 ipc_entry_dealloc(space
, name
, entry
);
1226 entry
->ie_bits
= bits
+ delta
;
1228 /* even if dropped a ref, port is active */
1230 is_write_unlock(space
);
1232 if (nsrequest
!= IP_NULL
)
1233 ipc_notify_no_senders(nsrequest
, mscount
);
1235 if (dnrequest
!= IP_NULL
)
1236 ipc_notify_port_deleted(dnrequest
, name
);
1241 panic("ipc_right_delta: strange right");
1244 return KERN_SUCCESS
;
1247 is_write_unlock(space
);
1248 return KERN_SUCCESS
;
1251 is_write_unlock(space
);
1252 return KERN_INVALID_RIGHT
;
1255 is_write_unlock(space
);
1256 return KERN_INVALID_VALUE
;
1259 is_write_unlock(space
);
1260 return KERN_UREFS_OVERFLOW
;
1264 * Routine: ipc_right_info
1266 * Retrieves information about the right.
1268 * The space is write-locked, and is unlocked upon return
1269 * if the call is unsuccessful. The space must be active.
1271 * KERN_SUCCESS Retrieved info; space still locked.
1277 mach_port_name_t name
,
1279 mach_port_type_t
*typep
,
1280 mach_port_urefs_t
*urefsp
)
1282 ipc_entry_bits_t bits
;
1283 mach_port_type_t type
;
1284 ipc_port_request_index_t request
;
1286 bits
= entry
->ie_bits
;
1288 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1289 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1291 if (ipc_right_check(space
, port
, name
, entry
)) {
1292 bits
= entry
->ie_bits
;
1293 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1298 type
= IE_BITS_TYPE(bits
);
1299 request
= entry
->ie_request
;
1302 type
|= MACH_PORT_TYPE_DNREQUEST
;
1305 *urefsp
= IE_BITS_UREFS(bits
);
1306 return KERN_SUCCESS
;
1310 * Routine: ipc_right_copyin_check
1312 * Check if a subsequent ipc_right_copyin would succeed.
1314 * The space is locked (read or write) and active.
1318 ipc_right_copyin_check(
1320 mach_port_name_t name
,
1322 mach_msg_type_name_t msgt_name
)
1324 ipc_entry_bits_t bits
;
1326 bits
= entry
->ie_bits
;
1327 assert(space
->is_active
);
1329 switch (msgt_name
) {
1330 case MACH_MSG_TYPE_MAKE_SEND
:
1331 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1332 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1333 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1338 case MACH_MSG_TYPE_COPY_SEND
:
1339 case MACH_MSG_TYPE_MOVE_SEND
:
1340 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1344 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1347 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1350 port
= (ipc_port_t
) entry
->ie_object
;
1351 assert(port
!= IP_NULL
);
1354 active
= ip_active(port
);
1361 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1362 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1365 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1373 panic("ipc_right_copyin_check: strange rights");
1380 * Routine: ipc_right_copyin
1382 * Copyin a capability from a space.
1383 * If successful, the caller gets a ref
1384 * for the resulting object, unless it is IO_DEAD,
1385 * and possibly a send-once right which should
1386 * be used in a port-deleted notification.
1388 * If deadok is not TRUE, the copyin operation
1389 * will fail instead of producing IO_DEAD.
1391 * The entry is never deallocated (except
1392 * when KERN_INVALID_NAME), so the caller
1393 * should deallocate the entry if its type
1394 * is MACH_PORT_TYPE_NONE.
1396 * The space is write-locked and active.
1398 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1399 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1405 mach_port_name_t name
,
1407 mach_msg_type_name_t msgt_name
,
1409 ipc_object_t
*objectp
,
1410 ipc_port_t
*sorightp
)
1412 ipc_entry_bits_t bits
;
1414 bits
= entry
->ie_bits
;
1416 assert(space
->is_active
);
1418 switch (msgt_name
) {
1419 case MACH_MSG_TYPE_MAKE_SEND
: {
1422 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1425 port
= (ipc_port_t
) entry
->ie_object
;
1426 assert(port
!= IP_NULL
);
1429 assert(ip_active(port
));
1430 assert(port
->ip_receiver_name
== name
);
1431 assert(port
->ip_receiver
== space
);
1438 *objectp
= (ipc_object_t
) port
;
1439 *sorightp
= IP_NULL
;
1443 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1446 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1449 port
= (ipc_port_t
) entry
->ie_object
;
1450 assert(port
!= IP_NULL
);
1453 assert(ip_active(port
));
1454 assert(port
->ip_receiver_name
== name
);
1455 assert(port
->ip_receiver
== space
);
1457 port
->ip_sorights
++;
1461 *objectp
= (ipc_object_t
) port
;
1462 *sorightp
= IP_NULL
;
1466 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1468 ipc_port_t dnrequest
= IP_NULL
;
1470 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1473 port
= (ipc_port_t
) entry
->ie_object
;
1474 assert(port
!= IP_NULL
);
1477 assert(ip_active(port
));
1478 assert(port
->ip_receiver_name
== name
);
1479 assert(port
->ip_receiver
== space
);
1481 if (bits
& MACH_PORT_TYPE_SEND
) {
1482 assert(IE_BITS_TYPE(bits
) ==
1483 MACH_PORT_TYPE_SEND_RECEIVE
);
1484 assert(IE_BITS_UREFS(bits
) > 0);
1485 assert(port
->ip_srights
> 0);
1487 ipc_hash_insert(space
, (ipc_object_t
) port
,
1491 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1492 assert(IE_BITS_UREFS(bits
) == 0);
1494 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1496 entry
->ie_object
= IO_NULL
;
1498 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1500 ipc_port_clear_receiver(port
);
1502 port
->ip_receiver_name
= MACH_PORT_NULL
;
1503 port
->ip_destination
= IP_NULL
;
1506 *objectp
= (ipc_object_t
) port
;
1507 *sorightp
= dnrequest
;
1511 case MACH_MSG_TYPE_COPY_SEND
: {
1514 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1517 /* allow for dead send-once rights */
1519 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1522 assert(IE_BITS_UREFS(bits
) > 0);
1524 port
= (ipc_port_t
) entry
->ie_object
;
1525 assert(port
!= IP_NULL
);
1527 if (ipc_right_check(space
, port
, name
, entry
)) {
1528 bits
= entry
->ie_bits
;
1531 /* port is locked and active */
1533 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1534 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1535 assert(port
->ip_sorights
> 0);
1541 assert(port
->ip_srights
> 0);
1547 *objectp
= (ipc_object_t
) port
;
1548 *sorightp
= IP_NULL
;
1552 case MACH_MSG_TYPE_MOVE_SEND
: {
1554 ipc_port_t dnrequest
= IP_NULL
;
1556 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1559 /* allow for dead send-once rights */
1561 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1564 assert(IE_BITS_UREFS(bits
) > 0);
1566 port
= (ipc_port_t
) entry
->ie_object
;
1567 assert(port
!= IP_NULL
);
1569 if (ipc_right_check(space
, port
, name
, entry
)) {
1570 bits
= entry
->ie_bits
;
1573 /* port is locked and active */
1575 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1576 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1577 assert(port
->ip_sorights
> 0);
1583 assert(port
->ip_srights
> 0);
1585 if (IE_BITS_UREFS(bits
) == 1) {
1586 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1587 assert(port
->ip_receiver_name
== name
);
1588 assert(port
->ip_receiver
== space
);
1589 assert(IE_BITS_TYPE(bits
) ==
1590 MACH_PORT_TYPE_SEND_RECEIVE
);
1594 assert(IE_BITS_TYPE(bits
) ==
1595 MACH_PORT_TYPE_SEND
);
1597 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1599 ipc_hash_delete(space
, (ipc_object_t
) port
,
1601 entry
->ie_object
= IO_NULL
;
1603 entry
->ie_bits
= bits
&~
1604 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1608 entry
->ie_bits
= bits
-1; /* decrement urefs */
1613 *objectp
= (ipc_object_t
) port
;
1614 *sorightp
= dnrequest
;
1618 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1620 ipc_port_t dnrequest
;
1622 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1625 /* allow for dead send rights */
1627 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1630 assert(IE_BITS_UREFS(bits
) > 0);
1632 port
= (ipc_port_t
) entry
->ie_object
;
1633 assert(port
!= IP_NULL
);
1635 if (ipc_right_check(space
, port
, name
, entry
)) {
1636 bits
= entry
->ie_bits
;
1639 /* port is locked and active */
1641 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1642 assert(bits
& MACH_PORT_TYPE_SEND
);
1643 assert(port
->ip_srights
> 0);
1649 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1650 assert(IE_BITS_UREFS(bits
) == 1);
1651 assert(port
->ip_sorights
> 0);
1653 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1656 entry
->ie_object
= IO_NULL
;
1657 entry
->ie_bits
= bits
&~
1658 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
1660 *objectp
= (ipc_object_t
) port
;
1661 *sorightp
= dnrequest
;
1667 return KERN_INVALID_RIGHT
;
1670 return KERN_SUCCESS
;
1673 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1674 assert(IE_BITS_UREFS(bits
) > 0);
1675 assert(entry
->ie_request
== 0);
1676 assert(entry
->ie_object
== 0);
1682 *sorightp
= IP_NULL
;
1683 return KERN_SUCCESS
;
1686 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1687 assert(IE_BITS_UREFS(bits
) > 0);
1688 assert(entry
->ie_request
== 0);
1689 assert(entry
->ie_object
== 0);
1694 if (IE_BITS_UREFS(bits
) == 1) {
1695 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
1697 entry
->ie_bits
= bits
-1; /* decrement urefs */
1700 *sorightp
= IP_NULL
;
1701 return KERN_SUCCESS
;
1706 * Routine: ipc_right_copyin_undo
1708 * Undoes the effects of an ipc_right_copyin
1709 * of a send/send-once right that is dead.
1710 * (Object is either IO_DEAD or a dead port.)
1712 * The space is write-locked and active.
1716 ipc_right_copyin_undo(
1718 mach_port_name_t name
,
1720 mach_msg_type_name_t msgt_name
,
1721 ipc_object_t object
,
1724 ipc_entry_bits_t bits
;
1726 bits
= entry
->ie_bits
;
1728 assert(space
->is_active
);
1730 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1731 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
1732 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1734 if (soright
!= IP_NULL
) {
1735 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1736 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1737 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1738 assert(object
!= IO_DEAD
);
1740 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1741 MACH_PORT_TYPE_DEAD_NAME
| 2);
1743 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
1744 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1745 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1747 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1748 MACH_PORT_TYPE_DEAD_NAME
| 1);
1749 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
1750 assert(object
== IO_DEAD
);
1751 assert(IE_BITS_UREFS(bits
) > 0);
1753 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1754 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1755 entry
->ie_bits
= bits
+1; /* increment urefs */
1758 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1759 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
1760 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1761 assert(object
!= IO_DEAD
);
1762 assert(entry
->ie_object
== object
);
1763 assert(IE_BITS_UREFS(bits
) > 0);
1765 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1766 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
1767 entry
->ie_bits
= bits
+1; /* increment urefs */
1771 * May as well convert the entry to a dead name.
1772 * (Or if it is a compat entry, destroy it.)
1775 (void) ipc_right_check(space
, (ipc_port_t
) object
,
1777 /* object is dead so it is not locked */
1780 /* release the reference acquired by copyin */
1782 if (object
!= IO_DEAD
)
1783 ipc_object_release(object
);
1787 * Routine: ipc_right_copyin_two
1789 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1790 * and deadok == FALSE, except that this moves two
1791 * send rights at once.
1793 * The space is write-locked and active.
1794 * The object is returned with two refs/send rights.
1796 * KERN_SUCCESS Acquired an object.
1797 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1801 ipc_right_copyin_two(
1803 mach_port_name_t name
,
1805 ipc_object_t
*objectp
,
1806 ipc_port_t
*sorightp
)
1808 ipc_entry_bits_t bits
;
1809 mach_port_urefs_t urefs
;
1811 ipc_port_t dnrequest
= IP_NULL
;
1813 assert(space
->is_active
);
1815 bits
= entry
->ie_bits
;
1817 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1820 urefs
= IE_BITS_UREFS(bits
);
1824 port
= (ipc_port_t
) entry
->ie_object
;
1825 assert(port
!= IP_NULL
);
1827 if (ipc_right_check(space
, port
, name
, entry
)) {
1830 /* port is locked and active */
1832 assert(port
->ip_srights
> 0);
1835 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1836 assert(port
->ip_receiver_name
== name
);
1837 assert(port
->ip_receiver
== space
);
1838 assert(IE_BITS_TYPE(bits
) ==
1839 MACH_PORT_TYPE_SEND_RECEIVE
);
1845 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1847 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1852 ipc_hash_delete(space
, (ipc_object_t
) port
,
1854 entry
->ie_object
= IO_NULL
;
1856 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1858 port
->ip_srights
+= 2;
1861 entry
->ie_bits
= bits
-2; /* decrement urefs */
1865 *objectp
= (ipc_object_t
) port
;
1866 *sorightp
= dnrequest
;
1867 return KERN_SUCCESS
;
1870 return KERN_INVALID_RIGHT
;
1874 * Routine: ipc_right_copyout
1876 * Copyout a capability to a space.
1877 * If successful, consumes a ref for the object.
1879 * Always succeeds when given a newly-allocated entry,
1880 * because user-reference overflow isn't a possibility.
1882 * If copying out the object would cause the user-reference
1883 * count in the entry to overflow, and overflow is TRUE,
1884 * then instead the user-reference count is left pegged
1885 * to its maximum value and the copyout succeeds anyway.
1887 * The space is write-locked and active.
1888 * The object is locked and active.
1889 * The object is unlocked; the space isn't.
1891 * KERN_SUCCESS Copied out capability.
1892 * KERN_UREFS_OVERFLOW User-refs would overflow;
1893 * guaranteed not to happen with a fresh entry
1894 * or if overflow=TRUE was specified.
1900 mach_port_name_t name
,
1902 mach_msg_type_name_t msgt_name
,
1904 ipc_object_t object
)
1906 ipc_entry_bits_t bits
;
1909 bits
= entry
->ie_bits
;
1911 assert(IO_VALID(object
));
1912 assert(io_otype(object
) == IOT_PORT
);
1913 assert(io_active(object
));
1914 assert(entry
->ie_object
== object
);
1916 port
= (ipc_port_t
) object
;
1918 switch (msgt_name
) {
1919 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
1921 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1922 assert(port
->ip_sorights
> 0);
1924 /* transfer send-once right and ref to entry */
1927 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
1930 case MACH_MSG_TYPE_PORT_SEND
:
1931 assert(port
->ip_srights
> 0);
1933 if (bits
& MACH_PORT_TYPE_SEND
) {
1934 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
1936 assert(port
->ip_srights
> 1);
1938 assert(urefs
< MACH_PORT_UREFS_MAX
);
1940 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
1942 /* leave urefs pegged to maximum */
1947 return KERN_SUCCESS
;
1951 return KERN_UREFS_OVERFLOW
;
1957 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1958 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1959 assert(IE_BITS_UREFS(bits
) == 0);
1961 /* transfer send right to entry */
1965 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1966 assert(IE_BITS_UREFS(bits
) == 0);
1968 /* transfer send right and ref to entry */
1971 /* entry is locked holding ref, so can use port */
1973 ipc_hash_insert(space
, (ipc_object_t
) port
,
1977 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
1980 case MACH_MSG_TYPE_PORT_RECEIVE
: {
1983 assert(port
->ip_mscount
== 0);
1984 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1985 dest
= port
->ip_destination
;
1987 port
->ip_receiver_name
= name
;
1988 port
->ip_receiver
= space
;
1990 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
1992 if (bits
& MACH_PORT_TYPE_SEND
) {
1993 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1994 assert(IE_BITS_UREFS(bits
) > 0);
1995 assert(port
->ip_srights
> 0);
2000 /* entry is locked holding ref, so can use port */
2002 ipc_hash_delete(space
, (ipc_object_t
) port
,
2005 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2006 assert(IE_BITS_UREFS(bits
) == 0);
2008 /* transfer ref to entry */
2011 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2013 if (dest
!= IP_NULL
)
2014 ipc_port_release(dest
);
2019 panic("ipc_right_copyout: strange rights");
2022 return KERN_SUCCESS
;
2026 * Routine: ipc_right_rename
2028 * Transfer an entry from one name to another.
2029 * The old entry is deallocated.
2031 * The space is write-locked and active.
2032 * The new entry is unused. Upon return,
2033 * the space is unlocked.
2035 * KERN_SUCCESS Moved entry to new name.
2041 mach_port_name_t oname
,
2043 mach_port_name_t nname
,
2046 ipc_port_request_index_t request
= oentry
->ie_request
;
2047 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2048 ipc_object_t object
= oentry
->ie_object
;
2050 assert(space
->is_active
);
2051 assert(oname
!= nname
);
2054 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2055 * if the port is dead. (This would foil ipc_port_destroy.)
2056 * Instead we should fail because oentry shouldn't exist.
2057 * Note IE_BITS_COMPAT implies ie_request != 0.
2063 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2064 port
= (ipc_port_t
) object
;
2065 assert(port
!= IP_NULL
);
2067 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2070 bits
= oentry
->ie_bits
;
2071 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2072 assert(oentry
->ie_request
== 0);
2074 /* port is locked and active */
2076 ipc_port_dnrename(port
, request
, oname
, nname
);
2078 oentry
->ie_request
= 0;
2082 /* initialize nentry before letting ipc_hash_insert see it */
2084 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2085 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2086 nentry
->ie_request
= request
;
2087 nentry
->ie_object
= object
;
2089 switch (IE_BITS_TYPE(bits
)) {
2090 case MACH_PORT_TYPE_SEND
: {
2093 port
= (ipc_port_t
) object
;
2094 assert(port
!= IP_NULL
);
2096 /* remember, there are no other share entries possible */
2097 /* or we can't do the rename. Therefore we do not need */
2098 /* to check the other subspaces */
2099 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2100 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2104 case MACH_PORT_TYPE_RECEIVE
:
2105 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2108 port
= (ipc_port_t
) object
;
2109 assert(port
!= IP_NULL
);
2112 assert(ip_active(port
));
2113 assert(port
->ip_receiver_name
== oname
);
2114 assert(port
->ip_receiver
== space
);
2116 port
->ip_receiver_name
= nname
;
2121 case MACH_PORT_TYPE_PORT_SET
: {
2124 pset
= (ipc_pset_t
) object
;
2125 assert(pset
!= IPS_NULL
);
2128 assert(ips_active(pset
));
2129 assert(pset
->ips_local_name
== oname
);
2131 pset
->ips_local_name
= nname
;
2136 case MACH_PORT_TYPE_SEND_ONCE
:
2137 case MACH_PORT_TYPE_DEAD_NAME
:
2141 panic("ipc_right_rename: strange rights");
2144 assert(oentry
->ie_request
== 0);
2145 oentry
->ie_object
= IO_NULL
;
2146 ipc_entry_dealloc(space
, oname
, oentry
);
2147 is_write_unlock(space
);
2149 return KERN_SUCCESS
;