2 * Copyright (c) 2002,2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * @OSF_FREE_COPYRIGHT@
29 * Mach Operating System
30 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
56 * File: ipc/ipc_right.c
60 * Functions to manipulate IPC capabilities.
63 #include <mach/boolean.h>
64 #include <mach/kern_return.h>
65 #include <mach/port.h>
66 #include <mach/message.h>
67 #include <kern/assert.h>
68 #include <kern/misc_protos.h>
70 #include <ipc/ipc_entry.h>
71 #include <ipc/ipc_space.h>
72 #include <ipc/ipc_object.h>
73 #include <ipc/ipc_hash.h>
74 #include <ipc/ipc_port.h>
75 #include <ipc/ipc_pset.h>
76 #include <ipc/ipc_right.h>
77 #include <ipc/ipc_notify.h>
78 #include <ipc/ipc_table.h>
81 * Routine: ipc_right_lookup_write
83 * Finds an entry in a space, given the name.
85 * Nothing locked. If successful, the space is write-locked.
87 * KERN_SUCCESS Found an entry.
88 * KERN_INVALID_TASK The space is dead.
89 * KERN_INVALID_NAME Name doesn't exist in space.
93 ipc_right_lookup_write(
95 mach_port_name_t name
,
100 assert(space
!= IS_NULL
);
102 is_write_lock(space
);
104 if (!space
->is_active
) {
105 is_write_unlock(space
);
106 return KERN_INVALID_TASK
;
109 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
110 is_write_unlock(space
);
111 return KERN_INVALID_NAME
;
119 * Routine: ipc_right_lookup_two_write
121 * Like ipc_right_lookup except that it returns two
122 * entries for two different names that were looked
123 * up under the same space lock.
125 * Nothing locked. If successful, the space is write-locked.
127 * KERN_INVALID_TASK The space is dead.
128 * KERN_INVALID_NAME Name doesn't exist in space.
132 ipc_right_lookup_two_write(
134 mach_port_name_t name1
,
135 ipc_entry_t
*entryp1
,
136 mach_port_name_t name2
,
137 ipc_entry_t
*entryp2
)
142 assert(space
!= IS_NULL
);
144 is_write_lock(space
);
146 if (!space
->is_active
) {
147 is_write_unlock(space
);
148 return KERN_INVALID_TASK
;
151 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
152 is_write_unlock(space
);
153 return KERN_INVALID_NAME
;
155 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
156 is_write_unlock(space
);
157 return KERN_INVALID_NAME
;
165 * Routine: ipc_right_reverse
167 * Translate (space, object) -> (name, entry).
168 * Only finds send/receive rights.
169 * Returns TRUE if an entry is found; if so,
170 * the object is locked and active.
172 * The space must be locked (read or write) and active.
173 * Nothing else locked.
180 mach_port_name_t
*namep
,
184 mach_port_name_t name
;
187 /* would switch on io_otype to handle multiple types of object */
189 assert(space
->is_active
);
190 assert(io_otype(object
) == IOT_PORT
);
192 port
= (ipc_port_t
) object
;
195 if (!ip_active(port
)) {
201 if (port
->ip_receiver
== space
) {
202 name
= port
->ip_receiver_name
;
203 assert(name
!= MACH_PORT_NULL
);
205 entry
= ipc_entry_lookup(space
, name
);
207 assert(entry
!= IE_NULL
);
208 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
209 assert(port
== (ipc_port_t
) entry
->ie_object
);
216 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
217 assert((entry
= *entryp
) != IE_NULL
);
218 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
219 assert(port
== (ipc_port_t
) entry
->ie_object
);
229 * Routine: ipc_right_dnrequest
231 * Make a dead-name request, returning the previously
232 * registered send-once right. If notify is IP_NULL,
233 * just cancels the previously registered request.
235 * This interacts with the IE_BITS_COMPAT, because they
236 * both use ie_request. If this is a compat entry, then
237 * previous always gets IP_NULL. If notify is IP_NULL,
238 * then the entry remains a compat entry. Otherwise
239 * the real dead-name request is registered and the entry
240 * is no longer a compat entry.
242 * Nothing locked. May allocate memory.
243 * Only consumes/returns refs if successful.
245 * KERN_SUCCESS Made/canceled dead-name request.
246 * KERN_INVALID_TASK The space is dead.
247 * KERN_INVALID_NAME Name doesn't exist in space.
248 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
249 * KERN_INVALID_ARGUMENT Name denotes dead name, but
250 * immediate is FALSE or notify is IP_NULL.
251 * KERN_UREFS_OVERFLOW Name denotes dead name, but
252 * generating immediate notif. would overflow urefs.
253 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
259 mach_port_name_t name
,
262 ipc_port_t
*previousp
)
268 ipc_entry_bits_t bits
;
271 kr
= ipc_right_lookup_write(space
, name
, &entry
);
272 if (kr
!= KERN_SUCCESS
)
274 /* space is write-locked and active */
275 bits
= entry
->ie_bits
;
276 if (bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
278 ipc_port_request_index_t request
;
280 port
= (ipc_port_t
) entry
->ie_object
;
281 assert(port
!= IP_NULL
);
283 if (!ipc_right_check(space
, port
, name
, entry
)) {
284 /* port is locked and active */
286 if (notify
== IP_NULL
) {
287 previous
= ipc_right_dncancel_macro(
288 space
, port
, name
, entry
);
291 is_write_unlock(space
);
296 * If a registered soright exists,
297 * want to atomically switch with it.
298 * If ipc_port_dncancel finds us a
299 * soright, then the following
300 * ipc_port_dnrequest will reuse
301 * that slot, so we are guaranteed
302 * not to unlock and retry.
305 previous
= ipc_right_dncancel_macro(space
,
308 kr
= ipc_port_dnrequest(port
, name
, notify
,
310 if (kr
!= KERN_SUCCESS
) {
311 assert(previous
== IP_NULL
);
312 is_write_unlock(space
);
314 kr
= ipc_port_dngrow(port
,
316 /* port is unlocked */
317 if (kr
!= KERN_SUCCESS
)
323 assert(request
!= 0);
326 entry
->ie_request
= request
;
327 is_write_unlock(space
);
332 * Our capability bits were changed by ipc_right_check
333 * because it found an inactive port and removed our
334 * references to it (converting our entry into a dead
335 * one). Reload the bits (and obviously we can't use
336 * the port name anymore).
338 bits
= entry
->ie_bits
;
342 assert(bits
& MACH_PORT_TYPE_DEAD_NAME
);
345 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) &&
346 immediate
&& (notify
!= IP_NULL
)) {
347 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
349 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
352 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
353 is_write_unlock(space
);
354 return KERN_UREFS_OVERFLOW
;
357 (entry
->ie_bits
)++; /* increment urefs */
358 is_write_unlock(space
);
360 ipc_notify_dead_name(notify
, name
);
365 is_write_unlock(space
);
366 if (bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
367 return KERN_INVALID_ARGUMENT
;
369 return KERN_INVALID_RIGHT
;
372 *previousp
= previous
;
377 * Routine: ipc_right_dncancel
379 * Cancel a dead-name request and return the send-once right.
380 * Afterwards, entry->ie_request == 0.
382 * The space must be write-locked; the port must be locked.
383 * The port must be active; the space doesn't have to be.
390 mach_port_name_t name
,
393 ipc_port_t dnrequest
;
395 assert(ip_active(port
));
396 assert(port
== (ipc_port_t
) entry
->ie_object
);
398 dnrequest
= ipc_port_dncancel(port
, name
, entry
->ie_request
);
399 entry
->ie_request
= 0;
405 * Routine: ipc_right_inuse
407 * Check if an entry is being used.
408 * Returns TRUE if it is.
410 * The space is write-locked and active.
411 * It is unlocked if the entry is inuse.
417 mach_port_name_t name
,
420 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
421 is_write_unlock(space
);
428 * Routine: ipc_right_check
430 * Check if the port has died. If it has,
431 * clean up the entry and return TRUE.
433 * The space is write-locked; the port is not locked.
434 * If returns FALSE, the port is also locked and active.
435 * Otherwise, entry is converted to a dead name, freeing
436 * a reference to port.
443 mach_port_name_t name
,
446 ipc_entry_bits_t bits
;
448 assert(space
->is_active
);
449 assert(port
== (ipc_port_t
) entry
->ie_object
);
456 /* this was either a pure send right or a send-once right */
458 bits
= entry
->ie_bits
;
459 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
460 assert(IE_BITS_UREFS(bits
) > 0);
462 if (bits
& MACH_PORT_TYPE_SEND
) {
463 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
465 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
466 assert(IE_BITS_UREFS(bits
) == 1);
470 ipc_port_release(port
);
472 /* convert entry to dead name */
474 if ((bits
& MACH_PORT_TYPE_SEND
) && !(bits
& MACH_PORT_TYPE_RECEIVE
))
475 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
477 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
480 * If there was a notification request outstanding on this
481 * name, and since the port went dead, that notification
482 * must already be on its way up from the port layer. We
483 * don't need the index of the notification port anymore.
485 * JMM - We also add a reference to the entry since the
486 * notification only carries the name and NOT a reference
487 * (or right). This makes for pretty loose reference
488 * counting, since it is only happenstance that we
489 * detected the notification in progress like this.
490 * But most (all?) calls that try to deal with this entry
491 * will also come through here, so the reference gets added
492 * before the entry gets used eventually (I would rather it
493 * be explicit in the notification generation, though)
495 if (entry
->ie_request
!= 0) {
496 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
497 entry
->ie_request
= 0;
500 entry
->ie_bits
= bits
;
501 entry
->ie_object
= IO_NULL
;
506 * Routine: ipc_right_clean
508 * Cleans up an entry in a dead space.
509 * The entry isn't deallocated or removed
510 * from reverse hash tables.
512 * The space is dead and unlocked.
518 mach_port_name_t name
,
521 ipc_entry_bits_t bits
;
522 mach_port_type_t type
;
524 bits
= entry
->ie_bits
;
525 type
= IE_BITS_TYPE(bits
);
527 assert(!space
->is_active
);
530 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
531 * problem, because we check that the port is active. If
532 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
533 * would still work, but dead space refs would accumulate
534 * in ip_dnrequests. They would use up slots in
535 * ip_dnrequests and keep the spaces from being freed.
539 case MACH_PORT_TYPE_DEAD_NAME
:
540 assert(entry
->ie_request
== 0);
541 assert(entry
->ie_object
== IO_NULL
);
544 case MACH_PORT_TYPE_PORT_SET
: {
545 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
547 assert(entry
->ie_request
== 0);
548 assert(pset
!= IPS_NULL
);
551 assert(ips_active(pset
));
553 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
557 case MACH_PORT_TYPE_SEND
:
558 case MACH_PORT_TYPE_RECEIVE
:
559 case MACH_PORT_TYPE_SEND_RECEIVE
:
560 case MACH_PORT_TYPE_SEND_ONCE
: {
561 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
562 ipc_port_t dnrequest
;
563 ipc_port_t nsrequest
= IP_NULL
;
564 mach_port_mscount_t mscount
;
566 assert(port
!= IP_NULL
);
569 if (!ip_active(port
)) {
571 ip_check_unlock(port
);
575 dnrequest
= ipc_right_dncancel_macro(space
, port
,
578 if (type
& MACH_PORT_TYPE_SEND
) {
579 assert(port
->ip_srights
> 0);
580 if (--port
->ip_srights
== 0
582 nsrequest
= port
->ip_nsrequest
;
583 if (nsrequest
!= IP_NULL
) {
584 port
->ip_nsrequest
= IP_NULL
;
585 mscount
= port
->ip_mscount
;
590 if (type
& MACH_PORT_TYPE_RECEIVE
) {
591 assert(port
->ip_receiver_name
== name
);
592 assert(port
->ip_receiver
== space
);
594 ipc_port_clear_receiver(port
);
595 ipc_port_destroy(port
); /* consumes our ref, unlocks */
596 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
597 assert(port
->ip_sorights
> 0);
600 ipc_notify_send_once(port
); /* consumes our ref */
602 assert(port
->ip_receiver
!= space
);
605 ip_unlock(port
); /* port is active */
608 if (nsrequest
!= IP_NULL
)
609 ipc_notify_no_senders(nsrequest
, mscount
);
611 if (dnrequest
!= IP_NULL
)
612 ipc_notify_port_deleted(dnrequest
, name
);
617 panic("ipc_right_clean: strange type");
622 * Routine: ipc_right_destroy
624 * Destroys an entry in a space.
626 * The space is write-locked.
627 * The space must be active.
629 * KERN_SUCCESS The entry was destroyed.
635 mach_port_name_t name
,
638 ipc_entry_bits_t bits
;
639 mach_port_type_t type
;
641 bits
= entry
->ie_bits
;
642 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
643 type
= IE_BITS_TYPE(bits
);
645 assert(space
->is_active
);
648 case MACH_PORT_TYPE_DEAD_NAME
:
649 assert(entry
->ie_request
== 0);
650 assert(entry
->ie_object
== IO_NULL
);
652 ipc_entry_dealloc(space
, name
, entry
);
655 case MACH_PORT_TYPE_PORT_SET
: {
656 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
658 assert(entry
->ie_request
== 0);
659 assert(pset
!= IPS_NULL
);
661 entry
->ie_object
= IO_NULL
;
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 ipc_port_clear_receiver(port
);
721 ipc_port_destroy(port
); /* consumes our ref, unlocks */
722 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
723 assert(port
->ip_sorights
> 0);
726 ipc_notify_send_once(port
); /* consumes our ref */
728 assert(port
->ip_receiver
!= space
);
734 if (nsrequest
!= IP_NULL
)
735 ipc_notify_no_senders(nsrequest
, mscount
);
737 if (dnrequest
!= IP_NULL
)
738 ipc_notify_port_deleted(dnrequest
, name
);
743 panic("ipc_right_destroy: strange type");
750 * Routine: ipc_right_dealloc
752 * Releases a send/send-once/dead-name user ref.
753 * Like ipc_right_delta with a delta of -1,
754 * but looks at the entry to determine the right.
756 * The space is write-locked, and is unlocked upon return.
757 * The space must be active.
759 * KERN_SUCCESS A user ref was released.
760 * KERN_INVALID_RIGHT Entry has wrong type.
766 mach_port_name_t name
,
770 ipc_entry_bits_t bits
;
771 mach_port_type_t type
;
773 bits
= entry
->ie_bits
;
774 type
= IE_BITS_TYPE(bits
);
777 assert(space
->is_active
);
780 case MACH_PORT_TYPE_DEAD_NAME
: {
783 assert(IE_BITS_UREFS(bits
) > 0);
784 assert(entry
->ie_request
== 0);
785 assert(entry
->ie_object
== IO_NULL
);
787 if (IE_BITS_UREFS(bits
) == 1) {
788 ipc_entry_dealloc(space
, name
, entry
);
791 entry
->ie_bits
= bits
-1; /* decrement urefs */
793 is_write_unlock(space
);
797 case MACH_PORT_TYPE_SEND_ONCE
: {
798 ipc_port_t port
, dnrequest
;
800 assert(IE_BITS_UREFS(bits
) == 1);
802 port
= (ipc_port_t
) entry
->ie_object
;
803 assert(port
!= IP_NULL
);
805 if (ipc_right_check(space
, port
, name
, entry
)) {
807 bits
= entry
->ie_bits
;
808 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
811 /* port is locked and active */
813 assert(port
->ip_sorights
> 0);
815 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
818 entry
->ie_object
= IO_NULL
;
819 ipc_entry_dealloc(space
, name
, entry
);
821 is_write_unlock(space
);
823 ipc_notify_send_once(port
);
825 if (dnrequest
!= IP_NULL
)
826 ipc_notify_port_deleted(dnrequest
, name
);
830 case MACH_PORT_TYPE_SEND
: {
832 ipc_port_t dnrequest
= IP_NULL
;
833 ipc_port_t nsrequest
= IP_NULL
;
834 mach_port_mscount_t mscount
;
837 assert(IE_BITS_UREFS(bits
) > 0);
839 port
= (ipc_port_t
) entry
->ie_object
;
840 assert(port
!= IP_NULL
);
842 if (ipc_right_check(space
, port
, name
, entry
)) {
843 bits
= entry
->ie_bits
;
844 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
847 /* port is locked and active */
849 assert(port
->ip_srights
> 0);
851 if (IE_BITS_UREFS(bits
) == 1) {
852 if (--port
->ip_srights
== 0) {
853 nsrequest
= port
->ip_nsrequest
;
854 if (nsrequest
!= IP_NULL
) {
855 port
->ip_nsrequest
= IP_NULL
;
856 mscount
= port
->ip_mscount
;
860 dnrequest
= ipc_right_dncancel_macro(space
, port
,
862 ipc_hash_delete(space
, (ipc_object_t
) port
,
866 entry
->ie_object
= IO_NULL
;
867 ipc_entry_dealloc(space
, name
, entry
);
870 entry
->ie_bits
= bits
-1; /* decrement urefs */
872 /* even if dropped a ref, port is active */
874 is_write_unlock(space
);
876 if (nsrequest
!= IP_NULL
)
877 ipc_notify_no_senders(nsrequest
, mscount
);
879 if (dnrequest
!= IP_NULL
)
880 ipc_notify_port_deleted(dnrequest
, name
);
884 case MACH_PORT_TYPE_SEND_RECEIVE
: {
886 ipc_port_t nsrequest
= IP_NULL
;
887 mach_port_mscount_t mscount
;
889 assert(IE_BITS_UREFS(bits
) > 0);
891 port
= (ipc_port_t
) entry
->ie_object
;
892 assert(port
!= IP_NULL
);
895 assert(ip_active(port
));
896 assert(port
->ip_receiver_name
== name
);
897 assert(port
->ip_receiver
== space
);
898 assert(port
->ip_srights
> 0);
900 if (IE_BITS_UREFS(bits
) == 1) {
901 if (--port
->ip_srights
== 0) {
902 nsrequest
= port
->ip_nsrequest
;
903 if (nsrequest
!= IP_NULL
) {
904 port
->ip_nsrequest
= IP_NULL
;
905 mscount
= port
->ip_mscount
;
909 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
910 MACH_PORT_TYPE_SEND
);
912 entry
->ie_bits
= bits
-1; /* decrement urefs */
915 is_write_unlock(space
);
917 if (nsrequest
!= IP_NULL
)
918 ipc_notify_no_senders(nsrequest
, mscount
);
923 is_write_unlock(space
);
924 return KERN_INVALID_RIGHT
;
931 * Routine: ipc_right_delta
933 * Modifies the user-reference count for a right.
934 * May deallocate the right, if the count goes to zero.
936 * The space is write-locked, and is unlocked upon return.
937 * The space must be active.
939 * KERN_SUCCESS Count was modified.
940 * KERN_INVALID_RIGHT Entry has wrong type.
941 * KERN_INVALID_VALUE Bad delta for the right.
942 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
948 mach_port_name_t name
,
950 mach_port_right_t right
,
951 mach_port_delta_t delta
)
953 ipc_entry_bits_t bits
;
955 bits
= entry
->ie_bits
;
959 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
960 * switch below. It is used to keep track of those cases (in DIPC)
961 * where we have postponed the dropping of a port reference. Since
962 * the dropping of the reference could cause the port to disappear
963 * we postpone doing so when we are holding the space lock.
966 assert(space
->is_active
);
967 assert(right
< MACH_PORT_RIGHT_NUMBER
);
969 /* Rights-specific restrictions and operations. */
972 case MACH_PORT_RIGHT_PORT_SET
: {
975 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
978 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
979 assert(IE_BITS_UREFS(bits
) == 0);
980 assert(entry
->ie_request
== 0);
988 pset
= (ipc_pset_t
) entry
->ie_object
;
989 assert(pset
!= IPS_NULL
);
993 entry
->ie_object
= IO_NULL
;
994 ipc_entry_dealloc(space
, name
, entry
);
998 assert(ips_active(pset
));
999 is_write_unlock(space
);
1001 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1005 case MACH_PORT_RIGHT_RECEIVE
: {
1007 ipc_port_t dnrequest
= IP_NULL
;
1009 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1018 port
= (ipc_port_t
) entry
->ie_object
;
1019 assert(port
!= IP_NULL
);
1022 * The port lock is needed for ipc_right_dncancel;
1023 * otherwise, we wouldn't have to take the lock
1024 * until just before dropping the space lock.
1028 assert(ip_active(port
));
1029 assert(port
->ip_receiver_name
== name
);
1030 assert(port
->ip_receiver
== space
);
1032 if (bits
& MACH_PORT_TYPE_SEND
) {
1033 assert(IE_BITS_TYPE(bits
) ==
1034 MACH_PORT_TYPE_SEND_RECEIVE
);
1035 assert(IE_BITS_UREFS(bits
) > 0);
1036 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1037 assert(port
->ip_srights
> 0);
1040 * The remaining send right turns into a
1041 * dead name. Notice we don't decrement
1042 * ip_srights, generate a no-senders notif,
1043 * or use ipc_right_dncancel, because the
1044 * port is destroyed "first".
1046 bits
&= ~IE_BITS_TYPE_MASK
;
1047 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1048 if (entry
->ie_request
) {
1049 entry
->ie_request
= 0;
1052 entry
->ie_bits
= bits
;
1053 entry
->ie_object
= IO_NULL
;
1055 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1056 assert(IE_BITS_UREFS(bits
) == 0);
1058 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1060 entry
->ie_object
= IO_NULL
;
1061 ipc_entry_dealloc(space
, name
, entry
);
1063 is_write_unlock(space
);
1065 ipc_port_clear_receiver(port
);
1066 ipc_port_destroy(port
); /* consumes ref, unlocks */
1068 if (dnrequest
!= IP_NULL
)
1069 ipc_notify_port_deleted(dnrequest
, name
);
1073 case MACH_PORT_RIGHT_SEND_ONCE
: {
1074 ipc_port_t port
, dnrequest
;
1076 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1079 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1080 assert(IE_BITS_UREFS(bits
) == 1);
1082 port
= (ipc_port_t
) entry
->ie_object
;
1083 assert(port
!= IP_NULL
);
1085 if (ipc_right_check(space
, port
, name
, entry
)) {
1086 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1089 /* port is locked and active */
1091 assert(port
->ip_sorights
> 0);
1093 if ((delta
> 0) || (delta
< -1)) {
1103 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1106 entry
->ie_object
= IO_NULL
;
1107 ipc_entry_dealloc(space
, name
, entry
);
1109 is_write_unlock(space
);
1111 ipc_notify_send_once(port
);
1113 if (dnrequest
!= IP_NULL
)
1114 ipc_notify_port_deleted(dnrequest
, name
);
1118 case MACH_PORT_RIGHT_DEAD_NAME
: {
1119 mach_port_urefs_t urefs
;
1121 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1124 port
= (ipc_port_t
) entry
->ie_object
;
1125 assert(port
!= IP_NULL
);
1127 if (!ipc_right_check(space
, port
, name
, entry
)) {
1128 /* port is locked and active */
1132 bits
= entry
->ie_bits
;
1133 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1136 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1137 assert(IE_BITS_UREFS(bits
) > 0);
1138 assert(entry
->ie_object
== IO_NULL
);
1139 assert(entry
->ie_request
== 0);
1141 urefs
= IE_BITS_UREFS(bits
);
1142 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1144 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1145 goto urefs_overflow
;
1147 if ((urefs
+ delta
) == 0) {
1148 ipc_entry_dealloc(space
, name
, entry
);
1151 entry
->ie_bits
= bits
+ delta
;
1153 is_write_unlock(space
);
1158 case MACH_PORT_RIGHT_SEND
: {
1159 mach_port_urefs_t urefs
;
1161 ipc_port_t dnrequest
= IP_NULL
;
1162 ipc_port_t nsrequest
= IP_NULL
;
1163 mach_port_mscount_t mscount
;
1165 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1168 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1170 port
= (ipc_port_t
) entry
->ie_object
;
1171 assert(port
!= IP_NULL
);
1173 if (ipc_right_check(space
, port
, name
, entry
)) {
1174 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1177 /* port is locked and active */
1179 assert(port
->ip_srights
> 0);
1181 urefs
= IE_BITS_UREFS(bits
);
1182 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1186 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1188 goto urefs_overflow
;
1191 if ((urefs
+ delta
) == 0) {
1192 if (--port
->ip_srights
== 0) {
1193 nsrequest
= port
->ip_nsrequest
;
1194 if (nsrequest
!= IP_NULL
) {
1195 port
->ip_nsrequest
= IP_NULL
;
1196 mscount
= port
->ip_mscount
;
1200 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1201 assert(port
->ip_receiver_name
== name
);
1202 assert(port
->ip_receiver
== space
);
1203 assert(IE_BITS_TYPE(bits
) ==
1204 MACH_PORT_TYPE_SEND_RECEIVE
);
1206 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1207 MACH_PORT_TYPE_SEND
);
1209 assert(IE_BITS_TYPE(bits
) ==
1210 MACH_PORT_TYPE_SEND
);
1212 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1214 ipc_hash_delete(space
, (ipc_object_t
) port
,
1219 entry
->ie_object
= IO_NULL
;
1220 ipc_entry_dealloc(space
, name
, entry
);
1223 entry
->ie_bits
= bits
+ delta
;
1225 /* even if dropped a ref, port is active */
1227 is_write_unlock(space
);
1229 if (nsrequest
!= IP_NULL
)
1230 ipc_notify_no_senders(nsrequest
, mscount
);
1232 if (dnrequest
!= IP_NULL
)
1233 ipc_notify_port_deleted(dnrequest
, name
);
1238 panic("ipc_right_delta: strange right");
1241 return KERN_SUCCESS
;
1244 is_write_unlock(space
);
1245 return KERN_SUCCESS
;
1248 is_write_unlock(space
);
1249 return KERN_INVALID_RIGHT
;
1252 is_write_unlock(space
);
1253 return KERN_INVALID_VALUE
;
1256 is_write_unlock(space
);
1257 return KERN_UREFS_OVERFLOW
;
1261 * Routine: ipc_right_info
1263 * Retrieves information about the right.
1265 * The space is write-locked, and is unlocked upon return
1266 * if the call is unsuccessful. The space must be active.
1268 * KERN_SUCCESS Retrieved info; space still locked.
1274 mach_port_name_t name
,
1276 mach_port_type_t
*typep
,
1277 mach_port_urefs_t
*urefsp
)
1279 ipc_entry_bits_t bits
;
1280 mach_port_type_t type
;
1281 ipc_port_request_index_t request
;
1283 bits
= entry
->ie_bits
;
1285 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1286 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1288 if (ipc_right_check(space
, port
, name
, entry
)) {
1289 bits
= entry
->ie_bits
;
1290 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1295 type
= IE_BITS_TYPE(bits
);
1296 request
= entry
->ie_request
;
1299 type
|= MACH_PORT_TYPE_DNREQUEST
;
1302 *urefsp
= IE_BITS_UREFS(bits
);
1303 return KERN_SUCCESS
;
1307 * Routine: ipc_right_copyin_check
1309 * Check if a subsequent ipc_right_copyin would succeed.
1311 * The space is locked (read or write) and active.
1315 ipc_right_copyin_check(
1317 mach_port_name_t name
,
1319 mach_msg_type_name_t msgt_name
)
1321 ipc_entry_bits_t bits
;
1323 bits
= entry
->ie_bits
;
1324 assert(space
->is_active
);
1326 switch (msgt_name
) {
1327 case MACH_MSG_TYPE_MAKE_SEND
:
1328 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1329 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1330 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1335 case MACH_MSG_TYPE_COPY_SEND
:
1336 case MACH_MSG_TYPE_MOVE_SEND
:
1337 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1341 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1344 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1347 port
= (ipc_port_t
) entry
->ie_object
;
1348 assert(port
!= IP_NULL
);
1351 active
= ip_active(port
);
1358 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1359 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1362 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1370 panic("ipc_right_copyin_check: strange rights");
1377 * Routine: ipc_right_copyin
1379 * Copyin a capability from a space.
1380 * If successful, the caller gets a ref
1381 * for the resulting object, unless it is IO_DEAD,
1382 * and possibly a send-once right which should
1383 * be used in a port-deleted notification.
1385 * If deadok is not TRUE, the copyin operation
1386 * will fail instead of producing IO_DEAD.
1388 * The entry is never deallocated (except
1389 * when KERN_INVALID_NAME), so the caller
1390 * should deallocate the entry if its type
1391 * is MACH_PORT_TYPE_NONE.
1393 * The space is write-locked and active.
1395 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1396 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1402 mach_port_name_t name
,
1404 mach_msg_type_name_t msgt_name
,
1406 ipc_object_t
*objectp
,
1407 ipc_port_t
*sorightp
)
1409 ipc_entry_bits_t bits
;
1411 bits
= entry
->ie_bits
;
1413 assert(space
->is_active
);
1415 switch (msgt_name
) {
1416 case MACH_MSG_TYPE_MAKE_SEND
: {
1419 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1422 port
= (ipc_port_t
) entry
->ie_object
;
1423 assert(port
!= IP_NULL
);
1426 assert(ip_active(port
));
1427 assert(port
->ip_receiver_name
== name
);
1428 assert(port
->ip_receiver
== space
);
1435 *objectp
= (ipc_object_t
) port
;
1436 *sorightp
= IP_NULL
;
1440 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1443 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1446 port
= (ipc_port_t
) entry
->ie_object
;
1447 assert(port
!= IP_NULL
);
1450 assert(ip_active(port
));
1451 assert(port
->ip_receiver_name
== name
);
1452 assert(port
->ip_receiver
== space
);
1454 port
->ip_sorights
++;
1458 *objectp
= (ipc_object_t
) port
;
1459 *sorightp
= IP_NULL
;
1463 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1465 ipc_port_t dnrequest
= IP_NULL
;
1467 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1470 port
= (ipc_port_t
) entry
->ie_object
;
1471 assert(port
!= IP_NULL
);
1474 assert(ip_active(port
));
1475 assert(port
->ip_receiver_name
== name
);
1476 assert(port
->ip_receiver
== space
);
1478 if (bits
& MACH_PORT_TYPE_SEND
) {
1479 assert(IE_BITS_TYPE(bits
) ==
1480 MACH_PORT_TYPE_SEND_RECEIVE
);
1481 assert(IE_BITS_UREFS(bits
) > 0);
1482 assert(port
->ip_srights
> 0);
1484 ipc_hash_insert(space
, (ipc_object_t
) port
,
1488 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1489 assert(IE_BITS_UREFS(bits
) == 0);
1491 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1493 entry
->ie_object
= IO_NULL
;
1495 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1497 ipc_port_clear_receiver(port
);
1499 port
->ip_receiver_name
= MACH_PORT_NULL
;
1500 port
->ip_destination
= IP_NULL
;
1503 *objectp
= (ipc_object_t
) port
;
1504 *sorightp
= dnrequest
;
1508 case MACH_MSG_TYPE_COPY_SEND
: {
1511 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1514 /* allow for dead send-once rights */
1516 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1519 assert(IE_BITS_UREFS(bits
) > 0);
1521 port
= (ipc_port_t
) entry
->ie_object
;
1522 assert(port
!= IP_NULL
);
1524 if (ipc_right_check(space
, port
, name
, entry
)) {
1525 bits
= entry
->ie_bits
;
1528 /* port is locked and active */
1530 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1531 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1532 assert(port
->ip_sorights
> 0);
1538 assert(port
->ip_srights
> 0);
1544 *objectp
= (ipc_object_t
) port
;
1545 *sorightp
= IP_NULL
;
1549 case MACH_MSG_TYPE_MOVE_SEND
: {
1551 ipc_port_t dnrequest
= IP_NULL
;
1553 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1556 /* allow for dead send-once rights */
1558 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1561 assert(IE_BITS_UREFS(bits
) > 0);
1563 port
= (ipc_port_t
) entry
->ie_object
;
1564 assert(port
!= IP_NULL
);
1566 if (ipc_right_check(space
, port
, name
, entry
)) {
1567 bits
= entry
->ie_bits
;
1570 /* port is locked and active */
1572 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1573 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1574 assert(port
->ip_sorights
> 0);
1580 assert(port
->ip_srights
> 0);
1582 if (IE_BITS_UREFS(bits
) == 1) {
1583 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1584 assert(port
->ip_receiver_name
== name
);
1585 assert(port
->ip_receiver
== space
);
1586 assert(IE_BITS_TYPE(bits
) ==
1587 MACH_PORT_TYPE_SEND_RECEIVE
);
1591 assert(IE_BITS_TYPE(bits
) ==
1592 MACH_PORT_TYPE_SEND
);
1594 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1596 ipc_hash_delete(space
, (ipc_object_t
) port
,
1598 entry
->ie_object
= IO_NULL
;
1600 entry
->ie_bits
= bits
&~
1601 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1605 entry
->ie_bits
= bits
-1; /* decrement urefs */
1610 *objectp
= (ipc_object_t
) port
;
1611 *sorightp
= dnrequest
;
1615 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1617 ipc_port_t dnrequest
;
1619 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1622 /* allow for dead send rights */
1624 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1627 assert(IE_BITS_UREFS(bits
) > 0);
1629 port
= (ipc_port_t
) entry
->ie_object
;
1630 assert(port
!= IP_NULL
);
1632 if (ipc_right_check(space
, port
, name
, entry
)) {
1633 bits
= entry
->ie_bits
;
1636 /* port is locked and active */
1638 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1639 assert(bits
& MACH_PORT_TYPE_SEND
);
1640 assert(port
->ip_srights
> 0);
1646 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1647 assert(IE_BITS_UREFS(bits
) == 1);
1648 assert(port
->ip_sorights
> 0);
1650 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1653 entry
->ie_object
= IO_NULL
;
1654 entry
->ie_bits
= bits
&~
1655 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
1657 *objectp
= (ipc_object_t
) port
;
1658 *sorightp
= dnrequest
;
1664 return KERN_INVALID_RIGHT
;
1667 return KERN_SUCCESS
;
1670 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1671 assert(IE_BITS_UREFS(bits
) > 0);
1672 assert(entry
->ie_request
== 0);
1673 assert(entry
->ie_object
== 0);
1679 *sorightp
= IP_NULL
;
1680 return KERN_SUCCESS
;
1683 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1684 assert(IE_BITS_UREFS(bits
) > 0);
1685 assert(entry
->ie_request
== 0);
1686 assert(entry
->ie_object
== 0);
1691 if (IE_BITS_UREFS(bits
) == 1) {
1692 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
1694 entry
->ie_bits
= bits
-1; /* decrement urefs */
1697 *sorightp
= IP_NULL
;
1698 return KERN_SUCCESS
;
1703 * Routine: ipc_right_copyin_undo
1705 * Undoes the effects of an ipc_right_copyin
1706 * of a send/send-once right that is dead.
1707 * (Object is either IO_DEAD or a dead port.)
1709 * The space is write-locked and active.
1713 ipc_right_copyin_undo(
1715 mach_port_name_t name
,
1717 mach_msg_type_name_t msgt_name
,
1718 ipc_object_t object
,
1721 ipc_entry_bits_t bits
;
1723 bits
= entry
->ie_bits
;
1725 assert(space
->is_active
);
1727 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1728 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
1729 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1731 if (soright
!= IP_NULL
) {
1732 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1733 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1734 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1735 assert(object
!= IO_DEAD
);
1737 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1738 MACH_PORT_TYPE_DEAD_NAME
| 2);
1740 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
1741 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1742 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1744 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1745 MACH_PORT_TYPE_DEAD_NAME
| 1);
1746 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
1747 assert(object
== IO_DEAD
);
1748 assert(IE_BITS_UREFS(bits
) > 0);
1750 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1751 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1752 entry
->ie_bits
= bits
+1; /* increment urefs */
1755 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1756 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
1757 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1758 assert(object
!= IO_DEAD
);
1759 assert(entry
->ie_object
== object
);
1760 assert(IE_BITS_UREFS(bits
) > 0);
1762 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1763 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
1764 entry
->ie_bits
= bits
+1; /* increment urefs */
1768 * May as well convert the entry to a dead name.
1769 * (Or if it is a compat entry, destroy it.)
1772 (void) ipc_right_check(space
, (ipc_port_t
) object
,
1774 /* object is dead so it is not locked */
1777 /* release the reference acquired by copyin */
1779 if (object
!= IO_DEAD
)
1780 ipc_object_release(object
);
1784 * Routine: ipc_right_copyin_two
1786 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1787 * and deadok == FALSE, except that this moves two
1788 * send rights at once.
1790 * The space is write-locked and active.
1791 * The object is returned with two refs/send rights.
1793 * KERN_SUCCESS Acquired an object.
1794 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1798 ipc_right_copyin_two(
1800 mach_port_name_t name
,
1802 ipc_object_t
*objectp
,
1803 ipc_port_t
*sorightp
)
1805 ipc_entry_bits_t bits
;
1806 mach_port_urefs_t urefs
;
1808 ipc_port_t dnrequest
= IP_NULL
;
1810 assert(space
->is_active
);
1812 bits
= entry
->ie_bits
;
1814 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1817 urefs
= IE_BITS_UREFS(bits
);
1821 port
= (ipc_port_t
) entry
->ie_object
;
1822 assert(port
!= IP_NULL
);
1824 if (ipc_right_check(space
, port
, name
, entry
)) {
1827 /* port is locked and active */
1829 assert(port
->ip_srights
> 0);
1832 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1833 assert(port
->ip_receiver_name
== name
);
1834 assert(port
->ip_receiver
== space
);
1835 assert(IE_BITS_TYPE(bits
) ==
1836 MACH_PORT_TYPE_SEND_RECEIVE
);
1842 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1844 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1849 ipc_hash_delete(space
, (ipc_object_t
) port
,
1851 entry
->ie_object
= IO_NULL
;
1853 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1855 port
->ip_srights
+= 2;
1858 entry
->ie_bits
= bits
-2; /* decrement urefs */
1862 *objectp
= (ipc_object_t
) port
;
1863 *sorightp
= dnrequest
;
1864 return KERN_SUCCESS
;
1867 return KERN_INVALID_RIGHT
;
1871 * Routine: ipc_right_copyout
1873 * Copyout a capability to a space.
1874 * If successful, consumes a ref for the object.
1876 * Always succeeds when given a newly-allocated entry,
1877 * because user-reference overflow isn't a possibility.
1879 * If copying out the object would cause the user-reference
1880 * count in the entry to overflow, and overflow is TRUE,
1881 * then instead the user-reference count is left pegged
1882 * to its maximum value and the copyout succeeds anyway.
1884 * The space is write-locked and active.
1885 * The object is locked and active.
1886 * The object is unlocked; the space isn't.
1888 * KERN_SUCCESS Copied out capability.
1889 * KERN_UREFS_OVERFLOW User-refs would overflow;
1890 * guaranteed not to happen with a fresh entry
1891 * or if overflow=TRUE was specified.
1897 mach_port_name_t name
,
1899 mach_msg_type_name_t msgt_name
,
1901 ipc_object_t object
)
1903 ipc_entry_bits_t bits
;
1906 bits
= entry
->ie_bits
;
1908 assert(IO_VALID(object
));
1909 assert(io_otype(object
) == IOT_PORT
);
1910 assert(io_active(object
));
1911 assert(entry
->ie_object
== object
);
1913 port
= (ipc_port_t
) object
;
1915 switch (msgt_name
) {
1916 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
1918 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1919 assert(port
->ip_sorights
> 0);
1921 /* transfer send-once right and ref to entry */
1924 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
1927 case MACH_MSG_TYPE_PORT_SEND
:
1928 assert(port
->ip_srights
> 0);
1930 if (bits
& MACH_PORT_TYPE_SEND
) {
1931 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
1933 assert(port
->ip_srights
> 1);
1935 assert(urefs
< MACH_PORT_UREFS_MAX
);
1937 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
1939 /* leave urefs pegged to maximum */
1944 return KERN_SUCCESS
;
1948 return KERN_UREFS_OVERFLOW
;
1954 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1955 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1956 assert(IE_BITS_UREFS(bits
) == 0);
1958 /* transfer send right to entry */
1962 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1963 assert(IE_BITS_UREFS(bits
) == 0);
1965 /* transfer send right and ref to entry */
1968 /* entry is locked holding ref, so can use port */
1970 ipc_hash_insert(space
, (ipc_object_t
) port
,
1974 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
1977 case MACH_MSG_TYPE_PORT_RECEIVE
: {
1980 assert(port
->ip_mscount
== 0);
1981 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1982 dest
= port
->ip_destination
;
1984 port
->ip_receiver_name
= name
;
1985 port
->ip_receiver
= space
;
1987 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
1989 if (bits
& MACH_PORT_TYPE_SEND
) {
1990 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1991 assert(IE_BITS_UREFS(bits
) > 0);
1992 assert(port
->ip_srights
> 0);
1997 /* entry is locked holding ref, so can use port */
1999 ipc_hash_delete(space
, (ipc_object_t
) port
,
2002 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2003 assert(IE_BITS_UREFS(bits
) == 0);
2005 /* transfer ref to entry */
2008 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2010 if (dest
!= IP_NULL
)
2011 ipc_port_release(dest
);
2016 panic("ipc_right_copyout: strange rights");
2019 return KERN_SUCCESS
;
2023 * Routine: ipc_right_rename
2025 * Transfer an entry from one name to another.
2026 * The old entry is deallocated.
2028 * The space is write-locked and active.
2029 * The new entry is unused. Upon return,
2030 * the space is unlocked.
2032 * KERN_SUCCESS Moved entry to new name.
2038 mach_port_name_t oname
,
2040 mach_port_name_t nname
,
2043 ipc_port_request_index_t request
= oentry
->ie_request
;
2044 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2045 ipc_object_t object
= oentry
->ie_object
;
2047 assert(space
->is_active
);
2048 assert(oname
!= nname
);
2051 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2052 * if the port is dead. (This would foil ipc_port_destroy.)
2053 * Instead we should fail because oentry shouldn't exist.
2054 * Note IE_BITS_COMPAT implies ie_request != 0.
2060 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2061 port
= (ipc_port_t
) object
;
2062 assert(port
!= IP_NULL
);
2064 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2067 bits
= oentry
->ie_bits
;
2068 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2069 assert(oentry
->ie_request
== 0);
2071 /* port is locked and active */
2073 ipc_port_dnrename(port
, request
, oname
, nname
);
2075 oentry
->ie_request
= 0;
2079 /* initialize nentry before letting ipc_hash_insert see it */
2081 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2082 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2083 nentry
->ie_request
= request
;
2084 nentry
->ie_object
= object
;
2086 switch (IE_BITS_TYPE(bits
)) {
2087 case MACH_PORT_TYPE_SEND
: {
2090 port
= (ipc_port_t
) object
;
2091 assert(port
!= IP_NULL
);
2093 /* remember, there are no other share entries possible */
2094 /* or we can't do the rename. Therefore we do not need */
2095 /* to check the other subspaces */
2096 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2097 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2101 case MACH_PORT_TYPE_RECEIVE
:
2102 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2105 port
= (ipc_port_t
) object
;
2106 assert(port
!= IP_NULL
);
2109 assert(ip_active(port
));
2110 assert(port
->ip_receiver_name
== oname
);
2111 assert(port
->ip_receiver
== space
);
2113 port
->ip_receiver_name
= nname
;
2118 case MACH_PORT_TYPE_PORT_SET
: {
2121 pset
= (ipc_pset_t
) object
;
2122 assert(pset
!= IPS_NULL
);
2125 assert(ips_active(pset
));
2126 assert(pset
->ips_local_name
== oname
);
2128 pset
->ips_local_name
= nname
;
2133 case MACH_PORT_TYPE_SEND_ONCE
:
2134 case MACH_PORT_TYPE_DEAD_NAME
:
2138 panic("ipc_right_rename: strange rights");
2141 assert(oentry
->ie_request
== 0);
2142 oentry
->ie_object
= IO_NULL
;
2143 ipc_entry_dealloc(space
, oname
, oentry
);
2144 is_write_unlock(space
);
2146 return KERN_SUCCESS
;