2 * Copyright (c) 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@
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/mach_port.c
60 * Exported kernel calls. See mach/mach_port.defs.
63 #include <mach_debug.h>
66 #include <mach/port.h>
67 #include <mach/kern_return.h>
68 #include <mach/notify.h>
69 #include <mach/mach_param.h>
70 #include <mach/vm_param.h>
71 #include <mach/vm_prot.h>
72 #include <mach/vm_map.h>
73 #include <kern/task.h>
74 #include <kern/counters.h>
75 #include <kern/thread_act.h>
76 #include <mach/mach_port_server.h>
77 #include <vm/vm_map.h>
78 #include <vm/vm_kern.h>
79 #include <ipc/ipc_entry.h>
80 #include <ipc/ipc_space.h>
81 #include <ipc/ipc_object.h>
82 #include <ipc/ipc_notify.h>
83 #include <ipc/ipc_port.h>
84 #include <ipc/ipc_pset.h>
85 #include <ipc/ipc_right.h>
86 #include <ipc/ipc_kmsg.h>
87 #include <kern/misc_protos.h>
90 * Forward declarations
92 void mach_port_names_helper(
93 ipc_port_timestamp_t timestamp
,
95 mach_port_name_t name
,
96 mach_port_name_t
*names
,
97 mach_port_type_t
*types
,
98 ipc_entry_num_t
*actualp
,
101 void mach_port_gst_helper(
104 ipc_entry_num_t maxnames
,
105 mach_port_name_t
*names
,
106 ipc_entry_num_t
*actualp
);
109 /* Zeroed template of qos flags */
111 static mach_port_qos_t qos_template
;
114 * Routine: mach_port_names_helper
116 * A helper function for mach_port_names.
120 mach_port_names_helper(
121 ipc_port_timestamp_t timestamp
,
123 mach_port_name_t name
,
124 mach_port_name_t
*names
,
125 mach_port_type_t
*types
,
126 ipc_entry_num_t
*actualp
,
129 ipc_entry_bits_t bits
;
130 ipc_port_request_index_t request
;
131 mach_port_type_t type
;
132 ipc_entry_num_t actual
;
134 bits
= entry
->ie_bits
;
135 request
= entry
->ie_request
;
136 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
140 port
= (ipc_port_t
) entry
->ie_object
;
141 assert(port
!= IP_NULL
);
144 * The timestamp serializes mach_port_names
145 * with ipc_port_destroy. If the port died,
146 * but after mach_port_names started, pretend
147 * that it isn't dead.
151 died
= (!ip_active(port
) &&
152 IP_TIMESTAMP_ORDER(port
->ip_timestamp
, timestamp
));
156 /* pretend this is a dead-name entry */
158 bits
&= ~(IE_BITS_TYPE_MASK
);
159 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
166 type
= IE_BITS_TYPE(bits
);
168 type
|= MACH_PORT_TYPE_DNREQUEST
;
171 names
[actual
] = name
;
172 types
[actual
] = type
;
177 * Routine: mach_port_names [kernel call]
179 * Retrieves a list of the rights present in the space,
180 * along with type information. (Same as returned
181 * by mach_port_type.) The names are returned in
182 * no particular order, but they (and the type info)
183 * are an accurate snapshot of the space.
187 * KERN_SUCCESS Arrays of names and types returned.
188 * KERN_INVALID_TASK The space is null.
189 * KERN_INVALID_TASK The space is dead.
190 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
196 mach_port_name_t
**namesp
,
197 mach_msg_type_number_t
*namesCnt
,
198 mach_port_type_t
**typesp
,
199 mach_msg_type_number_t
*typesCnt
)
201 ipc_entry_bits_t
*capability
;
202 ipc_tree_entry_t tentry
;
204 ipc_entry_num_t tsize
;
205 mach_port_index_t index
;
206 ipc_entry_num_t actual
; /* this many names */
207 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
208 mach_port_name_t
*names
;
209 mach_port_type_t
*types
;
212 vm_size_t size
; /* size of allocated memory */
213 vm_offset_t addr1
; /* allocated memory, for names */
214 vm_offset_t addr2
; /* allocated memory, for types */
215 vm_map_copy_t memory1
; /* copied-in memory, for names */
216 vm_map_copy_t memory2
; /* copied-in memory, for types */
218 /* safe simplifying assumption */
219 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
221 if (space
== IS_NULL
)
222 return KERN_INVALID_TASK
;
227 ipc_entry_num_t bound
;
228 vm_size_t size_needed
;
231 if (!space
->is_active
) {
232 is_read_unlock(space
);
234 kmem_free(ipc_kernel_map
, addr1
, size
);
235 kmem_free(ipc_kernel_map
, addr2
, size
);
237 return KERN_INVALID_TASK
;
240 /* upper bound on number of names in the space */
242 bound
= space
->is_table_size
+ space
->is_tree_total
;
243 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
245 if (size_needed
<= size
)
248 is_read_unlock(space
);
251 kmem_free(ipc_kernel_map
, addr1
, size
);
252 kmem_free(ipc_kernel_map
, addr2
, size
);
256 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, TRUE
);
257 if (kr
!= KERN_SUCCESS
)
258 return KERN_RESOURCE_SHORTAGE
;
260 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, TRUE
);
261 if (kr
!= KERN_SUCCESS
) {
262 kmem_free(ipc_kernel_map
, addr1
, size
);
263 return KERN_RESOURCE_SHORTAGE
;
266 /* can't fault while we hold locks */
268 kr
= vm_map_wire(ipc_kernel_map
, addr1
, addr1
+ size
,
269 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
270 if (kr
!= KERN_SUCCESS
) {
271 kmem_free(ipc_kernel_map
, addr1
, size
);
272 kmem_free(ipc_kernel_map
, addr2
, size
);
273 return KERN_RESOURCE_SHORTAGE
;
276 kr
= vm_map_wire(ipc_kernel_map
, addr2
, addr2
+ size
,
277 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
278 if (kr
!= KERN_SUCCESS
) {
279 kmem_free(ipc_kernel_map
, addr1
, size
);
280 kmem_free(ipc_kernel_map
, addr2
, size
);
281 return KERN_RESOURCE_SHORTAGE
;
285 /* space is read-locked and active */
287 names
= (mach_port_name_t
*) addr1
;
288 types
= (mach_port_type_t
*) addr2
;
291 timestamp
= ipc_port_timestamp();
293 table
= space
->is_table
;
294 tsize
= space
->is_table_size
;
296 for (index
= 0; index
< tsize
; index
++) {
297 ipc_entry_t entry
= &table
[index
];
298 ipc_entry_bits_t bits
= entry
->ie_bits
;
300 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
301 mach_port_name_t name
;
303 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
304 mach_port_names_helper(timestamp
, entry
, name
, names
,
305 types
, &actual
, space
);
309 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
311 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
312 ipc_entry_t entry
= &tentry
->ite_entry
;
313 mach_port_name_t name
= tentry
->ite_name
;
315 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
316 mach_port_names_helper(timestamp
, entry
, name
, names
,
317 types
, &actual
, space
);
319 ipc_splay_traverse_finish(&space
->is_tree
);
320 is_read_unlock(space
);
323 memory1
= VM_MAP_COPY_NULL
;
324 memory2
= VM_MAP_COPY_NULL
;
327 kmem_free(ipc_kernel_map
, addr1
, size
);
328 kmem_free(ipc_kernel_map
, addr2
, size
);
332 vm_size_t vm_size_used
;
334 size_used
= actual
* sizeof(mach_port_name_t
);
335 vm_size_used
= round_page(size_used
);
338 * Make used memory pageable and get it into
339 * copied-in form. Free any unused memory.
342 kr
= vm_map_unwire(ipc_kernel_map
,
343 addr1
, addr1
+ vm_size_used
, FALSE
);
344 assert(kr
== KERN_SUCCESS
);
346 kr
= vm_map_unwire(ipc_kernel_map
,
347 addr2
, addr2
+ vm_size_used
, FALSE
);
348 assert(kr
== KERN_SUCCESS
);
350 kr
= vm_map_copyin(ipc_kernel_map
, addr1
, size_used
,
352 assert(kr
== KERN_SUCCESS
);
354 kr
= vm_map_copyin(ipc_kernel_map
, addr2
, size_used
,
356 assert(kr
== KERN_SUCCESS
);
358 if (vm_size_used
!= size
) {
359 kmem_free(ipc_kernel_map
,
360 addr1
+ vm_size_used
, size
- vm_size_used
);
361 kmem_free(ipc_kernel_map
,
362 addr2
+ vm_size_used
, size
- vm_size_used
);
366 *namesp
= (mach_port_name_t
*) memory1
;
368 *typesp
= (mach_port_type_t
*) memory2
;
374 * Routine: mach_port_type [kernel call]
376 * Retrieves the type of a right in the space.
377 * The type is a bitwise combination of one or more
378 * of the following type bits:
379 * MACH_PORT_TYPE_SEND
380 * MACH_PORT_TYPE_RECEIVE
381 * MACH_PORT_TYPE_SEND_ONCE
382 * MACH_PORT_TYPE_PORT_SET
383 * MACH_PORT_TYPE_DEAD_NAME
384 * In addition, the following pseudo-type bits may be present:
385 * MACH_PORT_TYPE_DNREQUEST
386 * A dead-name notification is requested.
390 * KERN_SUCCESS Type is returned.
391 * KERN_INVALID_TASK The space is null.
392 * KERN_INVALID_TASK The space is dead.
393 * KERN_INVALID_NAME The name doesn't denote a right.
399 mach_port_name_t name
,
400 mach_port_type_t
*typep
)
402 mach_port_urefs_t urefs
;
406 if (space
== IS_NULL
)
407 return KERN_INVALID_TASK
;
409 if (name
== MACH_PORT_NULL
)
410 return KERN_INVALID_NAME
;
412 if (name
== MACH_PORT_DEAD
) {
413 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
417 kr
= ipc_right_lookup_write(space
, name
, &entry
);
418 if (kr
!= KERN_SUCCESS
)
420 /* space is write-locked and active */
422 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
423 if (kr
== KERN_SUCCESS
)
424 is_write_unlock(space
);
425 /* space is unlocked */
430 * Routine: mach_port_rename [kernel call]
432 * Changes the name denoting a right,
433 * from oname to nname.
437 * KERN_SUCCESS The right is renamed.
438 * KERN_INVALID_TASK The space is null.
439 * KERN_INVALID_TASK The space is dead.
440 * KERN_INVALID_NAME The oname doesn't denote a right.
441 * KERN_INVALID_VALUE The nname isn't a legal name.
442 * KERN_NAME_EXISTS The nname already denotes a right.
443 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
449 mach_port_name_t oname
,
450 mach_port_name_t nname
)
452 if (space
== IS_NULL
)
453 return KERN_INVALID_TASK
;
455 if (!MACH_PORT_VALID(oname
))
456 return KERN_INVALID_NAME
;
458 if (!MACH_PORT_VALID(nname
))
459 return KERN_INVALID_VALUE
;
461 return ipc_object_rename(space
, oname
, nname
);
465 * Routine: mach_port_allocate_name [kernel call]
467 * Allocates a right in a space, using a specific name
468 * for the new right. Possible rights:
469 * MACH_PORT_RIGHT_RECEIVE
470 * MACH_PORT_RIGHT_PORT_SET
471 * MACH_PORT_RIGHT_DEAD_NAME
473 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
474 * has no extant send or send-once rights and no queued
475 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
476 * and its make-send count is 0. It is not a member of
477 * a port set. It has no registered no-senders or
478 * port-destroyed notification requests.
480 * A new port set has no members.
482 * A new dead name has one user reference.
486 * KERN_SUCCESS The right is allocated.
487 * KERN_INVALID_TASK The space is null.
488 * KERN_INVALID_TASK The space is dead.
489 * KERN_INVALID_VALUE The name isn't a legal name.
490 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
491 * KERN_NAME_EXISTS The name already denotes a right.
492 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
494 * Restrictions on name allocation: NT bits are reserved by kernel,
495 * must be set on any chosen name. Can't do this at all in kernel
500 mach_port_allocate_name(
502 mach_port_right_t right
,
503 mach_port_name_t name
)
506 mach_port_qos_t qos
= qos_template
;
510 if (!MACH_PORT_VALID(name
))
511 return KERN_INVALID_VALUE
;
513 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
519 * Routine: mach_port_allocate [kernel call]
521 * Allocates a right in a space. Like mach_port_allocate_name,
522 * except that the implementation picks a name for the right.
523 * The name may be any legal name in the space that doesn't
524 * currently denote a right.
528 * KERN_SUCCESS The right is allocated.
529 * KERN_INVALID_TASK The space is null.
530 * KERN_INVALID_TASK The space is dead.
531 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
532 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
533 * KERN_NO_SPACE No room in space for another right.
539 mach_port_right_t right
,
540 mach_port_name_t
*namep
)
543 mach_port_qos_t qos
= qos_template
;
545 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
551 * Routine: mach_port_allocate_qos [kernel call]
553 * Allocates a right, with qos options, in a space. Like
554 * mach_port_allocate_name, except that the implementation
555 * picks a name for the right. The name may be any legal name
556 * in the space that doesn't currently denote a right.
560 * KERN_SUCCESS The right is allocated.
561 * KERN_INVALID_TASK The space is null.
562 * KERN_INVALID_TASK The space is dead.
563 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
564 * KERN_INVALID_ARGUMENT The qos request was invalid.
565 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
566 * KERN_NO_SPACE No room in space for another right.
570 mach_port_allocate_qos(
572 mach_port_right_t right
,
573 mach_port_qos_t
*qosp
,
574 mach_port_name_t
*namep
)
579 return KERN_INVALID_ARGUMENT
;
580 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
586 * Routine: mach_port_allocate_full [kernel call]
588 * Allocates a right in a space. Supports all of the
589 * special cases, such as specifying a subsystem,
590 * a specific name, a real-time port, etc.
591 * The name may be any legal name in the space that doesn't
592 * currently denote a right.
596 * KERN_SUCCESS The right is allocated.
597 * KERN_INVALID_TASK The space is null.
598 * KERN_INVALID_TASK The space is dead.
599 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
600 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
601 * KERN_NO_SPACE No room in space for another right.
605 mach_port_allocate_full(
607 mach_port_right_t right
,
609 mach_port_qos_t
*qosp
,
610 mach_port_name_t
*namep
)
615 if (space
== IS_NULL
)
616 return (KERN_INVALID_TASK
);
618 if (proto
!= MACH_PORT_NULL
)
619 return (KERN_INVALID_VALUE
);
622 if (!MACH_PORT_VALID (*namep
))
623 return (KERN_INVALID_VALUE
);
624 if (is_fast_space (space
))
625 return (KERN_FAILURE
);
628 if (qosp
->prealloc
) {
629 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
630 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
631 return (KERN_INVALID_VALUE
);
632 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(size
));
633 if (kmsg
== IKM_NULL
)
634 return (KERN_RESOURCE_SHORTAGE
);
635 ikm_init(kmsg
, size
);
639 case MACH_PORT_RIGHT_RECEIVE
:
644 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
646 kr
= ipc_port_alloc(space
, namep
, &port
);
647 if (kr
== KERN_SUCCESS
) {
649 ipc_kmsg_set_prealloc(kmsg
, port
);
653 } else if (qosp
->prealloc
)
658 case MACH_PORT_RIGHT_PORT_SET
:
663 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
665 kr
= ipc_pset_alloc(space
, namep
, &pset
);
666 if (kr
== KERN_SUCCESS
)
671 case MACH_PORT_RIGHT_DEAD_NAME
:
672 kr
= ipc_object_alloc_dead(space
, namep
);
676 kr
= KERN_INVALID_VALUE
;
684 * Routine: mach_port_destroy [kernel call]
686 * Cleans up and destroys all rights denoted by a name
687 * in a space. The destruction of a receive right
688 * destroys the port, unless a port-destroyed request
689 * has been made for it; the destruction of a port-set right
690 * destroys the port set.
694 * KERN_SUCCESS The name is destroyed.
695 * KERN_INVALID_TASK The space is null.
696 * KERN_INVALID_TASK The space is dead.
697 * KERN_INVALID_NAME The name doesn't denote a right.
703 mach_port_name_t name
)
708 if (space
== IS_NULL
)
709 return KERN_INVALID_TASK
;
711 if (!MACH_PORT_VALID(name
))
714 kr
= ipc_right_lookup_write(space
, name
, &entry
);
715 if (kr
!= KERN_SUCCESS
)
717 /* space is write-locked and active */
719 kr
= ipc_right_destroy(space
, name
, entry
);
720 is_write_unlock(space
);
725 * Routine: mach_port_deallocate [kernel call]
727 * Deallocates a user reference from a send right,
728 * send-once right, or a dead-name right. May
729 * deallocate the right, if this is the last uref,
730 * and destroy the name, if it doesn't denote
735 * KERN_SUCCESS The uref is deallocated.
736 * KERN_INVALID_TASK The space is null.
737 * KERN_INVALID_TASK The space is dead.
738 * KERN_INVALID_NAME The name doesn't denote a right.
739 * KERN_INVALID_RIGHT The right isn't correct.
743 mach_port_deallocate(
745 mach_port_name_t name
)
750 if (space
== IS_NULL
)
751 return KERN_INVALID_TASK
;
753 if (!MACH_PORT_VALID(name
))
756 kr
= ipc_right_lookup_write(space
, name
, &entry
);
757 if (kr
!= KERN_SUCCESS
)
759 /* space is write-locked */
761 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
766 * Routine: mach_port_get_refs [kernel call]
768 * Retrieves the number of user references held by a right.
769 * Receive rights, port-set rights, and send-once rights
770 * always have one user reference. Returns zero if the
771 * name denotes a right, but not the queried right.
775 * KERN_SUCCESS Number of urefs returned.
776 * KERN_INVALID_TASK The space is null.
777 * KERN_INVALID_TASK The space is dead.
778 * KERN_INVALID_VALUE "right" isn't a legal value.
779 * KERN_INVALID_NAME The name doesn't denote a right.
785 mach_port_name_t name
,
786 mach_port_right_t right
,
787 mach_port_urefs_t
*urefsp
)
789 mach_port_type_t type
;
790 mach_port_urefs_t urefs
;
794 if (space
== IS_NULL
)
795 return KERN_INVALID_TASK
;
797 if (right
>= MACH_PORT_RIGHT_NUMBER
)
798 return KERN_INVALID_VALUE
;
800 if (!MACH_PORT_VALID(name
)) {
801 if (right
== MACH_PORT_RIGHT_SEND
||
802 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
806 return KERN_INVALID_NAME
;
809 kr
= ipc_right_lookup_write(space
, name
, &entry
);
810 if (kr
!= KERN_SUCCESS
)
812 /* space is write-locked and active */
814 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
815 if (kr
!= KERN_SUCCESS
)
816 return kr
; /* space is unlocked */
817 is_write_unlock(space
);
819 if (type
& MACH_PORT_TYPE(right
))
821 case MACH_PORT_RIGHT_SEND_ONCE
:
825 case MACH_PORT_RIGHT_PORT_SET
:
826 case MACH_PORT_RIGHT_RECEIVE
:
830 case MACH_PORT_RIGHT_DEAD_NAME
:
831 case MACH_PORT_RIGHT_SEND
:
837 panic("mach_port_get_refs: strange rights");
846 * Routine: mach_port_mod_refs
848 * Modifies the number of user references held by a right.
849 * The resulting number of user references must be non-negative.
850 * If it is zero, the right is deallocated. If the name
851 * doesn't denote other rights, it is destroyed.
855 * KERN_SUCCESS Modified number of urefs.
856 * KERN_INVALID_TASK The space is null.
857 * KERN_INVALID_TASK The space is dead.
858 * KERN_INVALID_VALUE "right" isn't a legal value.
859 * KERN_INVALID_NAME The name doesn't denote a right.
860 * KERN_INVALID_RIGHT Name doesn't denote specified right.
861 * KERN_INVALID_VALUE Impossible modification to urefs.
862 * KERN_UREFS_OVERFLOW Urefs would overflow.
868 mach_port_name_t name
,
869 mach_port_right_t right
,
870 mach_port_delta_t delta
)
875 if (space
== IS_NULL
)
876 return KERN_INVALID_TASK
;
878 if (right
>= MACH_PORT_RIGHT_NUMBER
)
879 return KERN_INVALID_VALUE
;
881 if (!MACH_PORT_VALID(name
)) {
882 if (right
== MACH_PORT_RIGHT_SEND
||
883 right
== MACH_PORT_RIGHT_SEND_ONCE
)
885 return KERN_INVALID_NAME
;
888 kr
= ipc_right_lookup_write(space
, name
, &entry
);
889 if (kr
!= KERN_SUCCESS
)
891 /* space is write-locked and active */
893 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
899 * Routine: mach_port_set_mscount [kernel call]
901 * Changes a receive right's make-send count.
905 * KERN_SUCCESS Set make-send count.
906 * KERN_INVALID_TASK The space is null.
907 * KERN_INVALID_TASK The space is dead.
908 * KERN_INVALID_NAME The name doesn't denote a right.
909 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
913 mach_port_set_mscount(
915 mach_port_name_t name
,
916 mach_port_mscount_t mscount
)
921 if (space
== IS_NULL
)
922 return KERN_INVALID_TASK
;
924 if (!MACH_PORT_VALID(name
))
925 return KERN_INVALID_RIGHT
;
927 kr
= ipc_port_translate_receive(space
, name
, &port
);
928 if (kr
!= KERN_SUCCESS
)
930 /* port is locked and active */
932 ipc_port_set_mscount(port
, mscount
);
939 * Routine: mach_port_set_seqno [kernel call]
941 * Changes a receive right's sequence number.
945 * KERN_SUCCESS Set sequence number.
946 * KERN_INVALID_TASK The space is null.
947 * KERN_INVALID_TASK The space is dead.
948 * KERN_INVALID_NAME The name doesn't denote a right.
949 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
955 mach_port_name_t name
,
956 mach_port_seqno_t seqno
)
961 if (space
== IS_NULL
)
962 return KERN_INVALID_TASK
;
964 if (!MACH_PORT_VALID(name
))
965 return KERN_INVALID_RIGHT
;
967 kr
= ipc_port_translate_receive(space
, name
, &port
);
968 if (kr
!= KERN_SUCCESS
)
970 /* port is locked and active */
972 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
979 * Routine: mach_port_gst_helper
981 * A helper function for mach_port_get_set_status.
985 mach_port_gst_helper(
988 ipc_entry_num_t maxnames
,
989 mach_port_name_t
*names
,
990 ipc_entry_num_t
*actualp
)
993 mach_port_name_t name
;
995 assert(port
!= IP_NULL
);
998 assert(ip_active(port
));
1000 name
= port
->ip_receiver_name
;
1001 assert(name
!= MACH_PORT_NULL
);
1005 if (ipc_pset_member(pset
, port
)) {
1006 ipc_entry_num_t actual
= *actualp
;
1008 if (actual
< maxnames
)
1009 names
[actual
] = name
;
1011 *actualp
= actual
+1;
1016 * Routine: mach_port_get_set_status [kernel call]
1018 * Retrieves a list of members in a port set.
1019 * Returns the space's name for each receive right member.
1023 * KERN_SUCCESS Retrieved list of members.
1024 * KERN_INVALID_TASK The space is null.
1025 * KERN_INVALID_TASK The space is dead.
1026 * KERN_INVALID_NAME The name doesn't denote a right.
1027 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1028 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1032 mach_port_get_set_status(
1034 mach_port_name_t name
,
1035 mach_port_name_t
**members
,
1036 mach_msg_type_number_t
*membersCnt
)
1038 ipc_entry_num_t actual
; /* this many members */
1039 ipc_entry_num_t maxnames
; /* space for this many members */
1042 vm_size_t size
; /* size of allocated memory */
1043 vm_offset_t addr
; /* allocated memory */
1044 vm_map_copy_t memory
; /* copied-in memory */
1046 if (space
== IS_NULL
)
1047 return KERN_INVALID_TASK
;
1049 if (!MACH_PORT_VALID(name
))
1050 return KERN_INVALID_RIGHT
;
1052 size
= PAGE_SIZE
; /* initial guess */
1055 ipc_tree_entry_t tentry
;
1056 ipc_entry_t entry
, table
;
1057 ipc_entry_num_t tsize
;
1058 mach_port_index_t index
;
1059 mach_port_name_t
*names
;
1062 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, TRUE
);
1063 if (kr
!= KERN_SUCCESS
)
1064 return KERN_RESOURCE_SHORTAGE
;
1066 /* can't fault while we hold locks */
1068 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1069 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1070 assert(kr
== KERN_SUCCESS
);
1072 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1073 if (kr
!= KERN_SUCCESS
) {
1074 kmem_free(ipc_kernel_map
, addr
, size
);
1077 /* space is read-locked and active */
1079 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1080 is_read_unlock(space
);
1081 kmem_free(ipc_kernel_map
, addr
, size
);
1082 return KERN_INVALID_RIGHT
;
1085 pset
= (ipc_pset_t
) entry
->ie_object
;
1086 assert(pset
!= IPS_NULL
);
1087 /* the port set must be active */
1089 names
= (mach_port_name_t
*) addr
;
1090 maxnames
= size
/ sizeof(mach_port_name_t
);
1093 table
= space
->is_table
;
1094 tsize
= space
->is_table_size
;
1096 for (index
= 0; index
< tsize
; index
++) {
1097 ipc_entry_t ientry
= &table
[index
];
1099 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1101 (ipc_port_t
) ientry
->ie_object
;
1103 mach_port_gst_helper(pset
, port
,
1104 maxnames
, names
, &actual
);
1108 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1110 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1111 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1113 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1115 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1116 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1118 mach_port_gst_helper(pset
, port
, maxnames
,
1122 ipc_splay_traverse_finish(&space
->is_tree
);
1123 is_read_unlock(space
);
1125 if (actual
<= maxnames
)
1128 /* didn't have enough memory; allocate more */
1130 kmem_free(ipc_kernel_map
, addr
, size
);
1131 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1135 memory
= VM_MAP_COPY_NULL
;
1137 kmem_free(ipc_kernel_map
, addr
, size
);
1139 vm_size_t size_used
;
1140 vm_size_t vm_size_used
;
1142 size_used
= actual
* sizeof(mach_port_name_t
);
1143 vm_size_used
= round_page(size_used
);
1146 * Make used memory pageable and get it into
1147 * copied-in form. Free any unused memory.
1150 kr
= vm_map_unwire(ipc_kernel_map
,
1151 addr
, addr
+ vm_size_used
, FALSE
);
1152 assert(kr
== KERN_SUCCESS
);
1154 kr
= vm_map_copyin(ipc_kernel_map
, addr
, size_used
,
1156 assert(kr
== KERN_SUCCESS
);
1158 if (vm_size_used
!= size
)
1159 kmem_free(ipc_kernel_map
,
1160 addr
+ vm_size_used
, size
- vm_size_used
);
1163 *members
= (mach_port_name_t
*) memory
;
1164 *membersCnt
= actual
;
1165 return KERN_SUCCESS
;
1169 * Routine: mach_port_move_member [kernel call]
1171 * If after is MACH_PORT_NULL, removes member
1172 * from the port set it is in. Otherwise, adds
1173 * member to after, removing it from any set
1174 * it might already be in.
1178 * KERN_SUCCESS Moved the port.
1179 * KERN_INVALID_TASK The space is null.
1180 * KERN_INVALID_TASK The space is dead.
1181 * KERN_INVALID_NAME Member didn't denote a right.
1182 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1183 * KERN_INVALID_NAME After didn't denote a right.
1184 * KERN_INVALID_RIGHT After didn't denote a port set right.
1186 * After is MACH_PORT_NULL and Member isn't in a port set.
1190 mach_port_move_member(
1192 mach_port_name_t member
,
1193 mach_port_name_t after
)
1200 if (space
== IS_NULL
)
1201 return KERN_INVALID_TASK
;
1203 if (!MACH_PORT_VALID(member
))
1204 return KERN_INVALID_RIGHT
;
1206 if (after
== MACH_PORT_DEAD
)
1207 return KERN_INVALID_RIGHT
;
1209 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1210 if (kr
!= KERN_SUCCESS
)
1212 /* space is read-locked and active */
1214 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1215 is_read_unlock(space
);
1216 return KERN_INVALID_RIGHT
;
1219 port
= (ipc_port_t
) entry
->ie_object
;
1220 assert(port
!= IP_NULL
);
1222 if (after
== MACH_PORT_NULL
)
1225 entry
= ipc_entry_lookup(space
, after
);
1226 if (entry
== IE_NULL
) {
1227 is_read_unlock(space
);
1228 return KERN_INVALID_NAME
;
1231 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1232 is_read_unlock(space
);
1233 return KERN_INVALID_RIGHT
;
1236 nset
= (ipc_pset_t
) entry
->ie_object
;
1237 assert(nset
!= IPS_NULL
);
1240 ipc_pset_remove_from_all(port
);
1242 if (nset
!= IPS_NULL
) {
1244 kr
= ipc_pset_add(nset
, port
);
1248 is_read_unlock(space
);
1253 * Routine: mach_port_request_notification [kernel call]
1255 * Requests a notification. The caller supplies
1256 * a send-once right for the notification to use,
1257 * and the call returns the previously registered
1258 * send-once right, if any. Possible types:
1260 * MACH_NOTIFY_PORT_DESTROYED
1261 * Requests a port-destroyed notification
1262 * for a receive right. Sync should be zero.
1263 * MACH_NOTIFY_NO_SENDERS
1264 * Requests a no-senders notification for a
1265 * receive right. If there are currently no
1266 * senders, sync is less than or equal to the
1267 * current make-send count, and a send-once right
1268 * is supplied, then an immediate no-senders
1269 * notification is generated.
1270 * MACH_NOTIFY_DEAD_NAME
1271 * Requests a dead-name notification for a send
1272 * or receive right. If the name is already a
1273 * dead name, sync is non-zero, and a send-once
1274 * right is supplied, then an immediate dead-name
1275 * notification is generated.
1279 * KERN_SUCCESS Requested a notification.
1280 * KERN_INVALID_TASK The space is null.
1281 * KERN_INVALID_TASK The space is dead.
1282 * KERN_INVALID_VALUE Bad id value.
1283 * KERN_INVALID_NAME Name doesn't denote a right.
1284 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1285 * KERN_INVALID_CAPABILITY The notify port is dead.
1286 * MACH_NOTIFY_PORT_DESTROYED:
1287 * KERN_INVALID_VALUE Sync isn't zero.
1288 * MACH_NOTIFY_DEAD_NAME:
1289 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1290 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1291 * sync is zero or notify is IP_NULL.
1292 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1293 * generating immediate notif. would overflow urefs.
1297 mach_port_request_notification(
1299 mach_port_name_t name
,
1301 mach_port_mscount_t sync
,
1303 ipc_port_t
*previousp
)
1310 if (space
== IS_NULL
)
1311 return KERN_INVALID_TASK
;
1313 if (notify
== IP_DEAD
)
1314 return KERN_INVALID_CAPABILITY
;
1318 * Requesting notifications on RPC ports is an error.
1320 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1321 if (kr
!= KERN_SUCCESS
)
1324 port
= (ipc_port_t
) entry
->ie_object
;
1326 if (port
->ip_subsystem
!= NULL
) {
1327 is_write_unlock(space
);
1328 panic("mach_port_request_notification: on RPC port!!");
1329 return KERN_INVALID_CAPABILITY
;
1331 is_write_unlock(space
);
1336 case MACH_NOTIFY_PORT_DESTROYED
: {
1337 ipc_port_t port
, previous
;
1340 return KERN_INVALID_VALUE
;
1342 if (!MACH_PORT_VALID(name
))
1343 return KERN_INVALID_RIGHT
;
1345 kr
= ipc_port_translate_receive(space
, name
, &port
);
1346 if (kr
!= KERN_SUCCESS
)
1348 /* port is locked and active */
1350 ipc_port_pdrequest(port
, notify
, &previous
);
1351 /* port is unlocked */
1353 *previousp
= previous
;
1357 case MACH_NOTIFY_NO_SENDERS
: {
1360 if (!MACH_PORT_VALID(name
))
1361 return KERN_INVALID_RIGHT
;
1363 kr
= ipc_port_translate_receive(space
, name
, &port
);
1364 if (kr
!= KERN_SUCCESS
)
1366 /* port is locked and active */
1368 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1369 /* port is unlocked */
1373 case MACH_NOTIFY_DEAD_NAME
:
1375 if (!MACH_PORT_VALID(name
)) {
1378 * Should do immediate delivery check -
1379 * will do that in the near future.
1381 return KERN_INVALID_ARGUMENT
;
1384 kr
= ipc_right_dnrequest(space
, name
, sync
!= 0,
1386 if (kr
!= KERN_SUCCESS
)
1391 return KERN_INVALID_VALUE
;
1394 return KERN_SUCCESS
;
1398 * Routine: mach_port_insert_right [kernel call]
1400 * Inserts a right into a space, as if the space
1401 * voluntarily received the right in a message,
1402 * except that the right gets the specified name.
1406 * KERN_SUCCESS Inserted the right.
1407 * KERN_INVALID_TASK The space is null.
1408 * KERN_INVALID_TASK The space is dead.
1409 * KERN_INVALID_VALUE The name isn't a legal name.
1410 * KERN_NAME_EXISTS The name already denotes a right.
1411 * KERN_INVALID_VALUE Message doesn't carry a port right.
1412 * KERN_INVALID_CAPABILITY Port is null or dead.
1413 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1414 * KERN_RIGHT_EXISTS Space has rights under another name.
1415 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1419 mach_port_insert_right(
1421 mach_port_name_t name
,
1423 mach_msg_type_name_t polyPoly
)
1425 if (space
== IS_NULL
)
1426 return KERN_INVALID_TASK
;
1428 if (!MACH_PORT_VALID(name
) ||
1429 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1430 return KERN_INVALID_VALUE
;
1432 if (!IO_VALID((ipc_object_t
) poly
))
1433 return KERN_INVALID_CAPABILITY
;
1435 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1436 polyPoly
, FALSE
, name
);
1440 * Routine: mach_port_extract_right [kernel call]
1442 * Extracts a right from a space, as if the space
1443 * voluntarily sent the right to the caller.
1447 * KERN_SUCCESS Extracted the right.
1448 * KERN_INVALID_TASK The space is null.
1449 * KERN_INVALID_TASK The space is dead.
1450 * KERN_INVALID_VALUE Requested type isn't a port right.
1451 * KERN_INVALID_NAME Name doesn't denote a right.
1452 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1456 mach_port_extract_right(
1458 mach_port_name_t name
,
1459 mach_msg_type_name_t msgt_name
,
1461 mach_msg_type_name_t
*polyPoly
)
1465 if (space
== IS_NULL
)
1466 return KERN_INVALID_TASK
;
1468 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1469 return KERN_INVALID_VALUE
;
1471 if (!MACH_PORT_VALID(name
)) {
1473 * really should copy out a dead name, if it is a send or
1474 * send-once right being copied, but instead return an
1477 return KERN_INVALID_RIGHT
;
1480 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1482 if (kr
== KERN_SUCCESS
)
1483 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1489 mach_port_get_attributes(
1491 mach_port_name_t name
,
1493 mach_port_info_t info
,
1494 mach_msg_type_number_t
*count
)
1499 if (space
== IS_NULL
)
1500 return KERN_INVALID_TASK
;
1503 case MACH_PORT_LIMITS_INFO
: {
1504 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1506 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1507 return KERN_FAILURE
;
1509 if (!MACH_PORT_VALID(name
)) {
1514 kr
= ipc_port_translate_receive(space
, name
, &port
);
1515 if (kr
!= KERN_SUCCESS
)
1517 /* port is locked and active */
1519 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1520 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1525 case MACH_PORT_RECEIVE_STATUS
: {
1526 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1529 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1530 return KERN_FAILURE
;
1532 if (!MACH_PORT_VALID(name
))
1533 return KERN_INVALID_RIGHT
;
1535 kr
= ipc_port_translate_receive(space
, name
, &port
);
1536 if (kr
!= KERN_SUCCESS
)
1538 /* port is locked and active */
1540 statusp
->mps_pset
= port
->ip_pset_count
;
1543 imq_lock(&port
->ip_messages
);
1544 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1545 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1546 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1547 imq_unlock(&port
->ip_messages
);
1550 statusp
->mps_mscount
= port
->ip_mscount
;
1551 statusp
->mps_sorights
= port
->ip_sorights
;
1552 statusp
->mps_srights
= port
->ip_srights
> 0;
1553 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1554 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1555 statusp
->mps_flags
= 0;
1557 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1562 case MACH_PORT_DNREQUESTS_SIZE
: {
1563 ipc_port_request_t table
;
1565 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1566 return KERN_FAILURE
;
1568 if (!MACH_PORT_VALID(name
)) {
1573 kr
= ipc_port_translate_receive(space
, name
, &port
);
1574 if (kr
!= KERN_SUCCESS
)
1576 /* port is locked and active */
1578 table
= port
->ip_dnrequests
;
1579 if (table
== IPR_NULL
)
1582 *(int *)info
= table
->ipr_size
->its_size
;
1583 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1589 return KERN_INVALID_ARGUMENT
;
1593 return KERN_SUCCESS
;
1597 mach_port_set_attributes(
1599 mach_port_name_t name
,
1601 mach_port_info_t info
,
1602 mach_msg_type_number_t count
)
1607 if (space
== IS_NULL
)
1608 return KERN_INVALID_TASK
;
1612 case MACH_PORT_LIMITS_INFO
: {
1613 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1615 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1616 return KERN_FAILURE
;
1618 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1619 return KERN_INVALID_VALUE
;
1621 if (!MACH_PORT_VALID(name
))
1622 return KERN_INVALID_RIGHT
;
1624 kr
= ipc_port_translate_receive(space
, name
, &port
);
1625 if (kr
!= KERN_SUCCESS
)
1627 /* port is locked and active */
1629 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1633 case MACH_PORT_DNREQUESTS_SIZE
: {
1634 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1635 return KERN_FAILURE
;
1637 if (!MACH_PORT_VALID(name
))
1638 return KERN_INVALID_RIGHT
;
1640 kr
= ipc_port_translate_receive(space
, name
, &port
);
1641 if (kr
!= KERN_SUCCESS
)
1643 /* port is locked and active */
1645 kr
= ipc_port_dngrow(port
, *(int *)info
);
1646 if (kr
!= KERN_SUCCESS
)
1651 return KERN_INVALID_ARGUMENT
;
1654 return KERN_SUCCESS
;
1658 * Routine: mach_port_insert_member [kernel call]
1660 * Add the receive right, specified by name, to
1662 * The port cannot already be a member of the set.
1666 * KERN_SUCCESS Moved the port.
1667 * KERN_INVALID_TASK The space is null.
1668 * KERN_INVALID_TASK The space is dead.
1669 * KERN_INVALID_NAME name didn't denote a right.
1670 * KERN_INVALID_RIGHT name didn't denote a receive right.
1671 * KERN_INVALID_NAME pset_name didn't denote a right.
1672 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1673 * KERN_ALREADY_IN_SET name was already a member of pset.
1677 mach_port_insert_member(
1679 mach_port_name_t name
,
1680 mach_port_name_t psname
)
1686 if (space
== IS_NULL
)
1687 return KERN_INVALID_TASK
;
1689 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1690 return KERN_INVALID_RIGHT
;
1692 kr
= ipc_object_translate_two(space
,
1693 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1694 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1695 if (kr
!= KERN_SUCCESS
)
1698 /* obj and psobj are locked (and were locked in that order) */
1699 assert(psobj
!= IO_NULL
);
1700 assert(obj
!= IO_NULL
);
1702 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1709 * Routine: mach_port_extract_member [kernel call]
1711 * Remove a port from one portset that it is a member of.
1715 * KERN_SUCCESS Moved the port.
1716 * KERN_INVALID_TASK The space is null.
1717 * KERN_INVALID_TASK The space is dead.
1718 * KERN_INVALID_NAME Member didn't denote a right.
1719 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1720 * KERN_INVALID_NAME After didn't denote a right.
1721 * KERN_INVALID_RIGHT After didn't denote a port set right.
1723 * After is MACH_PORT_NULL and Member isn't in a port set.
1727 mach_port_extract_member(
1729 mach_port_name_t name
,
1730 mach_port_name_t psname
)
1732 mach_port_name_t oldname
;
1737 if (space
== IS_NULL
)
1738 return KERN_INVALID_TASK
;
1740 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1741 return KERN_INVALID_RIGHT
;
1743 kr
= ipc_object_translate_two(space
,
1744 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1745 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1746 if (kr
!= KERN_SUCCESS
)
1749 /* obj and psobj are both locked (and were locked in that order) */
1750 assert(psobj
!= IO_NULL
);
1751 assert(obj
!= IO_NULL
);
1753 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);