2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * @OSF_FREE_COPYRIGHT@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
36 * All Rights Reserved.
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
61 * File: ipc/ipc_right.c
65 * Functions to manipulate IPC capabilities.
68 #include <mach/boolean.h>
69 #include <mach/kern_return.h>
70 #include <mach/port.h>
71 #include <mach/message.h>
72 #include <kern/assert.h>
73 #include <kern/misc_protos.h>
75 #include <ipc/ipc_entry.h>
76 #include <ipc/ipc_space.h>
77 #include <ipc/ipc_object.h>
78 #include <ipc/ipc_hash.h>
79 #include <ipc/ipc_port.h>
80 #include <ipc/ipc_pset.h>
81 #include <ipc/ipc_right.h>
82 #include <ipc/ipc_notify.h>
83 #include <ipc/ipc_table.h>
86 * Routine: ipc_right_lookup_write
88 * Finds an entry in a space, given the name.
90 * Nothing locked. If successful, the space is write-locked.
92 * KERN_SUCCESS Found an entry.
93 * KERN_INVALID_TASK The space is dead.
94 * KERN_INVALID_NAME Name doesn't exist in space.
98 ipc_right_lookup_write(
100 mach_port_name_t name
,
105 assert(space
!= IS_NULL
);
107 is_write_lock(space
);
109 if (!space
->is_active
) {
110 is_write_unlock(space
);
111 return KERN_INVALID_TASK
;
114 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
115 is_write_unlock(space
);
116 return KERN_INVALID_NAME
;
124 * Routine: ipc_right_lookup_two_write
126 * Like ipc_right_lookup except that it returns two
127 * entries for two different names that were looked
128 * up under the same space lock.
130 * Nothing locked. If successful, the space is write-locked.
132 * KERN_INVALID_TASK The space is dead.
133 * KERN_INVALID_NAME Name doesn't exist in space.
137 ipc_right_lookup_two_write(
139 mach_port_name_t name1
,
140 ipc_entry_t
*entryp1
,
141 mach_port_name_t name2
,
142 ipc_entry_t
*entryp2
)
147 assert(space
!= IS_NULL
);
149 is_write_lock(space
);
151 if (!space
->is_active
) {
152 is_write_unlock(space
);
153 return KERN_INVALID_TASK
;
156 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
157 is_write_unlock(space
);
158 return KERN_INVALID_NAME
;
160 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
161 is_write_unlock(space
);
162 return KERN_INVALID_NAME
;
170 * Routine: ipc_right_reverse
172 * Translate (space, object) -> (name, entry).
173 * Only finds send/receive rights.
174 * Returns TRUE if an entry is found; if so,
175 * the object is locked and active.
177 * The space must be locked (read or write) and active.
178 * Nothing else locked.
185 mach_port_name_t
*namep
,
189 mach_port_name_t name
;
192 /* would switch on io_otype to handle multiple types of object */
194 assert(space
->is_active
);
195 assert(io_otype(object
) == IOT_PORT
);
197 port
= (ipc_port_t
) object
;
200 if (!ip_active(port
)) {
206 if (port
->ip_receiver
== space
) {
207 name
= port
->ip_receiver_name
;
208 assert(name
!= MACH_PORT_NULL
);
210 entry
= ipc_entry_lookup(space
, name
);
212 assert(entry
!= IE_NULL
);
213 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
214 assert(port
== (ipc_port_t
) entry
->ie_object
);
221 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
222 assert((entry
= *entryp
) != IE_NULL
);
223 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
224 assert(port
== (ipc_port_t
) entry
->ie_object
);
234 * Routine: ipc_right_dnrequest
236 * Make a dead-name request, returning the previously
237 * registered send-once right. If notify is IP_NULL,
238 * just cancels the previously registered request.
240 * This interacts with the IE_BITS_COMPAT, because they
241 * both use ie_request. If this is a compat entry, then
242 * previous always gets IP_NULL. If notify is IP_NULL,
243 * then the entry remains a compat entry. Otherwise
244 * the real dead-name request is registered and the entry
245 * is no longer a compat entry.
247 * Nothing locked. May allocate memory.
248 * Only consumes/returns refs if successful.
250 * KERN_SUCCESS Made/canceled dead-name request.
251 * KERN_INVALID_TASK The space is dead.
252 * KERN_INVALID_NAME Name doesn't exist in space.
253 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
254 * KERN_INVALID_ARGUMENT Name denotes dead name, but
255 * immediate is FALSE or notify is IP_NULL.
256 * KERN_UREFS_OVERFLOW Name denotes dead name, but
257 * generating immediate notif. would overflow urefs.
258 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
264 mach_port_name_t name
,
267 ipc_port_t
*previousp
)
273 ipc_entry_bits_t bits
;
276 kr
= ipc_right_lookup_write(space
, name
, &entry
);
277 if (kr
!= KERN_SUCCESS
)
279 /* space is write-locked and active */
280 bits
= entry
->ie_bits
;
281 if (bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
283 ipc_port_request_index_t request
;
285 port
= (ipc_port_t
) entry
->ie_object
;
286 assert(port
!= IP_NULL
);
288 if (!ipc_right_check(space
, port
, name
, entry
)) {
289 /* port is locked and active */
291 if (notify
== IP_NULL
) {
292 previous
= ipc_right_dncancel_macro(
293 space
, port
, name
, entry
);
296 is_write_unlock(space
);
301 * If a registered soright exists,
302 * want to atomically switch with it.
303 * If ipc_port_dncancel finds us a
304 * soright, then the following
305 * ipc_port_dnrequest will reuse
306 * that slot, so we are guaranteed
307 * not to unlock and retry.
310 previous
= ipc_right_dncancel_macro(space
,
313 kr
= ipc_port_dnrequest(port
, name
, notify
,
315 if (kr
!= KERN_SUCCESS
) {
316 assert(previous
== IP_NULL
);
317 is_write_unlock(space
);
319 kr
= ipc_port_dngrow(port
,
321 /* port is unlocked */
322 if (kr
!= KERN_SUCCESS
)
328 assert(request
!= 0);
331 entry
->ie_request
= request
;
332 is_write_unlock(space
);
337 * Our capability bits were changed by ipc_right_check
338 * because it found an inactive port and removed our
339 * references to it (converting our entry into a dead
340 * one). Reload the bits (and obviously we can't use
341 * the port name anymore).
343 bits
= entry
->ie_bits
;
347 assert(bits
& MACH_PORT_TYPE_DEAD_NAME
);
350 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) &&
351 immediate
&& (notify
!= IP_NULL
)) {
352 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
354 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
357 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
358 is_write_unlock(space
);
359 return KERN_UREFS_OVERFLOW
;
362 (entry
->ie_bits
)++; /* increment urefs */
363 is_write_unlock(space
);
365 ipc_notify_dead_name(notify
, name
);
370 is_write_unlock(space
);
371 if (bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
372 return KERN_INVALID_ARGUMENT
;
374 return KERN_INVALID_RIGHT
;
377 *previousp
= previous
;
382 * Routine: ipc_right_dncancel
384 * Cancel a dead-name request and return the send-once right.
385 * Afterwards, entry->ie_request == 0.
387 * The space must be write-locked; the port must be locked.
388 * The port must be active; the space doesn't have to be.
393 __unused ipc_space_t space
,
395 mach_port_name_t name
,
398 ipc_port_t dnrequest
;
400 assert(ip_active(port
));
401 assert(port
== (ipc_port_t
) entry
->ie_object
);
403 dnrequest
= ipc_port_dncancel(port
, name
, entry
->ie_request
);
404 entry
->ie_request
= 0;
410 * Routine: ipc_right_inuse
412 * Check if an entry is being used.
413 * Returns TRUE if it is.
415 * The space is write-locked and active.
416 * It is unlocked if the entry is inuse.
422 __unused mach_port_name_t name
,
425 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
426 is_write_unlock(space
);
433 * Routine: ipc_right_check
435 * Check if the port has died. If it has,
436 * clean up the entry and return TRUE.
438 * The space is write-locked; the port is not locked.
439 * If returns FALSE, the port is also locked and active.
440 * Otherwise, entry is converted to a dead name, freeing
441 * a reference to port.
448 mach_port_name_t name
,
451 ipc_entry_bits_t bits
;
453 assert(space
->is_active
);
454 assert(port
== (ipc_port_t
) entry
->ie_object
);
461 /* this was either a pure send right or a send-once right */
463 bits
= entry
->ie_bits
;
464 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
465 assert(IE_BITS_UREFS(bits
) > 0);
467 if (bits
& MACH_PORT_TYPE_SEND
) {
468 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
470 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
471 assert(IE_BITS_UREFS(bits
) == 1);
475 ipc_port_release(port
);
477 /* convert entry to dead name */
479 if ((bits
& MACH_PORT_TYPE_SEND
) && !(bits
& MACH_PORT_TYPE_RECEIVE
))
480 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
482 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
485 * If there was a notification request outstanding on this
486 * name, and since the port went dead, that notification
487 * must already be on its way up from the port layer. We
488 * don't need the index of the notification port anymore.
490 * JMM - We also add a reference to the entry since the
491 * notification only carries the name and NOT a reference
492 * (or right). This makes for pretty loose reference
493 * counting, since it is only happenstance that we
494 * detected the notification in progress like this.
495 * But most (all?) calls that try to deal with this entry
496 * will also come through here, so the reference gets added
497 * before the entry gets used eventually (I would rather it
498 * be explicit in the notification generation, though)
500 if (entry
->ie_request
!= 0) {
501 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
502 entry
->ie_request
= 0;
505 entry
->ie_bits
= bits
;
506 entry
->ie_object
= IO_NULL
;
511 * Routine: ipc_right_clean
513 * Cleans up an entry in a dead space.
514 * The entry isn't deallocated or removed
515 * from reverse hash tables.
517 * The space is dead and unlocked.
523 mach_port_name_t name
,
526 ipc_entry_bits_t bits
;
527 mach_port_type_t type
;
529 bits
= entry
->ie_bits
;
530 type
= IE_BITS_TYPE(bits
);
532 assert(!space
->is_active
);
535 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
536 * problem, because we check that the port is active. If
537 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
538 * would still work, but dead space refs would accumulate
539 * in ip_dnrequests. They would use up slots in
540 * ip_dnrequests and keep the spaces from being freed.
544 case MACH_PORT_TYPE_DEAD_NAME
:
545 assert(entry
->ie_request
== 0);
546 assert(entry
->ie_object
== IO_NULL
);
549 case MACH_PORT_TYPE_PORT_SET
: {
550 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
552 assert(entry
->ie_request
== 0);
553 assert(pset
!= IPS_NULL
);
556 assert(ips_active(pset
));
558 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
562 case MACH_PORT_TYPE_SEND
:
563 case MACH_PORT_TYPE_RECEIVE
:
564 case MACH_PORT_TYPE_SEND_RECEIVE
:
565 case MACH_PORT_TYPE_SEND_ONCE
: {
566 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
567 ipc_port_t dnrequest
;
568 ipc_port_t nsrequest
= IP_NULL
;
569 mach_port_mscount_t mscount
= 0;
571 assert(port
!= IP_NULL
);
574 if (!ip_active(port
)) {
576 ip_check_unlock(port
);
580 dnrequest
= ipc_right_dncancel_macro(space
, port
,
583 if (type
& MACH_PORT_TYPE_SEND
) {
584 assert(port
->ip_srights
> 0);
585 if (--port
->ip_srights
== 0
587 nsrequest
= port
->ip_nsrequest
;
588 if (nsrequest
!= IP_NULL
) {
589 port
->ip_nsrequest
= IP_NULL
;
590 mscount
= port
->ip_mscount
;
595 if (type
& MACH_PORT_TYPE_RECEIVE
) {
596 assert(port
->ip_receiver_name
== name
);
597 assert(port
->ip_receiver
== space
);
599 ipc_port_clear_receiver(port
);
600 ipc_port_destroy(port
); /* consumes our ref, unlocks */
601 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
602 assert(port
->ip_sorights
> 0);
605 ipc_notify_send_once(port
); /* consumes our ref */
607 assert(port
->ip_receiver
!= space
);
610 ip_unlock(port
); /* port is active */
613 if (nsrequest
!= IP_NULL
)
614 ipc_notify_no_senders(nsrequest
, mscount
);
616 if (dnrequest
!= IP_NULL
)
617 ipc_notify_port_deleted(dnrequest
, name
);
622 panic("ipc_right_clean: strange type");
627 * Routine: ipc_right_destroy
629 * Destroys an entry in a space.
631 * The space is write-locked.
632 * The space must be active.
634 * KERN_SUCCESS The entry was destroyed.
640 mach_port_name_t name
,
643 ipc_entry_bits_t bits
;
644 mach_port_type_t type
;
646 bits
= entry
->ie_bits
;
647 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
648 type
= IE_BITS_TYPE(bits
);
650 assert(space
->is_active
);
653 case MACH_PORT_TYPE_DEAD_NAME
:
654 assert(entry
->ie_request
== 0);
655 assert(entry
->ie_object
== IO_NULL
);
657 ipc_entry_dealloc(space
, name
, entry
);
660 case MACH_PORT_TYPE_PORT_SET
: {
661 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
663 assert(entry
->ie_request
== 0);
664 assert(pset
!= IPS_NULL
);
666 entry
->ie_object
= IO_NULL
;
667 ipc_entry_dealloc(space
, name
, entry
);
670 assert(ips_active(pset
));
672 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
676 case MACH_PORT_TYPE_SEND
:
677 case MACH_PORT_TYPE_RECEIVE
:
678 case MACH_PORT_TYPE_SEND_RECEIVE
:
679 case MACH_PORT_TYPE_SEND_ONCE
: {
680 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
681 ipc_port_t nsrequest
= IP_NULL
;
682 mach_port_mscount_t mscount
= 0;
683 ipc_port_t dnrequest
;
685 assert(port
!= IP_NULL
);
687 if (type
== MACH_PORT_TYPE_SEND
)
688 ipc_hash_delete(space
, (ipc_object_t
) port
,
693 if (!ip_active(port
)) {
694 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
696 ip_check_unlock(port
);
698 entry
->ie_request
= 0;
699 entry
->ie_object
= IO_NULL
;
700 ipc_entry_dealloc(space
, name
, entry
);
705 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
707 entry
->ie_object
= IO_NULL
;
708 ipc_entry_dealloc(space
, name
, entry
);
710 if (type
& MACH_PORT_TYPE_SEND
) {
711 assert(port
->ip_srights
> 0);
712 if (--port
->ip_srights
== 0) {
713 nsrequest
= port
->ip_nsrequest
;
714 if (nsrequest
!= IP_NULL
) {
715 port
->ip_nsrequest
= IP_NULL
;
716 mscount
= port
->ip_mscount
;
721 if (type
& MACH_PORT_TYPE_RECEIVE
) {
722 assert(ip_active(port
));
723 assert(port
->ip_receiver
== space
);
725 ipc_port_clear_receiver(port
);
726 ipc_port_destroy(port
); /* consumes our ref, unlocks */
727 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
728 assert(port
->ip_sorights
> 0);
731 ipc_notify_send_once(port
); /* consumes our ref */
733 assert(port
->ip_receiver
!= space
);
739 if (nsrequest
!= IP_NULL
)
740 ipc_notify_no_senders(nsrequest
, mscount
);
742 if (dnrequest
!= IP_NULL
)
743 ipc_notify_port_deleted(dnrequest
, name
);
748 panic("ipc_right_destroy: strange type");
755 * Routine: ipc_right_dealloc
757 * Releases a send/send-once/dead-name user ref.
758 * Like ipc_right_delta with a delta of -1,
759 * but looks at the entry to determine the right.
761 * The space is write-locked, and is unlocked upon return.
762 * The space must be active.
764 * KERN_SUCCESS A user ref was released.
765 * KERN_INVALID_RIGHT Entry has wrong type.
771 mach_port_name_t name
,
775 ipc_entry_bits_t bits
;
776 mach_port_type_t type
;
778 bits
= entry
->ie_bits
;
779 type
= IE_BITS_TYPE(bits
);
782 assert(space
->is_active
);
785 case MACH_PORT_TYPE_DEAD_NAME
: {
788 assert(IE_BITS_UREFS(bits
) > 0);
789 assert(entry
->ie_request
== 0);
790 assert(entry
->ie_object
== IO_NULL
);
792 if (IE_BITS_UREFS(bits
) == 1) {
793 ipc_entry_dealloc(space
, name
, entry
);
796 entry
->ie_bits
= bits
-1; /* decrement urefs */
798 is_write_unlock(space
);
802 case MACH_PORT_TYPE_SEND_ONCE
: {
803 ipc_port_t port
, dnrequest
;
805 assert(IE_BITS_UREFS(bits
) == 1);
807 port
= (ipc_port_t
) entry
->ie_object
;
808 assert(port
!= IP_NULL
);
810 if (ipc_right_check(space
, port
, name
, entry
)) {
812 bits
= entry
->ie_bits
;
813 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
816 /* port is locked and active */
818 assert(port
->ip_sorights
> 0);
820 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
823 entry
->ie_object
= IO_NULL
;
824 ipc_entry_dealloc(space
, name
, entry
);
826 is_write_unlock(space
);
828 ipc_notify_send_once(port
);
830 if (dnrequest
!= IP_NULL
)
831 ipc_notify_port_deleted(dnrequest
, name
);
835 case MACH_PORT_TYPE_SEND
: {
837 ipc_port_t dnrequest
= IP_NULL
;
838 ipc_port_t nsrequest
= IP_NULL
;
839 mach_port_mscount_t mscount
= 0;
842 assert(IE_BITS_UREFS(bits
) > 0);
844 port
= (ipc_port_t
) entry
->ie_object
;
845 assert(port
!= IP_NULL
);
847 if (ipc_right_check(space
, port
, name
, entry
)) {
848 bits
= entry
->ie_bits
;
849 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
852 /* port is locked and active */
854 assert(port
->ip_srights
> 0);
856 if (IE_BITS_UREFS(bits
) == 1) {
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
;
865 dnrequest
= ipc_right_dncancel_macro(space
, port
,
867 ipc_hash_delete(space
, (ipc_object_t
) port
,
871 entry
->ie_object
= IO_NULL
;
872 ipc_entry_dealloc(space
, name
, entry
);
875 entry
->ie_bits
= bits
-1; /* decrement urefs */
877 /* even if dropped a ref, port is active */
879 is_write_unlock(space
);
881 if (nsrequest
!= IP_NULL
)
882 ipc_notify_no_senders(nsrequest
, mscount
);
884 if (dnrequest
!= IP_NULL
)
885 ipc_notify_port_deleted(dnrequest
, name
);
889 case MACH_PORT_TYPE_SEND_RECEIVE
: {
891 ipc_port_t nsrequest
= IP_NULL
;
892 mach_port_mscount_t mscount
= 0;
894 assert(IE_BITS_UREFS(bits
) > 0);
896 port
= (ipc_port_t
) entry
->ie_object
;
897 assert(port
!= IP_NULL
);
900 assert(ip_active(port
));
901 assert(port
->ip_receiver_name
== name
);
902 assert(port
->ip_receiver
== space
);
903 assert(port
->ip_srights
> 0);
905 if (IE_BITS_UREFS(bits
) == 1) {
906 if (--port
->ip_srights
== 0) {
907 nsrequest
= port
->ip_nsrequest
;
908 if (nsrequest
!= IP_NULL
) {
909 port
->ip_nsrequest
= IP_NULL
;
910 mscount
= port
->ip_mscount
;
914 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
915 MACH_PORT_TYPE_SEND
);
917 entry
->ie_bits
= bits
-1; /* decrement urefs */
920 is_write_unlock(space
);
922 if (nsrequest
!= IP_NULL
)
923 ipc_notify_no_senders(nsrequest
, mscount
);
928 is_write_unlock(space
);
929 return KERN_INVALID_RIGHT
;
936 * Routine: ipc_right_delta
938 * Modifies the user-reference count for a right.
939 * May deallocate the right, if the count goes to zero.
941 * The space is write-locked, and is unlocked upon return.
942 * The space must be active.
944 * KERN_SUCCESS Count was modified.
945 * KERN_INVALID_RIGHT Entry has wrong type.
946 * KERN_INVALID_VALUE Bad delta for the right.
947 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
953 mach_port_name_t name
,
955 mach_port_right_t right
,
956 mach_port_delta_t delta
)
958 ipc_entry_bits_t bits
;
960 bits
= entry
->ie_bits
;
964 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
965 * switch below. It is used to keep track of those cases (in DIPC)
966 * where we have postponed the dropping of a port reference. Since
967 * the dropping of the reference could cause the port to disappear
968 * we postpone doing so when we are holding the space lock.
971 assert(space
->is_active
);
972 assert(right
< MACH_PORT_RIGHT_NUMBER
);
974 /* Rights-specific restrictions and operations. */
977 case MACH_PORT_RIGHT_PORT_SET
: {
980 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
983 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
984 assert(IE_BITS_UREFS(bits
) == 0);
985 assert(entry
->ie_request
== 0);
993 pset
= (ipc_pset_t
) entry
->ie_object
;
994 assert(pset
!= IPS_NULL
);
998 entry
->ie_object
= IO_NULL
;
999 ipc_entry_dealloc(space
, name
, entry
);
1003 assert(ips_active(pset
));
1004 is_write_unlock(space
);
1006 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1010 case MACH_PORT_RIGHT_RECEIVE
: {
1012 ipc_port_t dnrequest
= IP_NULL
;
1014 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1023 port
= (ipc_port_t
) entry
->ie_object
;
1024 assert(port
!= IP_NULL
);
1027 * The port lock is needed for ipc_right_dncancel;
1028 * otherwise, we wouldn't have to take the lock
1029 * until just before dropping the space lock.
1033 assert(ip_active(port
));
1034 assert(port
->ip_receiver_name
== name
);
1035 assert(port
->ip_receiver
== space
);
1037 if (bits
& MACH_PORT_TYPE_SEND
) {
1038 assert(IE_BITS_TYPE(bits
) ==
1039 MACH_PORT_TYPE_SEND_RECEIVE
);
1040 assert(IE_BITS_UREFS(bits
) > 0);
1041 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1042 assert(port
->ip_srights
> 0);
1045 * The remaining send right turns into a
1046 * dead name. Notice we don't decrement
1047 * ip_srights, generate a no-senders notif,
1048 * or use ipc_right_dncancel, because the
1049 * port is destroyed "first".
1051 bits
&= ~IE_BITS_TYPE_MASK
;
1052 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1053 if (entry
->ie_request
) {
1054 entry
->ie_request
= 0;
1057 entry
->ie_bits
= bits
;
1058 entry
->ie_object
= IO_NULL
;
1060 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1061 assert(IE_BITS_UREFS(bits
) == 0);
1063 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1065 entry
->ie_object
= IO_NULL
;
1066 ipc_entry_dealloc(space
, name
, entry
);
1068 is_write_unlock(space
);
1070 ipc_port_clear_receiver(port
);
1071 ipc_port_destroy(port
); /* consumes ref, unlocks */
1073 if (dnrequest
!= IP_NULL
)
1074 ipc_notify_port_deleted(dnrequest
, name
);
1078 case MACH_PORT_RIGHT_SEND_ONCE
: {
1079 ipc_port_t port
, dnrequest
;
1081 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1084 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1085 assert(IE_BITS_UREFS(bits
) == 1);
1087 port
= (ipc_port_t
) entry
->ie_object
;
1088 assert(port
!= IP_NULL
);
1090 if (ipc_right_check(space
, port
, name
, entry
)) {
1091 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1094 /* port is locked and active */
1096 assert(port
->ip_sorights
> 0);
1098 if ((delta
> 0) || (delta
< -1)) {
1108 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1111 entry
->ie_object
= IO_NULL
;
1112 ipc_entry_dealloc(space
, name
, entry
);
1114 is_write_unlock(space
);
1116 ipc_notify_send_once(port
);
1118 if (dnrequest
!= IP_NULL
)
1119 ipc_notify_port_deleted(dnrequest
, name
);
1123 case MACH_PORT_RIGHT_DEAD_NAME
: {
1124 mach_port_urefs_t urefs
;
1126 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1129 port
= (ipc_port_t
) entry
->ie_object
;
1130 assert(port
!= IP_NULL
);
1132 if (!ipc_right_check(space
, port
, name
, entry
)) {
1133 /* port is locked and active */
1137 bits
= entry
->ie_bits
;
1138 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1141 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1142 assert(IE_BITS_UREFS(bits
) > 0);
1143 assert(entry
->ie_object
== IO_NULL
);
1144 assert(entry
->ie_request
== 0);
1146 urefs
= IE_BITS_UREFS(bits
);
1147 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1149 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1150 goto urefs_overflow
;
1152 if ((urefs
+ delta
) == 0) {
1153 ipc_entry_dealloc(space
, name
, entry
);
1156 entry
->ie_bits
= bits
+ delta
;
1158 is_write_unlock(space
);
1163 case MACH_PORT_RIGHT_SEND
: {
1164 mach_port_urefs_t urefs
;
1166 ipc_port_t dnrequest
= IP_NULL
;
1167 ipc_port_t nsrequest
= IP_NULL
;
1168 mach_port_mscount_t mscount
= 0;
1170 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1173 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1175 port
= (ipc_port_t
) entry
->ie_object
;
1176 assert(port
!= IP_NULL
);
1178 if (ipc_right_check(space
, port
, name
, entry
)) {
1179 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1182 /* port is locked and active */
1184 assert(port
->ip_srights
> 0);
1186 urefs
= IE_BITS_UREFS(bits
);
1187 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1191 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1193 goto urefs_overflow
;
1196 if ((urefs
+ delta
) == 0) {
1197 if (--port
->ip_srights
== 0) {
1198 nsrequest
= port
->ip_nsrequest
;
1199 if (nsrequest
!= IP_NULL
) {
1200 port
->ip_nsrequest
= IP_NULL
;
1201 mscount
= port
->ip_mscount
;
1205 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1206 assert(port
->ip_receiver_name
== name
);
1207 assert(port
->ip_receiver
== space
);
1208 assert(IE_BITS_TYPE(bits
) ==
1209 MACH_PORT_TYPE_SEND_RECEIVE
);
1211 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1212 MACH_PORT_TYPE_SEND
);
1214 assert(IE_BITS_TYPE(bits
) ==
1215 MACH_PORT_TYPE_SEND
);
1217 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1219 ipc_hash_delete(space
, (ipc_object_t
) port
,
1224 entry
->ie_object
= IO_NULL
;
1225 ipc_entry_dealloc(space
, name
, entry
);
1228 entry
->ie_bits
= bits
+ delta
;
1230 /* even if dropped a ref, port is active */
1232 is_write_unlock(space
);
1234 if (nsrequest
!= IP_NULL
)
1235 ipc_notify_no_senders(nsrequest
, mscount
);
1237 if (dnrequest
!= IP_NULL
)
1238 ipc_notify_port_deleted(dnrequest
, name
);
1243 panic("ipc_right_delta: strange right");
1246 return KERN_SUCCESS
;
1249 is_write_unlock(space
);
1250 return KERN_SUCCESS
;
1253 is_write_unlock(space
);
1254 return KERN_INVALID_RIGHT
;
1257 is_write_unlock(space
);
1258 return KERN_INVALID_VALUE
;
1261 is_write_unlock(space
);
1262 return KERN_UREFS_OVERFLOW
;
1266 * Routine: ipc_right_info
1268 * Retrieves information about the right.
1270 * The space is write-locked, and is unlocked upon return
1271 * if the call is unsuccessful. The space must be active.
1273 * KERN_SUCCESS Retrieved info; space still locked.
1279 mach_port_name_t name
,
1281 mach_port_type_t
*typep
,
1282 mach_port_urefs_t
*urefsp
)
1284 ipc_entry_bits_t bits
;
1285 mach_port_type_t type
;
1286 ipc_port_request_index_t request
;
1288 bits
= entry
->ie_bits
;
1290 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1291 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1293 if (ipc_right_check(space
, port
, name
, entry
)) {
1294 bits
= entry
->ie_bits
;
1295 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1300 type
= IE_BITS_TYPE(bits
);
1301 request
= entry
->ie_request
;
1304 type
|= MACH_PORT_TYPE_DNREQUEST
;
1307 *urefsp
= IE_BITS_UREFS(bits
);
1308 return KERN_SUCCESS
;
1312 * Routine: ipc_right_copyin_check
1314 * Check if a subsequent ipc_right_copyin would succeed.
1316 * The space is locked (read or write) and active.
1320 ipc_right_copyin_check(
1321 __assert_only ipc_space_t space
,
1322 __unused mach_port_name_t name
,
1324 mach_msg_type_name_t msgt_name
)
1326 ipc_entry_bits_t bits
;
1328 bits
= entry
->ie_bits
;
1329 assert(space
->is_active
);
1331 switch (msgt_name
) {
1332 case MACH_MSG_TYPE_MAKE_SEND
:
1333 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1334 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1335 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1340 case MACH_MSG_TYPE_COPY_SEND
:
1341 case MACH_MSG_TYPE_MOVE_SEND
:
1342 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1346 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1349 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1352 port
= (ipc_port_t
) entry
->ie_object
;
1353 assert(port
!= IP_NULL
);
1356 active
= ip_active(port
);
1363 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1364 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1367 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1375 panic("ipc_right_copyin_check: strange rights");
1382 * Routine: ipc_right_copyin
1384 * Copyin a capability from a space.
1385 * If successful, the caller gets a ref
1386 * for the resulting object, unless it is IO_DEAD,
1387 * and possibly a send-once right which should
1388 * be used in a port-deleted notification.
1390 * If deadok is not TRUE, the copyin operation
1391 * will fail instead of producing IO_DEAD.
1393 * The entry is never deallocated (except
1394 * when KERN_INVALID_NAME), so the caller
1395 * should deallocate the entry if its type
1396 * is MACH_PORT_TYPE_NONE.
1398 * The space is write-locked and active.
1400 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1401 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1407 mach_port_name_t name
,
1409 mach_msg_type_name_t msgt_name
,
1411 ipc_object_t
*objectp
,
1412 ipc_port_t
*sorightp
)
1414 ipc_entry_bits_t bits
;
1416 bits
= entry
->ie_bits
;
1418 assert(space
->is_active
);
1420 switch (msgt_name
) {
1421 case MACH_MSG_TYPE_MAKE_SEND
: {
1424 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1427 port
= (ipc_port_t
) entry
->ie_object
;
1428 assert(port
!= IP_NULL
);
1431 assert(ip_active(port
));
1432 assert(port
->ip_receiver_name
== name
);
1433 assert(port
->ip_receiver
== space
);
1440 *objectp
= (ipc_object_t
) port
;
1441 *sorightp
= IP_NULL
;
1445 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1448 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1451 port
= (ipc_port_t
) entry
->ie_object
;
1452 assert(port
!= IP_NULL
);
1455 assert(ip_active(port
));
1456 assert(port
->ip_receiver_name
== name
);
1457 assert(port
->ip_receiver
== space
);
1459 port
->ip_sorights
++;
1463 *objectp
= (ipc_object_t
) port
;
1464 *sorightp
= IP_NULL
;
1468 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1470 ipc_port_t dnrequest
= IP_NULL
;
1472 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1475 port
= (ipc_port_t
) entry
->ie_object
;
1476 assert(port
!= IP_NULL
);
1479 assert(ip_active(port
));
1480 assert(port
->ip_receiver_name
== name
);
1481 assert(port
->ip_receiver
== space
);
1483 if (bits
& MACH_PORT_TYPE_SEND
) {
1484 assert(IE_BITS_TYPE(bits
) ==
1485 MACH_PORT_TYPE_SEND_RECEIVE
);
1486 assert(IE_BITS_UREFS(bits
) > 0);
1487 assert(port
->ip_srights
> 0);
1489 ipc_hash_insert(space
, (ipc_object_t
) port
,
1493 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1494 assert(IE_BITS_UREFS(bits
) == 0);
1496 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1498 entry
->ie_object
= IO_NULL
;
1500 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1502 ipc_port_clear_receiver(port
);
1504 port
->ip_receiver_name
= MACH_PORT_NULL
;
1505 port
->ip_destination
= IP_NULL
;
1508 *objectp
= (ipc_object_t
) port
;
1509 *sorightp
= dnrequest
;
1513 case MACH_MSG_TYPE_COPY_SEND
: {
1516 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1519 /* allow for dead send-once rights */
1521 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1524 assert(IE_BITS_UREFS(bits
) > 0);
1526 port
= (ipc_port_t
) entry
->ie_object
;
1527 assert(port
!= IP_NULL
);
1529 if (ipc_right_check(space
, port
, name
, entry
)) {
1530 bits
= entry
->ie_bits
;
1533 /* port is locked and active */
1535 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1536 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1537 assert(port
->ip_sorights
> 0);
1543 assert(port
->ip_srights
> 0);
1549 *objectp
= (ipc_object_t
) port
;
1550 *sorightp
= IP_NULL
;
1554 case MACH_MSG_TYPE_MOVE_SEND
: {
1556 ipc_port_t dnrequest
= IP_NULL
;
1558 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1561 /* allow for dead send-once rights */
1563 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1566 assert(IE_BITS_UREFS(bits
) > 0);
1568 port
= (ipc_port_t
) entry
->ie_object
;
1569 assert(port
!= IP_NULL
);
1571 if (ipc_right_check(space
, port
, name
, entry
)) {
1572 bits
= entry
->ie_bits
;
1575 /* port is locked and active */
1577 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1578 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1579 assert(port
->ip_sorights
> 0);
1585 assert(port
->ip_srights
> 0);
1587 if (IE_BITS_UREFS(bits
) == 1) {
1588 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1589 assert(port
->ip_receiver_name
== name
);
1590 assert(port
->ip_receiver
== space
);
1591 assert(IE_BITS_TYPE(bits
) ==
1592 MACH_PORT_TYPE_SEND_RECEIVE
);
1596 assert(IE_BITS_TYPE(bits
) ==
1597 MACH_PORT_TYPE_SEND
);
1599 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1601 ipc_hash_delete(space
, (ipc_object_t
) port
,
1603 entry
->ie_object
= IO_NULL
;
1605 entry
->ie_bits
= bits
&~
1606 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1610 entry
->ie_bits
= bits
-1; /* decrement urefs */
1615 *objectp
= (ipc_object_t
) port
;
1616 *sorightp
= dnrequest
;
1620 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1622 ipc_port_t dnrequest
;
1624 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1627 /* allow for dead send rights */
1629 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1632 assert(IE_BITS_UREFS(bits
) > 0);
1634 port
= (ipc_port_t
) entry
->ie_object
;
1635 assert(port
!= IP_NULL
);
1637 if (ipc_right_check(space
, port
, name
, entry
)) {
1638 bits
= entry
->ie_bits
;
1641 /* port is locked and active */
1643 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1644 assert(bits
& MACH_PORT_TYPE_SEND
);
1645 assert(port
->ip_srights
> 0);
1651 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1652 assert(IE_BITS_UREFS(bits
) == 1);
1653 assert(port
->ip_sorights
> 0);
1655 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1658 entry
->ie_object
= IO_NULL
;
1659 entry
->ie_bits
= bits
&~
1660 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
1662 *objectp
= (ipc_object_t
) port
;
1663 *sorightp
= dnrequest
;
1669 return KERN_INVALID_RIGHT
;
1672 return KERN_SUCCESS
;
1675 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1676 assert(IE_BITS_UREFS(bits
) > 0);
1677 assert(entry
->ie_request
== 0);
1678 assert(entry
->ie_object
== 0);
1684 *sorightp
= IP_NULL
;
1685 return KERN_SUCCESS
;
1688 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1689 assert(IE_BITS_UREFS(bits
) > 0);
1690 assert(entry
->ie_request
== 0);
1691 assert(entry
->ie_object
== 0);
1696 if (IE_BITS_UREFS(bits
) == 1) {
1697 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
1699 entry
->ie_bits
= bits
-1; /* decrement urefs */
1702 *sorightp
= IP_NULL
;
1703 return KERN_SUCCESS
;
1708 * Routine: ipc_right_copyin_undo
1710 * Undoes the effects of an ipc_right_copyin
1711 * of a send/send-once right that is dead.
1712 * (Object is either IO_DEAD or a dead port.)
1714 * The space is write-locked and active.
1718 ipc_right_copyin_undo(
1720 mach_port_name_t name
,
1722 mach_msg_type_name_t msgt_name
,
1723 ipc_object_t object
,
1726 ipc_entry_bits_t bits
;
1728 bits
= entry
->ie_bits
;
1730 assert(space
->is_active
);
1732 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1733 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
1734 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1736 if (soright
!= IP_NULL
) {
1737 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1738 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1739 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1740 assert(object
!= IO_DEAD
);
1742 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1743 MACH_PORT_TYPE_DEAD_NAME
| 2);
1745 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
1746 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1747 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1749 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1750 MACH_PORT_TYPE_DEAD_NAME
| 1);
1751 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
1752 assert(object
== IO_DEAD
);
1753 assert(IE_BITS_UREFS(bits
) > 0);
1755 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1756 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1757 entry
->ie_bits
= bits
+1; /* increment urefs */
1760 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1761 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
1762 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1763 assert(object
!= IO_DEAD
);
1764 assert(entry
->ie_object
== object
);
1765 assert(IE_BITS_UREFS(bits
) > 0);
1767 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1768 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
1769 entry
->ie_bits
= bits
+1; /* increment urefs */
1773 * May as well convert the entry to a dead name.
1774 * (Or if it is a compat entry, destroy it.)
1777 (void) ipc_right_check(space
, (ipc_port_t
) object
,
1779 /* object is dead so it is not locked */
1782 /* release the reference acquired by copyin */
1784 if (object
!= IO_DEAD
)
1785 ipc_object_release(object
);
1789 * Routine: ipc_right_copyin_two
1791 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1792 * and deadok == FALSE, except that this moves two
1793 * send rights at once.
1795 * The space is write-locked and active.
1796 * The object is returned with two refs/send rights.
1798 * KERN_SUCCESS Acquired an object.
1799 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1803 ipc_right_copyin_two(
1805 mach_port_name_t name
,
1807 ipc_object_t
*objectp
,
1808 ipc_port_t
*sorightp
)
1810 ipc_entry_bits_t bits
;
1811 mach_port_urefs_t urefs
;
1813 ipc_port_t dnrequest
= IP_NULL
;
1815 assert(space
->is_active
);
1817 bits
= entry
->ie_bits
;
1819 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1822 urefs
= IE_BITS_UREFS(bits
);
1826 port
= (ipc_port_t
) entry
->ie_object
;
1827 assert(port
!= IP_NULL
);
1829 if (ipc_right_check(space
, port
, name
, entry
)) {
1832 /* port is locked and active */
1834 assert(port
->ip_srights
> 0);
1837 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1838 assert(port
->ip_receiver_name
== name
);
1839 assert(port
->ip_receiver
== space
);
1840 assert(IE_BITS_TYPE(bits
) ==
1841 MACH_PORT_TYPE_SEND_RECEIVE
);
1847 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1849 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1854 ipc_hash_delete(space
, (ipc_object_t
) port
,
1856 entry
->ie_object
= IO_NULL
;
1858 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1860 port
->ip_srights
+= 2;
1863 entry
->ie_bits
= bits
-2; /* decrement urefs */
1867 *objectp
= (ipc_object_t
) port
;
1868 *sorightp
= dnrequest
;
1869 return KERN_SUCCESS
;
1872 return KERN_INVALID_RIGHT
;
1876 * Routine: ipc_right_copyout
1878 * Copyout a capability to a space.
1879 * If successful, consumes a ref for the object.
1881 * Always succeeds when given a newly-allocated entry,
1882 * because user-reference overflow isn't a possibility.
1884 * If copying out the object would cause the user-reference
1885 * count in the entry to overflow, and overflow is TRUE,
1886 * then instead the user-reference count is left pegged
1887 * to its maximum value and the copyout succeeds anyway.
1889 * The space is write-locked and active.
1890 * The object is locked and active.
1891 * The object is unlocked; the space isn't.
1893 * KERN_SUCCESS Copied out capability.
1894 * KERN_UREFS_OVERFLOW User-refs would overflow;
1895 * guaranteed not to happen with a fresh entry
1896 * or if overflow=TRUE was specified.
1902 mach_port_name_t name
,
1904 mach_msg_type_name_t msgt_name
,
1906 ipc_object_t object
)
1908 ipc_entry_bits_t bits
;
1911 bits
= entry
->ie_bits
;
1913 assert(IO_VALID(object
));
1914 assert(io_otype(object
) == IOT_PORT
);
1915 assert(io_active(object
));
1916 assert(entry
->ie_object
== object
);
1918 port
= (ipc_port_t
) object
;
1920 switch (msgt_name
) {
1921 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
1923 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1924 assert(port
->ip_sorights
> 0);
1926 /* transfer send-once right and ref to entry */
1929 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
1932 case MACH_MSG_TYPE_PORT_SEND
:
1933 assert(port
->ip_srights
> 0);
1935 if (bits
& MACH_PORT_TYPE_SEND
) {
1936 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
1938 assert(port
->ip_srights
> 1);
1940 assert(urefs
< MACH_PORT_UREFS_MAX
);
1942 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
1944 /* leave urefs pegged to maximum */
1949 return KERN_SUCCESS
;
1953 return KERN_UREFS_OVERFLOW
;
1959 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1960 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1961 assert(IE_BITS_UREFS(bits
) == 0);
1963 /* transfer send right to entry */
1967 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1968 assert(IE_BITS_UREFS(bits
) == 0);
1970 /* transfer send right and ref to entry */
1973 /* entry is locked holding ref, so can use port */
1975 ipc_hash_insert(space
, (ipc_object_t
) port
,
1979 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
1982 case MACH_MSG_TYPE_PORT_RECEIVE
: {
1985 assert(port
->ip_mscount
== 0);
1986 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1987 dest
= port
->ip_destination
;
1989 port
->ip_receiver_name
= name
;
1990 port
->ip_receiver
= space
;
1992 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
1994 if (bits
& MACH_PORT_TYPE_SEND
) {
1995 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1996 assert(IE_BITS_UREFS(bits
) > 0);
1997 assert(port
->ip_srights
> 0);
2002 /* entry is locked holding ref, so can use port */
2004 ipc_hash_delete(space
, (ipc_object_t
) port
,
2007 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2008 assert(IE_BITS_UREFS(bits
) == 0);
2010 /* transfer ref to entry */
2013 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2015 if (dest
!= IP_NULL
)
2016 ipc_port_release(dest
);
2021 panic("ipc_right_copyout: strange rights");
2024 return KERN_SUCCESS
;
2028 * Routine: ipc_right_rename
2030 * Transfer an entry from one name to another.
2031 * The old entry is deallocated.
2033 * The space is write-locked and active.
2034 * The new entry is unused. Upon return,
2035 * the space is unlocked.
2037 * KERN_SUCCESS Moved entry to new name.
2043 mach_port_name_t oname
,
2045 mach_port_name_t nname
,
2048 ipc_port_request_index_t request
= oentry
->ie_request
;
2049 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2050 ipc_object_t object
= oentry
->ie_object
;
2052 assert(space
->is_active
);
2053 assert(oname
!= nname
);
2056 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2057 * if the port is dead. (This would foil ipc_port_destroy.)
2058 * Instead we should fail because oentry shouldn't exist.
2059 * Note IE_BITS_COMPAT implies ie_request != 0.
2065 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2066 port
= (ipc_port_t
) object
;
2067 assert(port
!= IP_NULL
);
2069 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2072 bits
= oentry
->ie_bits
;
2073 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2074 assert(oentry
->ie_request
== 0);
2076 /* port is locked and active */
2078 ipc_port_dnrename(port
, request
, oname
, nname
);
2080 oentry
->ie_request
= 0;
2084 /* initialize nentry before letting ipc_hash_insert see it */
2086 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2087 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2088 nentry
->ie_request
= request
;
2089 nentry
->ie_object
= object
;
2091 switch (IE_BITS_TYPE(bits
)) {
2092 case MACH_PORT_TYPE_SEND
: {
2095 port
= (ipc_port_t
) object
;
2096 assert(port
!= IP_NULL
);
2098 /* remember, there are no other share entries possible */
2099 /* or we can't do the rename. Therefore we do not need */
2100 /* to check the other subspaces */
2101 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2102 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2106 case MACH_PORT_TYPE_RECEIVE
:
2107 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2110 port
= (ipc_port_t
) object
;
2111 assert(port
!= IP_NULL
);
2114 assert(ip_active(port
));
2115 assert(port
->ip_receiver_name
== oname
);
2116 assert(port
->ip_receiver
== space
);
2118 port
->ip_receiver_name
= nname
;
2123 case MACH_PORT_TYPE_PORT_SET
: {
2126 pset
= (ipc_pset_t
) object
;
2127 assert(pset
!= IPS_NULL
);
2130 assert(ips_active(pset
));
2131 assert(pset
->ips_local_name
== oname
);
2133 pset
->ips_local_name
= nname
;
2138 case MACH_PORT_TYPE_SEND_ONCE
:
2139 case MACH_PORT_TYPE_DEAD_NAME
:
2143 panic("ipc_right_rename: strange rights");
2146 assert(oentry
->ie_request
== 0);
2147 oentry
->ie_object
= IO_NULL
;
2148 ipc_entry_dealloc(space
, oname
, oentry
);
2149 is_write_unlock(space
);
2151 return KERN_SUCCESS
;