2 * Copyright (c) 2002,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>
67 #include <ipc/ipc_entry.h>
68 #include <ipc/ipc_space.h>
69 #include <ipc/ipc_object.h>
70 #include <ipc/ipc_hash.h>
71 #include <ipc/ipc_port.h>
72 #include <ipc/ipc_pset.h>
73 #include <ipc/ipc_right.h>
74 #include <ipc/ipc_notify.h>
75 #include <ipc/ipc_table.h>
78 * Routine: ipc_right_lookup_write
80 * Finds an entry in a space, given the name.
82 * Nothing locked. If successful, the space is write-locked.
84 * KERN_SUCCESS Found an entry.
85 * KERN_INVALID_TASK The space is dead.
86 * KERN_INVALID_NAME Name doesn't exist in space.
90 ipc_right_lookup_write(
92 mach_port_name_t name
,
97 assert(space
!= IS_NULL
);
101 if (!space
->is_active
) {
102 is_write_unlock(space
);
103 return KERN_INVALID_TASK
;
106 if ((entry
= ipc_entry_lookup(space
, name
)) == IE_NULL
) {
107 is_write_unlock(space
);
108 return KERN_INVALID_NAME
;
116 * Routine: ipc_right_lookup_two_write
118 * Like ipc_right_lookup except that it returns two
119 * entries for two different names that were looked
120 * up under the same space lock.
122 * Nothing locked. If successful, the space is write-locked.
124 * KERN_INVALID_TASK The space is dead.
125 * KERN_INVALID_NAME Name doesn't exist in space.
129 ipc_right_lookup_two_write(
131 mach_port_name_t name1
,
132 ipc_entry_t
*entryp1
,
133 mach_port_name_t name2
,
134 ipc_entry_t
*entryp2
)
139 assert(space
!= IS_NULL
);
141 is_write_lock(space
);
143 if (!space
->is_active
) {
144 is_write_unlock(space
);
145 return KERN_INVALID_TASK
;
148 if ((entry1
= ipc_entry_lookup(space
, name1
)) == IE_NULL
) {
149 is_write_unlock(space
);
150 return KERN_INVALID_NAME
;
152 if ((entry2
= ipc_entry_lookup(space
, name2
)) == IE_NULL
) {
153 is_write_unlock(space
);
154 return KERN_INVALID_NAME
;
162 * Routine: ipc_right_reverse
164 * Translate (space, object) -> (name, entry).
165 * Only finds send/receive rights.
166 * Returns TRUE if an entry is found; if so,
167 * the object is locked and active.
169 * The space must be locked (read or write) and active.
170 * Nothing else locked.
177 mach_port_name_t
*namep
,
181 mach_port_name_t name
;
184 /* would switch on io_otype to handle multiple types of object */
186 assert(space
->is_active
);
187 assert(io_otype(object
) == IOT_PORT
);
189 port
= (ipc_port_t
) object
;
192 if (!ip_active(port
)) {
198 if (port
->ip_receiver
== space
) {
199 name
= port
->ip_receiver_name
;
200 assert(name
!= MACH_PORT_NULL
);
202 entry
= ipc_entry_lookup(space
, name
);
204 assert(entry
!= IE_NULL
);
205 assert(entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
);
206 assert(port
== (ipc_port_t
) entry
->ie_object
);
213 if (ipc_hash_lookup(space
, (ipc_object_t
) port
, namep
, entryp
)) {
214 assert((entry
= *entryp
) != IE_NULL
);
215 assert(IE_BITS_TYPE(entry
->ie_bits
) == MACH_PORT_TYPE_SEND
);
216 assert(port
== (ipc_port_t
) entry
->ie_object
);
226 * Routine: ipc_right_dnrequest
228 * Make a dead-name request, returning the previously
229 * registered send-once right. If notify is IP_NULL,
230 * just cancels the previously registered request.
232 * This interacts with the IE_BITS_COMPAT, because they
233 * both use ie_request. If this is a compat entry, then
234 * previous always gets IP_NULL. If notify is IP_NULL,
235 * then the entry remains a compat entry. Otherwise
236 * the real dead-name request is registered and the entry
237 * is no longer a compat entry.
239 * Nothing locked. May allocate memory.
240 * Only consumes/returns refs if successful.
242 * KERN_SUCCESS Made/canceled dead-name request.
243 * KERN_INVALID_TASK The space is dead.
244 * KERN_INVALID_NAME Name doesn't exist in space.
245 * KERN_INVALID_RIGHT Name doesn't denote port/dead rights.
246 * KERN_INVALID_ARGUMENT Name denotes dead name, but
247 * immediate is FALSE or notify is IP_NULL.
248 * KERN_UREFS_OVERFLOW Name denotes dead name, but
249 * generating immediate notif. would overflow urefs.
250 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
256 mach_port_name_t name
,
259 ipc_port_t
*previousp
)
265 ipc_entry_bits_t bits
;
268 kr
= ipc_right_lookup_write(space
, name
, &entry
);
269 if (kr
!= KERN_SUCCESS
)
271 /* space is write-locked and active */
272 bits
= entry
->ie_bits
;
273 if (bits
& MACH_PORT_TYPE_PORT_RIGHTS
) {
275 ipc_port_request_index_t request
;
277 port
= (ipc_port_t
) entry
->ie_object
;
278 assert(port
!= IP_NULL
);
280 if (!ipc_right_check(space
, port
, name
, entry
)) {
281 /* port is locked and active */
283 if (notify
== IP_NULL
) {
284 previous
= ipc_right_dncancel_macro(
285 space
, port
, name
, entry
);
288 is_write_unlock(space
);
293 * If a registered soright exists,
294 * want to atomically switch with it.
295 * If ipc_port_dncancel finds us a
296 * soright, then the following
297 * ipc_port_dnrequest will reuse
298 * that slot, so we are guaranteed
299 * not to unlock and retry.
302 previous
= ipc_right_dncancel_macro(space
,
305 kr
= ipc_port_dnrequest(port
, name
, notify
,
307 if (kr
!= KERN_SUCCESS
) {
308 assert(previous
== IP_NULL
);
309 is_write_unlock(space
);
311 kr
= ipc_port_dngrow(port
,
313 /* port is unlocked */
314 if (kr
!= KERN_SUCCESS
)
320 assert(request
!= 0);
323 entry
->ie_request
= request
;
324 is_write_unlock(space
);
329 * Our capability bits were changed by ipc_right_check
330 * because it found an inactive port and removed our
331 * references to it (converting our entry into a dead
332 * one). Reload the bits (and obviously we can't use
333 * the port name anymore).
335 bits
= entry
->ie_bits
;
339 assert(bits
& MACH_PORT_TYPE_DEAD_NAME
);
342 if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) &&
343 immediate
&& (notify
!= IP_NULL
)) {
344 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
346 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
349 if (MACH_PORT_UREFS_OVERFLOW(urefs
, 1)) {
350 is_write_unlock(space
);
351 return KERN_UREFS_OVERFLOW
;
354 (entry
->ie_bits
)++; /* increment urefs */
355 is_write_unlock(space
);
357 ipc_notify_dead_name(notify
, name
);
362 is_write_unlock(space
);
363 if (bits
& MACH_PORT_TYPE_PORT_OR_DEAD
)
364 return KERN_INVALID_ARGUMENT
;
366 return KERN_INVALID_RIGHT
;
369 *previousp
= previous
;
374 * Routine: ipc_right_dncancel
376 * Cancel a dead-name request and return the send-once right.
377 * Afterwards, entry->ie_request == 0.
379 * The space must be write-locked; the port must be locked.
380 * The port must be active; the space doesn't have to be.
387 mach_port_name_t name
,
390 ipc_port_t dnrequest
;
392 assert(ip_active(port
));
393 assert(port
== (ipc_port_t
) entry
->ie_object
);
395 dnrequest
= ipc_port_dncancel(port
, name
, entry
->ie_request
);
396 entry
->ie_request
= 0;
402 * Routine: ipc_right_inuse
404 * Check if an entry is being used.
405 * Returns TRUE if it is.
407 * The space is write-locked and active.
408 * It is unlocked if the entry is inuse.
414 mach_port_name_t name
,
417 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_NONE
) {
418 is_write_unlock(space
);
425 * Routine: ipc_right_check
427 * Check if the port has died. If it has,
428 * clean up the entry and return TRUE.
430 * The space is write-locked; the port is not locked.
431 * If returns FALSE, the port is also locked and active.
432 * Otherwise, entry is converted to a dead name, freeing
433 * a reference to port.
440 mach_port_name_t name
,
443 ipc_entry_bits_t bits
;
445 assert(space
->is_active
);
446 assert(port
== (ipc_port_t
) entry
->ie_object
);
453 /* this was either a pure send right or a send-once right */
455 bits
= entry
->ie_bits
;
456 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
457 assert(IE_BITS_UREFS(bits
) > 0);
459 if (bits
& MACH_PORT_TYPE_SEND
) {
460 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
462 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
463 assert(IE_BITS_UREFS(bits
) == 1);
467 ipc_port_release(port
);
469 /* convert entry to dead name */
471 if ((bits
& MACH_PORT_TYPE_SEND
) && !(bits
& MACH_PORT_TYPE_RECEIVE
))
472 ipc_hash_delete(space
, (ipc_object_t
)port
, name
, entry
);
474 bits
= (bits
&~ IE_BITS_TYPE_MASK
) | MACH_PORT_TYPE_DEAD_NAME
;
477 * If there was a notification request outstanding on this
478 * name, and since the port went dead, that notification
479 * must already be on its way up from the port layer. We
480 * don't need the index of the notification port anymore.
482 * JMM - We also add a reference to the entry since the
483 * notification only carries the name and NOT a reference
484 * (or right). This makes for pretty loose reference
485 * counting, since it is only happenstance that we
486 * detected the notification in progress like this.
487 * But most (all?) calls that try to deal with this entry
488 * will also come through here, so the reference gets added
489 * before the entry gets used eventually (I would rather it
490 * be explicit in the notification generation, though)
492 if (entry
->ie_request
!= 0) {
493 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
494 entry
->ie_request
= 0;
497 entry
->ie_bits
= bits
;
498 entry
->ie_object
= IO_NULL
;
503 * Routine: ipc_right_clean
505 * Cleans up an entry in a dead space.
506 * The entry isn't deallocated or removed
507 * from reverse hash tables.
509 * The space is dead and unlocked.
515 mach_port_name_t name
,
518 ipc_entry_bits_t bits
;
519 mach_port_type_t type
;
521 bits
= entry
->ie_bits
;
522 type
= IE_BITS_TYPE(bits
);
524 assert(!space
->is_active
);
527 * IE_BITS_COMPAT/ipc_right_dncancel doesn't have this
528 * problem, because we check that the port is active. If
529 * we didn't cancel IE_BITS_COMPAT, ipc_port_destroy
530 * would still work, but dead space refs would accumulate
531 * in ip_dnrequests. They would use up slots in
532 * ip_dnrequests and keep the spaces from being freed.
536 case MACH_PORT_TYPE_DEAD_NAME
:
537 assert(entry
->ie_request
== 0);
538 assert(entry
->ie_object
== IO_NULL
);
541 case MACH_PORT_TYPE_PORT_SET
: {
542 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
544 assert(entry
->ie_request
== 0);
545 assert(pset
!= IPS_NULL
);
548 assert(ips_active(pset
));
550 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
554 case MACH_PORT_TYPE_SEND
:
555 case MACH_PORT_TYPE_RECEIVE
:
556 case MACH_PORT_TYPE_SEND_RECEIVE
:
557 case MACH_PORT_TYPE_SEND_ONCE
: {
558 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
559 ipc_port_t dnrequest
;
560 ipc_port_t nsrequest
= IP_NULL
;
561 mach_port_mscount_t mscount
;
563 assert(port
!= IP_NULL
);
566 if (!ip_active(port
)) {
568 ip_check_unlock(port
);
572 dnrequest
= ipc_right_dncancel_macro(space
, port
,
575 if (type
& MACH_PORT_TYPE_SEND
) {
576 assert(port
->ip_srights
> 0);
577 if (--port
->ip_srights
== 0
579 nsrequest
= port
->ip_nsrequest
;
580 if (nsrequest
!= IP_NULL
) {
581 port
->ip_nsrequest
= IP_NULL
;
582 mscount
= port
->ip_mscount
;
587 if (type
& MACH_PORT_TYPE_RECEIVE
) {
588 assert(port
->ip_receiver_name
== name
);
589 assert(port
->ip_receiver
== space
);
591 ipc_port_clear_receiver(port
);
592 ipc_port_destroy(port
); /* consumes our ref, unlocks */
593 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
594 assert(port
->ip_sorights
> 0);
597 ipc_notify_send_once(port
); /* consumes our ref */
599 assert(port
->ip_receiver
!= space
);
602 ip_unlock(port
); /* port is active */
605 if (nsrequest
!= IP_NULL
)
606 ipc_notify_no_senders(nsrequest
, mscount
);
608 if (dnrequest
!= IP_NULL
)
609 ipc_notify_port_deleted(dnrequest
, name
);
614 panic("ipc_right_clean: strange type");
619 * Routine: ipc_right_destroy
621 * Destroys an entry in a space.
623 * The space is write-locked.
624 * The space must be active.
626 * KERN_SUCCESS The entry was destroyed.
632 mach_port_name_t name
,
635 ipc_entry_bits_t bits
;
636 mach_port_type_t type
;
638 bits
= entry
->ie_bits
;
639 entry
->ie_bits
&= ~IE_BITS_TYPE_MASK
;
640 type
= IE_BITS_TYPE(bits
);
642 assert(space
->is_active
);
645 case MACH_PORT_TYPE_DEAD_NAME
:
646 assert(entry
->ie_request
== 0);
647 assert(entry
->ie_object
== IO_NULL
);
649 ipc_entry_dealloc(space
, name
, entry
);
652 case MACH_PORT_TYPE_PORT_SET
: {
653 ipc_pset_t pset
= (ipc_pset_t
) entry
->ie_object
;
655 assert(entry
->ie_request
== 0);
656 assert(pset
!= IPS_NULL
);
658 entry
->ie_object
= IO_NULL
;
659 ipc_entry_dealloc(space
, name
, entry
);
662 assert(ips_active(pset
));
664 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
668 case MACH_PORT_TYPE_SEND
:
669 case MACH_PORT_TYPE_RECEIVE
:
670 case MACH_PORT_TYPE_SEND_RECEIVE
:
671 case MACH_PORT_TYPE_SEND_ONCE
: {
672 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
673 ipc_port_t nsrequest
= IP_NULL
;
674 mach_port_mscount_t mscount
;
675 ipc_port_t dnrequest
;
677 assert(port
!= IP_NULL
);
679 if (type
== MACH_PORT_TYPE_SEND
)
680 ipc_hash_delete(space
, (ipc_object_t
) port
,
685 if (!ip_active(port
)) {
686 assert((type
& MACH_PORT_TYPE_RECEIVE
) == 0);
688 ip_check_unlock(port
);
690 entry
->ie_request
= 0;
691 entry
->ie_object
= IO_NULL
;
692 ipc_entry_dealloc(space
, name
, entry
);
697 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
699 entry
->ie_object
= IO_NULL
;
700 ipc_entry_dealloc(space
, name
, entry
);
702 if (type
& MACH_PORT_TYPE_SEND
) {
703 assert(port
->ip_srights
> 0);
704 if (--port
->ip_srights
== 0) {
705 nsrequest
= port
->ip_nsrequest
;
706 if (nsrequest
!= IP_NULL
) {
707 port
->ip_nsrequest
= IP_NULL
;
708 mscount
= port
->ip_mscount
;
713 if (type
& MACH_PORT_TYPE_RECEIVE
) {
714 assert(ip_active(port
));
715 assert(port
->ip_receiver
== space
);
717 ipc_port_clear_receiver(port
);
718 ipc_port_destroy(port
); /* consumes our ref, unlocks */
719 } else if (type
& MACH_PORT_TYPE_SEND_ONCE
) {
720 assert(port
->ip_sorights
> 0);
723 ipc_notify_send_once(port
); /* consumes our ref */
725 assert(port
->ip_receiver
!= space
);
731 if (nsrequest
!= IP_NULL
)
732 ipc_notify_no_senders(nsrequest
, mscount
);
734 if (dnrequest
!= IP_NULL
)
735 ipc_notify_port_deleted(dnrequest
, name
);
740 panic("ipc_right_destroy: strange type");
747 * Routine: ipc_right_dealloc
749 * Releases a send/send-once/dead-name user ref.
750 * Like ipc_right_delta with a delta of -1,
751 * but looks at the entry to determine the right.
753 * The space is write-locked, and is unlocked upon return.
754 * The space must be active.
756 * KERN_SUCCESS A user ref was released.
757 * KERN_INVALID_RIGHT Entry has wrong type.
763 mach_port_name_t name
,
767 ipc_entry_bits_t bits
;
768 mach_port_type_t type
;
770 bits
= entry
->ie_bits
;
771 type
= IE_BITS_TYPE(bits
);
774 assert(space
->is_active
);
777 case MACH_PORT_TYPE_DEAD_NAME
: {
780 assert(IE_BITS_UREFS(bits
) > 0);
781 assert(entry
->ie_request
== 0);
782 assert(entry
->ie_object
== IO_NULL
);
784 if (IE_BITS_UREFS(bits
) == 1) {
785 ipc_entry_dealloc(space
, name
, entry
);
788 entry
->ie_bits
= bits
-1; /* decrement urefs */
790 is_write_unlock(space
);
794 case MACH_PORT_TYPE_SEND_ONCE
: {
795 ipc_port_t port
, dnrequest
;
797 assert(IE_BITS_UREFS(bits
) == 1);
799 port
= (ipc_port_t
) entry
->ie_object
;
800 assert(port
!= IP_NULL
);
802 if (ipc_right_check(space
, port
, name
, entry
)) {
804 bits
= entry
->ie_bits
;
805 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
808 /* port is locked and active */
810 assert(port
->ip_sorights
> 0);
812 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
815 entry
->ie_object
= IO_NULL
;
816 ipc_entry_dealloc(space
, name
, entry
);
818 is_write_unlock(space
);
820 ipc_notify_send_once(port
);
822 if (dnrequest
!= IP_NULL
)
823 ipc_notify_port_deleted(dnrequest
, name
);
827 case MACH_PORT_TYPE_SEND
: {
829 ipc_port_t dnrequest
= IP_NULL
;
830 ipc_port_t nsrequest
= IP_NULL
;
831 mach_port_mscount_t mscount
;
834 assert(IE_BITS_UREFS(bits
) > 0);
836 port
= (ipc_port_t
) entry
->ie_object
;
837 assert(port
!= IP_NULL
);
839 if (ipc_right_check(space
, port
, name
, entry
)) {
840 bits
= entry
->ie_bits
;
841 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
844 /* port is locked and active */
846 assert(port
->ip_srights
> 0);
848 if (IE_BITS_UREFS(bits
) == 1) {
849 if (--port
->ip_srights
== 0) {
850 nsrequest
= port
->ip_nsrequest
;
851 if (nsrequest
!= IP_NULL
) {
852 port
->ip_nsrequest
= IP_NULL
;
853 mscount
= port
->ip_mscount
;
857 dnrequest
= ipc_right_dncancel_macro(space
, port
,
859 ipc_hash_delete(space
, (ipc_object_t
) port
,
863 entry
->ie_object
= IO_NULL
;
864 ipc_entry_dealloc(space
, name
, entry
);
867 entry
->ie_bits
= bits
-1; /* decrement urefs */
869 /* even if dropped a ref, port is active */
871 is_write_unlock(space
);
873 if (nsrequest
!= IP_NULL
)
874 ipc_notify_no_senders(nsrequest
, mscount
);
876 if (dnrequest
!= IP_NULL
)
877 ipc_notify_port_deleted(dnrequest
, name
);
881 case MACH_PORT_TYPE_SEND_RECEIVE
: {
883 ipc_port_t nsrequest
= IP_NULL
;
884 mach_port_mscount_t mscount
;
886 assert(IE_BITS_UREFS(bits
) > 0);
888 port
= (ipc_port_t
) entry
->ie_object
;
889 assert(port
!= IP_NULL
);
892 assert(ip_active(port
));
893 assert(port
->ip_receiver_name
== name
);
894 assert(port
->ip_receiver
== space
);
895 assert(port
->ip_srights
> 0);
897 if (IE_BITS_UREFS(bits
) == 1) {
898 if (--port
->ip_srights
== 0) {
899 nsrequest
= port
->ip_nsrequest
;
900 if (nsrequest
!= IP_NULL
) {
901 port
->ip_nsrequest
= IP_NULL
;
902 mscount
= port
->ip_mscount
;
906 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
907 MACH_PORT_TYPE_SEND
);
909 entry
->ie_bits
= bits
-1; /* decrement urefs */
912 is_write_unlock(space
);
914 if (nsrequest
!= IP_NULL
)
915 ipc_notify_no_senders(nsrequest
, mscount
);
920 is_write_unlock(space
);
921 return KERN_INVALID_RIGHT
;
928 * Routine: ipc_right_delta
930 * Modifies the user-reference count for a right.
931 * May deallocate the right, if the count goes to zero.
933 * The space is write-locked, and is unlocked upon return.
934 * The space must be active.
936 * KERN_SUCCESS Count was modified.
937 * KERN_INVALID_RIGHT Entry has wrong type.
938 * KERN_INVALID_VALUE Bad delta for the right.
939 * KERN_UREFS_OVERFLOW OK delta, except would overflow.
945 mach_port_name_t name
,
947 mach_port_right_t right
,
948 mach_port_delta_t delta
)
950 ipc_entry_bits_t bits
;
952 bits
= entry
->ie_bits
;
956 * The following is used (for case MACH_PORT_RIGHT_DEAD_NAME) in the
957 * switch below. It is used to keep track of those cases (in DIPC)
958 * where we have postponed the dropping of a port reference. Since
959 * the dropping of the reference could cause the port to disappear
960 * we postpone doing so when we are holding the space lock.
963 assert(space
->is_active
);
964 assert(right
< MACH_PORT_RIGHT_NUMBER
);
966 /* Rights-specific restrictions and operations. */
969 case MACH_PORT_RIGHT_PORT_SET
: {
972 if ((bits
& MACH_PORT_TYPE_PORT_SET
) == 0)
975 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_PORT_SET
);
976 assert(IE_BITS_UREFS(bits
) == 0);
977 assert(entry
->ie_request
== 0);
985 pset
= (ipc_pset_t
) entry
->ie_object
;
986 assert(pset
!= IPS_NULL
);
990 entry
->ie_object
= IO_NULL
;
991 ipc_entry_dealloc(space
, name
, entry
);
995 assert(ips_active(pset
));
996 is_write_unlock(space
);
998 ipc_pset_destroy(pset
); /* consumes ref, unlocks */
1002 case MACH_PORT_RIGHT_RECEIVE
: {
1004 ipc_port_t dnrequest
= IP_NULL
;
1006 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1015 port
= (ipc_port_t
) entry
->ie_object
;
1016 assert(port
!= IP_NULL
);
1019 * The port lock is needed for ipc_right_dncancel;
1020 * otherwise, we wouldn't have to take the lock
1021 * until just before dropping the space lock.
1025 assert(ip_active(port
));
1026 assert(port
->ip_receiver_name
== name
);
1027 assert(port
->ip_receiver
== space
);
1029 if (bits
& MACH_PORT_TYPE_SEND
) {
1030 assert(IE_BITS_TYPE(bits
) ==
1031 MACH_PORT_TYPE_SEND_RECEIVE
);
1032 assert(IE_BITS_UREFS(bits
) > 0);
1033 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1034 assert(port
->ip_srights
> 0);
1037 * The remaining send right turns into a
1038 * dead name. Notice we don't decrement
1039 * ip_srights, generate a no-senders notif,
1040 * or use ipc_right_dncancel, because the
1041 * port is destroyed "first".
1043 bits
&= ~IE_BITS_TYPE_MASK
;
1044 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
1045 if (entry
->ie_request
) {
1046 entry
->ie_request
= 0;
1049 entry
->ie_bits
= bits
;
1050 entry
->ie_object
= IO_NULL
;
1052 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1053 assert(IE_BITS_UREFS(bits
) == 0);
1055 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1057 entry
->ie_object
= IO_NULL
;
1058 ipc_entry_dealloc(space
, name
, entry
);
1060 is_write_unlock(space
);
1062 ipc_port_clear_receiver(port
);
1063 ipc_port_destroy(port
); /* consumes ref, unlocks */
1065 if (dnrequest
!= IP_NULL
)
1066 ipc_notify_port_deleted(dnrequest
, name
);
1070 case MACH_PORT_RIGHT_SEND_ONCE
: {
1071 ipc_port_t port
, dnrequest
;
1073 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1076 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1077 assert(IE_BITS_UREFS(bits
) == 1);
1079 port
= (ipc_port_t
) entry
->ie_object
;
1080 assert(port
!= IP_NULL
);
1082 if (ipc_right_check(space
, port
, name
, entry
)) {
1083 assert(!(entry
->ie_bits
& MACH_PORT_TYPE_SEND_ONCE
));
1086 /* port is locked and active */
1088 assert(port
->ip_sorights
> 0);
1090 if ((delta
> 0) || (delta
< -1)) {
1100 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1103 entry
->ie_object
= IO_NULL
;
1104 ipc_entry_dealloc(space
, name
, entry
);
1106 is_write_unlock(space
);
1108 ipc_notify_send_once(port
);
1110 if (dnrequest
!= IP_NULL
)
1111 ipc_notify_port_deleted(dnrequest
, name
);
1115 case MACH_PORT_RIGHT_DEAD_NAME
: {
1116 mach_port_urefs_t urefs
;
1118 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1121 port
= (ipc_port_t
) entry
->ie_object
;
1122 assert(port
!= IP_NULL
);
1124 if (!ipc_right_check(space
, port
, name
, entry
)) {
1125 /* port is locked and active */
1129 bits
= entry
->ie_bits
;
1130 } else if ((bits
& MACH_PORT_TYPE_DEAD_NAME
) == 0)
1133 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1134 assert(IE_BITS_UREFS(bits
) > 0);
1135 assert(entry
->ie_object
== IO_NULL
);
1136 assert(entry
->ie_request
== 0);
1138 urefs
= IE_BITS_UREFS(bits
);
1139 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
))
1141 if (MACH_PORT_UREFS_OVERFLOW(urefs
, delta
))
1142 goto urefs_overflow
;
1144 if ((urefs
+ delta
) == 0) {
1145 ipc_entry_dealloc(space
, name
, entry
);
1148 entry
->ie_bits
= bits
+ delta
;
1150 is_write_unlock(space
);
1155 case MACH_PORT_RIGHT_SEND
: {
1156 mach_port_urefs_t urefs
;
1158 ipc_port_t dnrequest
= IP_NULL
;
1159 ipc_port_t nsrequest
= IP_NULL
;
1160 mach_port_mscount_t mscount
;
1162 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1165 /* maximum urefs for send is MACH_PORT_UREFS_MAX-1 */
1167 port
= (ipc_port_t
) entry
->ie_object
;
1168 assert(port
!= IP_NULL
);
1170 if (ipc_right_check(space
, port
, name
, entry
)) {
1171 assert((entry
->ie_bits
& MACH_PORT_TYPE_SEND
) == 0);
1174 /* port is locked and active */
1176 assert(port
->ip_srights
> 0);
1178 urefs
= IE_BITS_UREFS(bits
);
1179 if (MACH_PORT_UREFS_UNDERFLOW(urefs
, delta
)) {
1183 if (MACH_PORT_UREFS_OVERFLOW(urefs
+1, delta
)) {
1185 goto urefs_overflow
;
1188 if ((urefs
+ delta
) == 0) {
1189 if (--port
->ip_srights
== 0) {
1190 nsrequest
= port
->ip_nsrequest
;
1191 if (nsrequest
!= IP_NULL
) {
1192 port
->ip_nsrequest
= IP_NULL
;
1193 mscount
= port
->ip_mscount
;
1197 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1198 assert(port
->ip_receiver_name
== name
);
1199 assert(port
->ip_receiver
== space
);
1200 assert(IE_BITS_TYPE(bits
) ==
1201 MACH_PORT_TYPE_SEND_RECEIVE
);
1203 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|
1204 MACH_PORT_TYPE_SEND
);
1206 assert(IE_BITS_TYPE(bits
) ==
1207 MACH_PORT_TYPE_SEND
);
1209 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1211 ipc_hash_delete(space
, (ipc_object_t
) port
,
1216 entry
->ie_object
= IO_NULL
;
1217 ipc_entry_dealloc(space
, name
, entry
);
1220 entry
->ie_bits
= bits
+ delta
;
1222 /* even if dropped a ref, port is active */
1224 is_write_unlock(space
);
1226 if (nsrequest
!= IP_NULL
)
1227 ipc_notify_no_senders(nsrequest
, mscount
);
1229 if (dnrequest
!= IP_NULL
)
1230 ipc_notify_port_deleted(dnrequest
, name
);
1235 panic("ipc_right_delta: strange right");
1238 return KERN_SUCCESS
;
1241 is_write_unlock(space
);
1242 return KERN_SUCCESS
;
1245 is_write_unlock(space
);
1246 return KERN_INVALID_RIGHT
;
1249 is_write_unlock(space
);
1250 return KERN_INVALID_VALUE
;
1253 is_write_unlock(space
);
1254 return KERN_UREFS_OVERFLOW
;
1258 * Routine: ipc_right_info
1260 * Retrieves information about the right.
1262 * The space is write-locked, and is unlocked upon return
1263 * if the call is unsuccessful. The space must be active.
1265 * KERN_SUCCESS Retrieved info; space still locked.
1271 mach_port_name_t name
,
1273 mach_port_type_t
*typep
,
1274 mach_port_urefs_t
*urefsp
)
1276 ipc_entry_bits_t bits
;
1277 mach_port_type_t type
;
1278 ipc_port_request_index_t request
;
1280 bits
= entry
->ie_bits
;
1282 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
1283 ipc_port_t port
= (ipc_port_t
) entry
->ie_object
;
1285 if (ipc_right_check(space
, port
, name
, entry
)) {
1286 bits
= entry
->ie_bits
;
1287 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1292 type
= IE_BITS_TYPE(bits
);
1293 request
= entry
->ie_request
;
1296 type
|= MACH_PORT_TYPE_DNREQUEST
;
1299 *urefsp
= IE_BITS_UREFS(bits
);
1300 return KERN_SUCCESS
;
1304 * Routine: ipc_right_copyin_check
1306 * Check if a subsequent ipc_right_copyin would succeed.
1308 * The space is locked (read or write) and active.
1312 ipc_right_copyin_check(
1314 mach_port_name_t name
,
1316 mach_msg_type_name_t msgt_name
)
1318 ipc_entry_bits_t bits
;
1320 bits
= entry
->ie_bits
;
1321 assert(space
->is_active
);
1323 switch (msgt_name
) {
1324 case MACH_MSG_TYPE_MAKE_SEND
:
1325 case MACH_MSG_TYPE_MAKE_SEND_ONCE
:
1326 case MACH_MSG_TYPE_MOVE_RECEIVE
:
1327 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1332 case MACH_MSG_TYPE_COPY_SEND
:
1333 case MACH_MSG_TYPE_MOVE_SEND
:
1334 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1338 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1341 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1344 port
= (ipc_port_t
) entry
->ie_object
;
1345 assert(port
!= IP_NULL
);
1348 active
= ip_active(port
);
1355 if (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
) {
1356 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0)
1359 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1367 panic("ipc_right_copyin_check: strange rights");
1374 * Routine: ipc_right_copyin
1376 * Copyin a capability from a space.
1377 * If successful, the caller gets a ref
1378 * for the resulting object, unless it is IO_DEAD,
1379 * and possibly a send-once right which should
1380 * be used in a port-deleted notification.
1382 * If deadok is not TRUE, the copyin operation
1383 * will fail instead of producing IO_DEAD.
1385 * The entry is never deallocated (except
1386 * when KERN_INVALID_NAME), so the caller
1387 * should deallocate the entry if its type
1388 * is MACH_PORT_TYPE_NONE.
1390 * The space is write-locked and active.
1392 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
1393 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1399 mach_port_name_t name
,
1401 mach_msg_type_name_t msgt_name
,
1403 ipc_object_t
*objectp
,
1404 ipc_port_t
*sorightp
)
1406 ipc_entry_bits_t bits
;
1408 bits
= entry
->ie_bits
;
1410 assert(space
->is_active
);
1412 switch (msgt_name
) {
1413 case MACH_MSG_TYPE_MAKE_SEND
: {
1416 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1419 port
= (ipc_port_t
) entry
->ie_object
;
1420 assert(port
!= IP_NULL
);
1423 assert(ip_active(port
));
1424 assert(port
->ip_receiver_name
== name
);
1425 assert(port
->ip_receiver
== space
);
1432 *objectp
= (ipc_object_t
) port
;
1433 *sorightp
= IP_NULL
;
1437 case MACH_MSG_TYPE_MAKE_SEND_ONCE
: {
1440 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1443 port
= (ipc_port_t
) entry
->ie_object
;
1444 assert(port
!= IP_NULL
);
1447 assert(ip_active(port
));
1448 assert(port
->ip_receiver_name
== name
);
1449 assert(port
->ip_receiver
== space
);
1451 port
->ip_sorights
++;
1455 *objectp
= (ipc_object_t
) port
;
1456 *sorightp
= IP_NULL
;
1460 case MACH_MSG_TYPE_MOVE_RECEIVE
: {
1462 ipc_port_t dnrequest
= IP_NULL
;
1464 if ((bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
1467 port
= (ipc_port_t
) entry
->ie_object
;
1468 assert(port
!= IP_NULL
);
1471 assert(ip_active(port
));
1472 assert(port
->ip_receiver_name
== name
);
1473 assert(port
->ip_receiver
== space
);
1475 if (bits
& MACH_PORT_TYPE_SEND
) {
1476 assert(IE_BITS_TYPE(bits
) ==
1477 MACH_PORT_TYPE_SEND_RECEIVE
);
1478 assert(IE_BITS_UREFS(bits
) > 0);
1479 assert(port
->ip_srights
> 0);
1481 ipc_hash_insert(space
, (ipc_object_t
) port
,
1485 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1486 assert(IE_BITS_UREFS(bits
) == 0);
1488 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1490 entry
->ie_object
= IO_NULL
;
1492 entry
->ie_bits
= bits
&~ MACH_PORT_TYPE_RECEIVE
;
1494 ipc_port_clear_receiver(port
);
1496 port
->ip_receiver_name
= MACH_PORT_NULL
;
1497 port
->ip_destination
= IP_NULL
;
1500 *objectp
= (ipc_object_t
) port
;
1501 *sorightp
= dnrequest
;
1505 case MACH_MSG_TYPE_COPY_SEND
: {
1508 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1511 /* allow for dead send-once rights */
1513 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1516 assert(IE_BITS_UREFS(bits
) > 0);
1518 port
= (ipc_port_t
) entry
->ie_object
;
1519 assert(port
!= IP_NULL
);
1521 if (ipc_right_check(space
, port
, name
, entry
)) {
1522 bits
= entry
->ie_bits
;
1525 /* port is locked and active */
1527 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1528 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1529 assert(port
->ip_sorights
> 0);
1535 assert(port
->ip_srights
> 0);
1541 *objectp
= (ipc_object_t
) port
;
1542 *sorightp
= IP_NULL
;
1546 case MACH_MSG_TYPE_MOVE_SEND
: {
1548 ipc_port_t dnrequest
= IP_NULL
;
1550 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1553 /* allow for dead send-once rights */
1555 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1558 assert(IE_BITS_UREFS(bits
) > 0);
1560 port
= (ipc_port_t
) entry
->ie_object
;
1561 assert(port
!= IP_NULL
);
1563 if (ipc_right_check(space
, port
, name
, entry
)) {
1564 bits
= entry
->ie_bits
;
1567 /* port is locked and active */
1569 if ((bits
& MACH_PORT_TYPE_SEND
) == 0) {
1570 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1571 assert(port
->ip_sorights
> 0);
1577 assert(port
->ip_srights
> 0);
1579 if (IE_BITS_UREFS(bits
) == 1) {
1580 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1581 assert(port
->ip_receiver_name
== name
);
1582 assert(port
->ip_receiver
== space
);
1583 assert(IE_BITS_TYPE(bits
) ==
1584 MACH_PORT_TYPE_SEND_RECEIVE
);
1588 assert(IE_BITS_TYPE(bits
) ==
1589 MACH_PORT_TYPE_SEND
);
1591 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1593 ipc_hash_delete(space
, (ipc_object_t
) port
,
1595 entry
->ie_object
= IO_NULL
;
1597 entry
->ie_bits
= bits
&~
1598 (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1602 entry
->ie_bits
= bits
-1; /* decrement urefs */
1607 *objectp
= (ipc_object_t
) port
;
1608 *sorightp
= dnrequest
;
1612 case MACH_MSG_TYPE_MOVE_SEND_ONCE
: {
1614 ipc_port_t dnrequest
;
1616 if (bits
& MACH_PORT_TYPE_DEAD_NAME
)
1619 /* allow for dead send rights */
1621 if ((bits
& MACH_PORT_TYPE_SEND_RIGHTS
) == 0)
1624 assert(IE_BITS_UREFS(bits
) > 0);
1626 port
= (ipc_port_t
) entry
->ie_object
;
1627 assert(port
!= IP_NULL
);
1629 if (ipc_right_check(space
, port
, name
, entry
)) {
1630 bits
= entry
->ie_bits
;
1633 /* port is locked and active */
1635 if ((bits
& MACH_PORT_TYPE_SEND_ONCE
) == 0) {
1636 assert(bits
& MACH_PORT_TYPE_SEND
);
1637 assert(port
->ip_srights
> 0);
1643 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND_ONCE
);
1644 assert(IE_BITS_UREFS(bits
) == 1);
1645 assert(port
->ip_sorights
> 0);
1647 dnrequest
= ipc_right_dncancel_macro(space
, port
, name
, entry
);
1650 entry
->ie_object
= IO_NULL
;
1651 entry
->ie_bits
= bits
&~
1652 (IE_BITS_UREFS_MASK
| MACH_PORT_TYPE_SEND_ONCE
);
1654 *objectp
= (ipc_object_t
) port
;
1655 *sorightp
= dnrequest
;
1661 return KERN_INVALID_RIGHT
;
1664 return KERN_SUCCESS
;
1667 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1668 assert(IE_BITS_UREFS(bits
) > 0);
1669 assert(entry
->ie_request
== 0);
1670 assert(entry
->ie_object
== 0);
1676 *sorightp
= IP_NULL
;
1677 return KERN_SUCCESS
;
1680 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
1681 assert(IE_BITS_UREFS(bits
) > 0);
1682 assert(entry
->ie_request
== 0);
1683 assert(entry
->ie_object
== 0);
1688 if (IE_BITS_UREFS(bits
) == 1) {
1689 bits
&= ~MACH_PORT_TYPE_DEAD_NAME
;
1691 entry
->ie_bits
= bits
-1; /* decrement urefs */
1694 *sorightp
= IP_NULL
;
1695 return KERN_SUCCESS
;
1700 * Routine: ipc_right_copyin_undo
1702 * Undoes the effects of an ipc_right_copyin
1703 * of a send/send-once right that is dead.
1704 * (Object is either IO_DEAD or a dead port.)
1706 * The space is write-locked and active.
1710 ipc_right_copyin_undo(
1712 mach_port_name_t name
,
1714 mach_msg_type_name_t msgt_name
,
1715 ipc_object_t object
,
1718 ipc_entry_bits_t bits
;
1720 bits
= entry
->ie_bits
;
1722 assert(space
->is_active
);
1724 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1725 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
) ||
1726 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1728 if (soright
!= IP_NULL
) {
1729 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1730 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1731 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1732 assert(object
!= IO_DEAD
);
1734 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1735 MACH_PORT_TYPE_DEAD_NAME
| 2);
1737 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
) {
1738 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1739 (msgt_name
== MACH_MSG_TYPE_MOVE_SEND_ONCE
));
1741 entry
->ie_bits
= ((bits
&~ IE_BITS_RIGHT_MASK
) |
1742 MACH_PORT_TYPE_DEAD_NAME
| 1);
1743 } else if (IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
) {
1744 assert(object
== IO_DEAD
);
1745 assert(IE_BITS_UREFS(bits
) > 0);
1747 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1748 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
);
1749 entry
->ie_bits
= bits
+1; /* increment urefs */
1752 assert((msgt_name
== MACH_MSG_TYPE_MOVE_SEND
) ||
1753 (msgt_name
== MACH_MSG_TYPE_COPY_SEND
));
1754 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1755 assert(object
!= IO_DEAD
);
1756 assert(entry
->ie_object
== object
);
1757 assert(IE_BITS_UREFS(bits
) > 0);
1759 if (msgt_name
!= MACH_MSG_TYPE_COPY_SEND
) {
1760 assert(IE_BITS_UREFS(bits
) < MACH_PORT_UREFS_MAX
-1);
1761 entry
->ie_bits
= bits
+1; /* increment urefs */
1765 * May as well convert the entry to a dead name.
1766 * (Or if it is a compat entry, destroy it.)
1769 (void) ipc_right_check(space
, (ipc_port_t
) object
,
1771 /* object is dead so it is not locked */
1774 /* release the reference acquired by copyin */
1776 if (object
!= IO_DEAD
)
1777 ipc_object_release(object
);
1781 * Routine: ipc_right_copyin_two
1783 * Like ipc_right_copyin with MACH_MSG_TYPE_MOVE_SEND
1784 * and deadok == FALSE, except that this moves two
1785 * send rights at once.
1787 * The space is write-locked and active.
1788 * The object is returned with two refs/send rights.
1790 * KERN_SUCCESS Acquired an object.
1791 * KERN_INVALID_RIGHT Name doesn't denote correct right.
1795 ipc_right_copyin_two(
1797 mach_port_name_t name
,
1799 ipc_object_t
*objectp
,
1800 ipc_port_t
*sorightp
)
1802 ipc_entry_bits_t bits
;
1803 mach_port_urefs_t urefs
;
1805 ipc_port_t dnrequest
= IP_NULL
;
1807 assert(space
->is_active
);
1809 bits
= entry
->ie_bits
;
1811 if ((bits
& MACH_PORT_TYPE_SEND
) == 0)
1814 urefs
= IE_BITS_UREFS(bits
);
1818 port
= (ipc_port_t
) entry
->ie_object
;
1819 assert(port
!= IP_NULL
);
1821 if (ipc_right_check(space
, port
, name
, entry
)) {
1824 /* port is locked and active */
1826 assert(port
->ip_srights
> 0);
1829 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1830 assert(port
->ip_receiver_name
== name
);
1831 assert(port
->ip_receiver
== space
);
1832 assert(IE_BITS_TYPE(bits
) ==
1833 MACH_PORT_TYPE_SEND_RECEIVE
);
1839 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1841 dnrequest
= ipc_right_dncancel_macro(space
, port
,
1846 ipc_hash_delete(space
, (ipc_object_t
) port
,
1848 entry
->ie_object
= IO_NULL
;
1850 entry
->ie_bits
= bits
&~ (IE_BITS_UREFS_MASK
|MACH_PORT_TYPE_SEND
);
1852 port
->ip_srights
+= 2;
1855 entry
->ie_bits
= bits
-2; /* decrement urefs */
1859 *objectp
= (ipc_object_t
) port
;
1860 *sorightp
= dnrequest
;
1861 return KERN_SUCCESS
;
1864 return KERN_INVALID_RIGHT
;
1868 * Routine: ipc_right_copyout
1870 * Copyout a capability to a space.
1871 * If successful, consumes a ref for the object.
1873 * Always succeeds when given a newly-allocated entry,
1874 * because user-reference overflow isn't a possibility.
1876 * If copying out the object would cause the user-reference
1877 * count in the entry to overflow, and overflow is TRUE,
1878 * then instead the user-reference count is left pegged
1879 * to its maximum value and the copyout succeeds anyway.
1881 * The space is write-locked and active.
1882 * The object is locked and active.
1883 * The object is unlocked; the space isn't.
1885 * KERN_SUCCESS Copied out capability.
1886 * KERN_UREFS_OVERFLOW User-refs would overflow;
1887 * guaranteed not to happen with a fresh entry
1888 * or if overflow=TRUE was specified.
1894 mach_port_name_t name
,
1896 mach_msg_type_name_t msgt_name
,
1898 ipc_object_t object
)
1900 ipc_entry_bits_t bits
;
1903 bits
= entry
->ie_bits
;
1905 assert(IO_VALID(object
));
1906 assert(io_otype(object
) == IOT_PORT
);
1907 assert(io_active(object
));
1908 assert(entry
->ie_object
== object
);
1910 port
= (ipc_port_t
) object
;
1912 switch (msgt_name
) {
1913 case MACH_MSG_TYPE_PORT_SEND_ONCE
:
1915 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1916 assert(port
->ip_sorights
> 0);
1918 /* transfer send-once right and ref to entry */
1921 entry
->ie_bits
= bits
| (MACH_PORT_TYPE_SEND_ONCE
| 1);
1924 case MACH_MSG_TYPE_PORT_SEND
:
1925 assert(port
->ip_srights
> 0);
1927 if (bits
& MACH_PORT_TYPE_SEND
) {
1928 mach_port_urefs_t urefs
= IE_BITS_UREFS(bits
);
1930 assert(port
->ip_srights
> 1);
1932 assert(urefs
< MACH_PORT_UREFS_MAX
);
1934 if (urefs
+1 == MACH_PORT_UREFS_MAX
) {
1936 /* leave urefs pegged to maximum */
1941 return KERN_SUCCESS
;
1945 return KERN_UREFS_OVERFLOW
;
1951 } else if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1952 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_RECEIVE
);
1953 assert(IE_BITS_UREFS(bits
) == 0);
1955 /* transfer send right to entry */
1959 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
1960 assert(IE_BITS_UREFS(bits
) == 0);
1962 /* transfer send right and ref to entry */
1965 /* entry is locked holding ref, so can use port */
1967 ipc_hash_insert(space
, (ipc_object_t
) port
,
1971 entry
->ie_bits
= (bits
| MACH_PORT_TYPE_SEND
) + 1;
1974 case MACH_MSG_TYPE_PORT_RECEIVE
: {
1977 assert(port
->ip_mscount
== 0);
1978 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1979 dest
= port
->ip_destination
;
1981 port
->ip_receiver_name
= name
;
1982 port
->ip_receiver
= space
;
1984 assert((bits
& MACH_PORT_TYPE_RECEIVE
) == 0);
1986 if (bits
& MACH_PORT_TYPE_SEND
) {
1987 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_SEND
);
1988 assert(IE_BITS_UREFS(bits
) > 0);
1989 assert(port
->ip_srights
> 0);
1994 /* entry is locked holding ref, so can use port */
1996 ipc_hash_delete(space
, (ipc_object_t
) port
,
1999 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_NONE
);
2000 assert(IE_BITS_UREFS(bits
) == 0);
2002 /* transfer ref to entry */
2005 entry
->ie_bits
= bits
| MACH_PORT_TYPE_RECEIVE
;
2007 if (dest
!= IP_NULL
)
2008 ipc_port_release(dest
);
2013 panic("ipc_right_copyout: strange rights");
2016 return KERN_SUCCESS
;
2020 * Routine: ipc_right_rename
2022 * Transfer an entry from one name to another.
2023 * The old entry is deallocated.
2025 * The space is write-locked and active.
2026 * The new entry is unused. Upon return,
2027 * the space is unlocked.
2029 * KERN_SUCCESS Moved entry to new name.
2035 mach_port_name_t oname
,
2037 mach_port_name_t nname
,
2040 ipc_port_request_index_t request
= oentry
->ie_request
;
2041 ipc_entry_bits_t bits
= oentry
->ie_bits
;
2042 ipc_object_t object
= oentry
->ie_object
;
2044 assert(space
->is_active
);
2045 assert(oname
!= nname
);
2048 * If IE_BITS_COMPAT, we can't allow the entry to be renamed
2049 * if the port is dead. (This would foil ipc_port_destroy.)
2050 * Instead we should fail because oentry shouldn't exist.
2051 * Note IE_BITS_COMPAT implies ie_request != 0.
2057 assert(bits
& MACH_PORT_TYPE_PORT_RIGHTS
);
2058 port
= (ipc_port_t
) object
;
2059 assert(port
!= IP_NULL
);
2061 if (ipc_right_check(space
, port
, oname
, oentry
)) {
2064 bits
= oentry
->ie_bits
;
2065 assert(IE_BITS_TYPE(bits
) == MACH_PORT_TYPE_DEAD_NAME
);
2066 assert(oentry
->ie_request
== 0);
2068 /* port is locked and active */
2070 ipc_port_dnrename(port
, request
, oname
, nname
);
2072 oentry
->ie_request
= 0;
2076 /* initialize nentry before letting ipc_hash_insert see it */
2078 assert((nentry
->ie_bits
& IE_BITS_RIGHT_MASK
) == 0);
2079 nentry
->ie_bits
|= bits
& IE_BITS_RIGHT_MASK
;
2080 nentry
->ie_request
= request
;
2081 nentry
->ie_object
= object
;
2083 switch (IE_BITS_TYPE(bits
)) {
2084 case MACH_PORT_TYPE_SEND
: {
2087 port
= (ipc_port_t
) object
;
2088 assert(port
!= IP_NULL
);
2090 /* remember, there are no other share entries possible */
2091 /* or we can't do the rename. Therefore we do not need */
2092 /* to check the other subspaces */
2093 ipc_hash_delete(space
, (ipc_object_t
) port
, oname
, oentry
);
2094 ipc_hash_insert(space
, (ipc_object_t
) port
, nname
, nentry
);
2098 case MACH_PORT_TYPE_RECEIVE
:
2099 case MACH_PORT_TYPE_SEND_RECEIVE
: {
2102 port
= (ipc_port_t
) object
;
2103 assert(port
!= IP_NULL
);
2106 assert(ip_active(port
));
2107 assert(port
->ip_receiver_name
== oname
);
2108 assert(port
->ip_receiver
== space
);
2110 port
->ip_receiver_name
= nname
;
2115 case MACH_PORT_TYPE_PORT_SET
: {
2118 pset
= (ipc_pset_t
) object
;
2119 assert(pset
!= IPS_NULL
);
2122 assert(ips_active(pset
));
2123 assert(pset
->ips_local_name
== oname
);
2125 pset
->ips_local_name
= nname
;
2130 case MACH_PORT_TYPE_SEND_ONCE
:
2131 case MACH_PORT_TYPE_DEAD_NAME
:
2135 panic("ipc_right_rename: strange rights");
2138 assert(oentry
->ie_request
== 0);
2139 oentry
->ie_object
= IO_NULL
;
2140 ipc_entry_dealloc(space
, oname
, oentry
);
2141 is_write_unlock(space
);
2143 return KERN_SUCCESS
;