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@
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/mach_port.c
65 * Exported kernel calls. See mach/mach_port.defs.
68 #include <mach_debug.h>
71 #include <mach/port.h>
72 #include <mach/kern_return.h>
73 #include <mach/notify.h>
74 #include <mach/mach_param.h>
75 #include <mach/vm_param.h>
76 #include <mach/vm_prot.h>
77 #include <mach/vm_map.h>
78 #include <kern/task.h>
79 #include <kern/counters.h>
80 #include <kern/thread.h>
81 #include <kern/kalloc.h>
82 #include <mach/mach_port_server.h>
83 #include <vm/vm_map.h>
84 #include <vm/vm_kern.h>
85 #include <ipc/ipc_entry.h>
86 #include <ipc/ipc_space.h>
87 #include <ipc/ipc_object.h>
88 #include <ipc/ipc_notify.h>
89 #include <ipc/ipc_port.h>
90 #include <ipc/ipc_pset.h>
91 #include <ipc/ipc_right.h>
92 #include <ipc/ipc_kmsg.h>
93 #include <kern/misc_protos.h>
96 * Forward declarations
98 void mach_port_names_helper(
99 ipc_port_timestamp_t timestamp
,
101 mach_port_name_t name
,
102 mach_port_name_t
*names
,
103 mach_port_type_t
*types
,
104 ipc_entry_num_t
*actualp
);
106 void mach_port_gst_helper(
109 ipc_entry_num_t maxnames
,
110 mach_port_name_t
*names
,
111 ipc_entry_num_t
*actualp
);
114 /* Zeroed template of qos flags */
116 static mach_port_qos_t qos_template
;
119 * Routine: mach_port_names_helper
121 * A helper function for mach_port_names.
125 mach_port_names_helper(
126 ipc_port_timestamp_t timestamp
,
128 mach_port_name_t name
,
129 mach_port_name_t
*names
,
130 mach_port_type_t
*types
,
131 ipc_entry_num_t
*actualp
)
133 ipc_entry_bits_t bits
;
134 ipc_port_request_index_t request
;
135 mach_port_type_t type
;
136 ipc_entry_num_t actual
;
138 bits
= entry
->ie_bits
;
139 request
= entry
->ie_request
;
140 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
144 port
= (ipc_port_t
) entry
->ie_object
;
145 assert(port
!= IP_NULL
);
148 * The timestamp serializes mach_port_names
149 * with ipc_port_destroy. If the port died,
150 * but after mach_port_names started, pretend
151 * that it isn't dead.
155 died
= (!ip_active(port
) &&
156 IP_TIMESTAMP_ORDER(port
->ip_timestamp
, timestamp
));
160 /* pretend this is a dead-name entry */
162 bits
&= ~(IE_BITS_TYPE_MASK
);
163 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
170 type
= IE_BITS_TYPE(bits
);
172 type
|= MACH_PORT_TYPE_DNREQUEST
;
175 names
[actual
] = name
;
176 types
[actual
] = type
;
181 * Routine: mach_port_names [kernel call]
183 * Retrieves a list of the rights present in the space,
184 * along with type information. (Same as returned
185 * by mach_port_type.) The names are returned in
186 * no particular order, but they (and the type info)
187 * are an accurate snapshot of the space.
191 * KERN_SUCCESS Arrays of names and types returned.
192 * KERN_INVALID_TASK The space is null.
193 * KERN_INVALID_TASK The space is dead.
194 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
200 mach_port_name_t
**namesp
,
201 mach_msg_type_number_t
*namesCnt
,
202 mach_port_type_t
**typesp
,
203 mach_msg_type_number_t
*typesCnt
)
205 ipc_tree_entry_t tentry
;
207 ipc_entry_num_t tsize
;
208 mach_port_index_t index
;
209 ipc_entry_num_t actual
; /* this many names */
210 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
211 mach_port_name_t
*names
;
212 mach_port_type_t
*types
;
215 vm_size_t size
; /* size of allocated memory */
216 vm_offset_t addr1
; /* allocated memory, for names */
217 vm_offset_t addr2
; /* allocated memory, for types */
218 vm_map_copy_t memory1
; /* copied-in memory, for names */
219 vm_map_copy_t memory2
; /* copied-in memory, for types */
221 /* safe simplifying assumption */
222 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
224 if (space
== IS_NULL
)
225 return KERN_INVALID_TASK
;
230 ipc_entry_num_t bound
;
231 vm_size_t size_needed
;
234 if (!space
->is_active
) {
235 is_read_unlock(space
);
237 kmem_free(ipc_kernel_map
, addr1
, size
);
238 kmem_free(ipc_kernel_map
, addr2
, size
);
240 return KERN_INVALID_TASK
;
243 /* upper bound on number of names in the space */
245 bound
= space
->is_table_size
+ space
->is_tree_total
;
246 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
248 if (size_needed
<= size
)
251 is_read_unlock(space
);
254 kmem_free(ipc_kernel_map
, addr1
, size
);
255 kmem_free(ipc_kernel_map
, addr2
, size
);
259 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
260 if (kr
!= KERN_SUCCESS
)
261 return KERN_RESOURCE_SHORTAGE
;
263 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
264 if (kr
!= KERN_SUCCESS
) {
265 kmem_free(ipc_kernel_map
, addr1
, size
);
266 return KERN_RESOURCE_SHORTAGE
;
269 /* can't fault while we hold locks */
271 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
272 vm_map_round_page(addr1
+ size
),
273 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
274 if (kr
!= KERN_SUCCESS
) {
275 kmem_free(ipc_kernel_map
, addr1
, size
);
276 kmem_free(ipc_kernel_map
, addr2
, size
);
277 return KERN_RESOURCE_SHORTAGE
;
280 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
281 vm_map_round_page(addr2
+ size
),
282 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
283 if (kr
!= KERN_SUCCESS
) {
284 kmem_free(ipc_kernel_map
, addr1
, size
);
285 kmem_free(ipc_kernel_map
, addr2
, size
);
286 return KERN_RESOURCE_SHORTAGE
;
290 /* space is read-locked and active */
292 names
= (mach_port_name_t
*) addr1
;
293 types
= (mach_port_type_t
*) addr2
;
296 timestamp
= ipc_port_timestamp();
298 table
= space
->is_table
;
299 tsize
= space
->is_table_size
;
301 for (index
= 0; index
< tsize
; index
++) {
302 ipc_entry_t entry
= &table
[index
];
303 ipc_entry_bits_t bits
= entry
->ie_bits
;
305 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
306 mach_port_name_t name
;
308 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
309 mach_port_names_helper(timestamp
, entry
, name
, names
,
314 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
316 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
317 ipc_entry_t entry
= &tentry
->ite_entry
;
318 mach_port_name_t name
= tentry
->ite_name
;
320 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
321 mach_port_names_helper(timestamp
, entry
, name
, names
,
324 ipc_splay_traverse_finish(&space
->is_tree
);
325 is_read_unlock(space
);
328 memory1
= VM_MAP_COPY_NULL
;
329 memory2
= VM_MAP_COPY_NULL
;
332 kmem_free(ipc_kernel_map
, addr1
, size
);
333 kmem_free(ipc_kernel_map
, addr2
, size
);
337 vm_size_t vm_size_used
;
339 size_used
= actual
* sizeof(mach_port_name_t
);
340 vm_size_used
= round_page(size_used
);
343 * Make used memory pageable and get it into
344 * copied-in form. Free any unused memory.
347 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
348 vm_map_round_page(addr1
+ vm_size_used
), FALSE
);
349 assert(kr
== KERN_SUCCESS
);
351 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
352 vm_map_round_page(addr2
+ vm_size_used
), FALSE
);
353 assert(kr
== KERN_SUCCESS
);
355 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
356 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
357 assert(kr
== KERN_SUCCESS
);
359 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
360 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
361 assert(kr
== KERN_SUCCESS
);
363 if (vm_size_used
!= size
) {
364 kmem_free(ipc_kernel_map
,
365 addr1
+ vm_size_used
, size
- vm_size_used
);
366 kmem_free(ipc_kernel_map
,
367 addr2
+ vm_size_used
, size
- vm_size_used
);
371 *namesp
= (mach_port_name_t
*) memory1
;
373 *typesp
= (mach_port_type_t
*) memory2
;
379 * Routine: mach_port_type [kernel call]
381 * Retrieves the type of a right in the space.
382 * The type is a bitwise combination of one or more
383 * of the following type bits:
384 * MACH_PORT_TYPE_SEND
385 * MACH_PORT_TYPE_RECEIVE
386 * MACH_PORT_TYPE_SEND_ONCE
387 * MACH_PORT_TYPE_PORT_SET
388 * MACH_PORT_TYPE_DEAD_NAME
389 * In addition, the following pseudo-type bits may be present:
390 * MACH_PORT_TYPE_DNREQUEST
391 * A dead-name notification is requested.
395 * KERN_SUCCESS Type is returned.
396 * KERN_INVALID_TASK The space is null.
397 * KERN_INVALID_TASK The space is dead.
398 * KERN_INVALID_NAME The name doesn't denote a right.
404 mach_port_name_t name
,
405 mach_port_type_t
*typep
)
407 mach_port_urefs_t urefs
;
411 if (space
== IS_NULL
)
412 return KERN_INVALID_TASK
;
414 if (name
== MACH_PORT_NULL
)
415 return KERN_INVALID_NAME
;
417 if (name
== MACH_PORT_DEAD
) {
418 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
422 kr
= ipc_right_lookup_write(space
, name
, &entry
);
423 if (kr
!= KERN_SUCCESS
)
425 /* space is write-locked and active */
427 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
428 if (kr
== KERN_SUCCESS
)
429 is_write_unlock(space
);
430 /* space is unlocked */
435 * Routine: mach_port_rename [kernel call]
437 * Changes the name denoting a right,
438 * from oname to nname.
442 * KERN_SUCCESS The right is renamed.
443 * KERN_INVALID_TASK The space is null.
444 * KERN_INVALID_TASK The space is dead.
445 * KERN_INVALID_NAME The oname doesn't denote a right.
446 * KERN_INVALID_VALUE The nname isn't a legal name.
447 * KERN_NAME_EXISTS The nname already denotes a right.
448 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
454 mach_port_name_t oname
,
455 mach_port_name_t nname
)
457 if (space
== IS_NULL
)
458 return KERN_INVALID_TASK
;
460 if (!MACH_PORT_VALID(oname
))
461 return KERN_INVALID_NAME
;
463 if (!MACH_PORT_VALID(nname
))
464 return KERN_INVALID_VALUE
;
466 return ipc_object_rename(space
, oname
, nname
);
470 * Routine: mach_port_allocate_name [kernel call]
472 * Allocates a right in a space, using a specific name
473 * for the new right. Possible rights:
474 * MACH_PORT_RIGHT_RECEIVE
475 * MACH_PORT_RIGHT_PORT_SET
476 * MACH_PORT_RIGHT_DEAD_NAME
478 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
479 * has no extant send or send-once rights and no queued
480 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
481 * and its make-send count is 0. It is not a member of
482 * a port set. It has no registered no-senders or
483 * port-destroyed notification requests.
485 * A new port set has no members.
487 * A new dead name has one user reference.
491 * KERN_SUCCESS The right is allocated.
492 * KERN_INVALID_TASK The space is null.
493 * KERN_INVALID_TASK The space is dead.
494 * KERN_INVALID_VALUE The name isn't a legal name.
495 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
496 * KERN_NAME_EXISTS The name already denotes a right.
497 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
499 * Restrictions on name allocation: NT bits are reserved by kernel,
500 * must be set on any chosen name. Can't do this at all in kernel
505 mach_port_allocate_name(
507 mach_port_right_t right
,
508 mach_port_name_t name
)
511 mach_port_qos_t qos
= qos_template
;
515 if (!MACH_PORT_VALID(name
))
516 return KERN_INVALID_VALUE
;
518 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
524 * Routine: mach_port_allocate [kernel call]
526 * Allocates a right in a space. Like mach_port_allocate_name,
527 * except that the implementation picks a name for the right.
528 * The name may be any legal name in the space that doesn't
529 * currently denote a right.
533 * KERN_SUCCESS The right is allocated.
534 * KERN_INVALID_TASK The space is null.
535 * KERN_INVALID_TASK The space is dead.
536 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
537 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
538 * KERN_NO_SPACE No room in space for another right.
544 mach_port_right_t right
,
545 mach_port_name_t
*namep
)
548 mach_port_qos_t qos
= qos_template
;
550 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
556 * Routine: mach_port_allocate_qos [kernel call]
558 * Allocates a right, with qos options, in a space. Like
559 * mach_port_allocate_name, except that the implementation
560 * picks a name for the right. The name may be any legal name
561 * in the space that doesn't currently denote a right.
565 * KERN_SUCCESS The right is allocated.
566 * KERN_INVALID_TASK The space is null.
567 * KERN_INVALID_TASK The space is dead.
568 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
569 * KERN_INVALID_ARGUMENT The qos request was invalid.
570 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
571 * KERN_NO_SPACE No room in space for another right.
575 mach_port_allocate_qos(
577 mach_port_right_t right
,
578 mach_port_qos_t
*qosp
,
579 mach_port_name_t
*namep
)
584 return KERN_INVALID_ARGUMENT
;
585 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
591 * Routine: mach_port_allocate_full [kernel call]
593 * Allocates a right in a space. Supports all of the
594 * special cases, such as specifying a subsystem,
595 * a specific name, a real-time port, etc.
596 * The name may be any legal name in the space that doesn't
597 * currently denote a right.
601 * KERN_SUCCESS The right is allocated.
602 * KERN_INVALID_TASK The space is null.
603 * KERN_INVALID_TASK The space is dead.
604 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
605 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
606 * KERN_NO_SPACE No room in space for another right.
610 mach_port_allocate_full(
612 mach_port_right_t right
,
614 mach_port_qos_t
*qosp
,
615 mach_port_name_t
*namep
)
617 ipc_kmsg_t kmsg
= IKM_NULL
;
620 if (space
== IS_NULL
)
621 return (KERN_INVALID_TASK
);
623 if (proto
!= MACH_PORT_NULL
)
624 return (KERN_INVALID_VALUE
);
627 if (!MACH_PORT_VALID (*namep
))
628 return (KERN_INVALID_VALUE
);
629 if (is_fast_space (space
))
630 return (KERN_FAILURE
);
633 if (qosp
->prealloc
) {
634 if (qosp
->len
> MACH_MSG_SIZE_MAX
- MAX_TRAILER_SIZE
) {
635 return KERN_RESOURCE_SHORTAGE
;
637 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
638 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
639 return (KERN_INVALID_VALUE
);
640 kmsg
= (ipc_kmsg_t
)ipc_kmsg_alloc(size
);
641 if (kmsg
== IKM_NULL
)
642 return (KERN_RESOURCE_SHORTAGE
);
647 case MACH_PORT_RIGHT_RECEIVE
:
652 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
654 kr
= ipc_port_alloc(space
, namep
, &port
);
655 if (kr
== KERN_SUCCESS
) {
656 if (kmsg
!= IKM_NULL
)
657 ipc_kmsg_set_prealloc(kmsg
, port
);
661 } else if (kmsg
!= IKM_NULL
)
666 case MACH_PORT_RIGHT_PORT_SET
:
671 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
673 kr
= ipc_pset_alloc(space
, namep
, &pset
);
674 if (kr
== KERN_SUCCESS
)
679 case MACH_PORT_RIGHT_DEAD_NAME
:
680 kr
= ipc_object_alloc_dead(space
, namep
);
684 kr
= KERN_INVALID_VALUE
;
692 * Routine: mach_port_destroy [kernel call]
694 * Cleans up and destroys all rights denoted by a name
695 * in a space. The destruction of a receive right
696 * destroys the port, unless a port-destroyed request
697 * has been made for it; the destruction of a port-set right
698 * destroys the port set.
702 * KERN_SUCCESS The name is destroyed.
703 * KERN_INVALID_TASK The space is null.
704 * KERN_INVALID_TASK The space is dead.
705 * KERN_INVALID_NAME The name doesn't denote a right.
711 mach_port_name_t name
)
716 if (space
== IS_NULL
)
717 return KERN_INVALID_TASK
;
719 if (!MACH_PORT_VALID(name
))
722 kr
= ipc_right_lookup_write(space
, name
, &entry
);
723 if (kr
!= KERN_SUCCESS
)
725 /* space is write-locked and active */
727 kr
= ipc_right_destroy(space
, name
, entry
);
728 is_write_unlock(space
);
733 * Routine: mach_port_deallocate [kernel call]
735 * Deallocates a user reference from a send right,
736 * send-once right, or a dead-name right. May
737 * deallocate the right, if this is the last uref,
738 * and destroy the name, if it doesn't denote
743 * KERN_SUCCESS The uref is deallocated.
744 * KERN_INVALID_TASK The space is null.
745 * KERN_INVALID_TASK The space is dead.
746 * KERN_INVALID_NAME The name doesn't denote a right.
747 * KERN_INVALID_RIGHT The right isn't correct.
751 mach_port_deallocate(
753 mach_port_name_t name
)
758 if (space
== IS_NULL
)
759 return KERN_INVALID_TASK
;
761 if (!MACH_PORT_VALID(name
))
764 kr
= ipc_right_lookup_write(space
, name
, &entry
);
765 if (kr
!= KERN_SUCCESS
)
767 /* space is write-locked */
769 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
774 * Routine: mach_port_get_refs [kernel call]
776 * Retrieves the number of user references held by a right.
777 * Receive rights, port-set rights, and send-once rights
778 * always have one user reference. Returns zero if the
779 * name denotes a right, but not the queried right.
783 * KERN_SUCCESS Number of urefs returned.
784 * KERN_INVALID_TASK The space is null.
785 * KERN_INVALID_TASK The space is dead.
786 * KERN_INVALID_VALUE "right" isn't a legal value.
787 * KERN_INVALID_NAME The name doesn't denote a right.
793 mach_port_name_t name
,
794 mach_port_right_t right
,
795 mach_port_urefs_t
*urefsp
)
797 mach_port_type_t type
;
798 mach_port_urefs_t urefs
;
802 if (space
== IS_NULL
)
803 return KERN_INVALID_TASK
;
805 if (right
>= MACH_PORT_RIGHT_NUMBER
)
806 return KERN_INVALID_VALUE
;
808 if (!MACH_PORT_VALID(name
)) {
809 if (right
== MACH_PORT_RIGHT_SEND
||
810 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
814 return KERN_INVALID_NAME
;
817 kr
= ipc_right_lookup_write(space
, name
, &entry
);
818 if (kr
!= KERN_SUCCESS
)
820 /* space is write-locked and active */
822 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
823 if (kr
!= KERN_SUCCESS
)
824 return kr
; /* space is unlocked */
825 is_write_unlock(space
);
827 if (type
& MACH_PORT_TYPE(right
))
829 case MACH_PORT_RIGHT_SEND_ONCE
:
833 case MACH_PORT_RIGHT_PORT_SET
:
834 case MACH_PORT_RIGHT_RECEIVE
:
838 case MACH_PORT_RIGHT_DEAD_NAME
:
839 case MACH_PORT_RIGHT_SEND
:
845 panic("mach_port_get_refs: strange rights");
854 * Routine: mach_port_mod_refs
856 * Modifies the number of user references held by a right.
857 * The resulting number of user references must be non-negative.
858 * If it is zero, the right is deallocated. If the name
859 * doesn't denote other rights, it is destroyed.
863 * KERN_SUCCESS Modified number of urefs.
864 * KERN_INVALID_TASK The space is null.
865 * KERN_INVALID_TASK The space is dead.
866 * KERN_INVALID_VALUE "right" isn't a legal value.
867 * KERN_INVALID_NAME The name doesn't denote a right.
868 * KERN_INVALID_RIGHT Name doesn't denote specified right.
869 * KERN_INVALID_VALUE Impossible modification to urefs.
870 * KERN_UREFS_OVERFLOW Urefs would overflow.
876 mach_port_name_t name
,
877 mach_port_right_t right
,
878 mach_port_delta_t delta
)
883 if (space
== IS_NULL
)
884 return KERN_INVALID_TASK
;
886 if (right
>= MACH_PORT_RIGHT_NUMBER
)
887 return KERN_INVALID_VALUE
;
889 if (!MACH_PORT_VALID(name
)) {
890 if (right
== MACH_PORT_RIGHT_SEND
||
891 right
== MACH_PORT_RIGHT_SEND_ONCE
)
893 return KERN_INVALID_NAME
;
896 kr
= ipc_right_lookup_write(space
, name
, &entry
);
897 if (kr
!= KERN_SUCCESS
)
899 /* space is write-locked and active */
901 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
907 * Routine: mach_port_set_mscount [kernel call]
909 * Changes a receive right's make-send count.
913 * KERN_SUCCESS Set make-send count.
914 * KERN_INVALID_TASK The space is null.
915 * KERN_INVALID_TASK The space is dead.
916 * KERN_INVALID_NAME The name doesn't denote a right.
917 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
921 mach_port_set_mscount(
923 mach_port_name_t name
,
924 mach_port_mscount_t mscount
)
929 if (space
== IS_NULL
)
930 return KERN_INVALID_TASK
;
932 if (!MACH_PORT_VALID(name
))
933 return KERN_INVALID_RIGHT
;
935 kr
= ipc_port_translate_receive(space
, name
, &port
);
936 if (kr
!= KERN_SUCCESS
)
938 /* port is locked and active */
940 ipc_port_set_mscount(port
, mscount
);
947 * Routine: mach_port_set_seqno [kernel call]
949 * Changes a receive right's sequence number.
953 * KERN_SUCCESS Set sequence number.
954 * KERN_INVALID_TASK The space is null.
955 * KERN_INVALID_TASK The space is dead.
956 * KERN_INVALID_NAME The name doesn't denote a right.
957 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
963 mach_port_name_t name
,
964 mach_port_seqno_t seqno
)
969 if (space
== IS_NULL
)
970 return KERN_INVALID_TASK
;
972 if (!MACH_PORT_VALID(name
))
973 return KERN_INVALID_RIGHT
;
975 kr
= ipc_port_translate_receive(space
, name
, &port
);
976 if (kr
!= KERN_SUCCESS
)
978 /* port is locked and active */
980 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
987 * Routine: mach_port_gst_helper
989 * A helper function for mach_port_get_set_status.
993 mach_port_gst_helper(
996 ipc_entry_num_t maxnames
,
997 mach_port_name_t
*names
,
998 ipc_entry_num_t
*actualp
)
1000 mach_port_name_t name
;
1002 assert(port
!= IP_NULL
);
1005 assert(ip_active(port
));
1007 name
= port
->ip_receiver_name
;
1008 assert(name
!= MACH_PORT_NULL
);
1012 if (ipc_pset_member(pset
, port
)) {
1013 ipc_entry_num_t actual
= *actualp
;
1015 if (actual
< maxnames
)
1016 names
[actual
] = name
;
1018 *actualp
= actual
+1;
1023 * Routine: mach_port_get_set_status [kernel call]
1025 * Retrieves a list of members in a port set.
1026 * Returns the space's name for each receive right member.
1030 * KERN_SUCCESS Retrieved list of members.
1031 * KERN_INVALID_TASK The space is null.
1032 * KERN_INVALID_TASK The space is dead.
1033 * KERN_INVALID_NAME The name doesn't denote a right.
1034 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1035 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1039 mach_port_get_set_status(
1041 mach_port_name_t name
,
1042 mach_port_name_t
**members
,
1043 mach_msg_type_number_t
*membersCnt
)
1045 ipc_entry_num_t actual
; /* this many members */
1046 ipc_entry_num_t maxnames
; /* space for this many members */
1049 vm_size_t size
; /* size of allocated memory */
1050 vm_offset_t addr
; /* allocated memory */
1051 vm_map_copy_t memory
; /* copied-in memory */
1053 if (space
== IS_NULL
)
1054 return KERN_INVALID_TASK
;
1056 if (!MACH_PORT_VALID(name
))
1057 return KERN_INVALID_RIGHT
;
1059 size
= PAGE_SIZE
; /* initial guess */
1062 ipc_tree_entry_t tentry
;
1063 ipc_entry_t entry
, table
;
1064 ipc_entry_num_t tsize
;
1065 mach_port_index_t index
;
1066 mach_port_name_t
*names
;
1069 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1070 if (kr
!= KERN_SUCCESS
)
1071 return KERN_RESOURCE_SHORTAGE
;
1073 /* can't fault while we hold locks */
1075 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1076 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1077 assert(kr
== KERN_SUCCESS
);
1079 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1080 if (kr
!= KERN_SUCCESS
) {
1081 kmem_free(ipc_kernel_map
, addr
, size
);
1084 /* space is read-locked and active */
1086 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1087 is_read_unlock(space
);
1088 kmem_free(ipc_kernel_map
, addr
, size
);
1089 return KERN_INVALID_RIGHT
;
1092 pset
= (ipc_pset_t
) entry
->ie_object
;
1093 assert(pset
!= IPS_NULL
);
1094 /* the port set must be active */
1096 names
= (mach_port_name_t
*) addr
;
1097 maxnames
= size
/ sizeof(mach_port_name_t
);
1100 table
= space
->is_table
;
1101 tsize
= space
->is_table_size
;
1103 for (index
= 0; index
< tsize
; index
++) {
1104 ipc_entry_t ientry
= &table
[index
];
1106 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1108 (ipc_port_t
) ientry
->ie_object
;
1110 mach_port_gst_helper(pset
, port
,
1111 maxnames
, names
, &actual
);
1115 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1117 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1118 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1120 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1122 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1123 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1125 mach_port_gst_helper(pset
, port
, maxnames
,
1129 ipc_splay_traverse_finish(&space
->is_tree
);
1130 is_read_unlock(space
);
1132 if (actual
<= maxnames
)
1135 /* didn't have enough memory; allocate more */
1137 kmem_free(ipc_kernel_map
, addr
, size
);
1138 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1142 memory
= VM_MAP_COPY_NULL
;
1144 kmem_free(ipc_kernel_map
, addr
, size
);
1146 vm_size_t size_used
;
1147 vm_size_t vm_size_used
;
1149 size_used
= actual
* sizeof(mach_port_name_t
);
1150 vm_size_used
= round_page(size_used
);
1153 * Make used memory pageable and get it into
1154 * copied-in form. Free any unused memory.
1157 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr
),
1158 vm_map_round_page(addr
+ vm_size_used
), FALSE
);
1159 assert(kr
== KERN_SUCCESS
);
1161 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1162 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1163 assert(kr
== KERN_SUCCESS
);
1165 if (vm_size_used
!= size
)
1166 kmem_free(ipc_kernel_map
,
1167 addr
+ vm_size_used
, size
- vm_size_used
);
1170 *members
= (mach_port_name_t
*) memory
;
1171 *membersCnt
= actual
;
1172 return KERN_SUCCESS
;
1176 * Routine: mach_port_move_member [kernel call]
1178 * If after is MACH_PORT_NULL, removes member
1179 * from the port set it is in. Otherwise, adds
1180 * member to after, removing it from any set
1181 * it might already be in.
1185 * KERN_SUCCESS Moved the port.
1186 * KERN_INVALID_TASK The space is null.
1187 * KERN_INVALID_TASK The space is dead.
1188 * KERN_INVALID_NAME Member didn't denote a right.
1189 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1190 * KERN_INVALID_NAME After didn't denote a right.
1191 * KERN_INVALID_RIGHT After didn't denote a port set right.
1193 * After is MACH_PORT_NULL and Member isn't in a port set.
1197 mach_port_move_member(
1199 mach_port_name_t member
,
1200 mach_port_name_t after
)
1207 if (space
== IS_NULL
)
1208 return KERN_INVALID_TASK
;
1210 if (!MACH_PORT_VALID(member
))
1211 return KERN_INVALID_RIGHT
;
1213 if (after
== MACH_PORT_DEAD
)
1214 return KERN_INVALID_RIGHT
;
1216 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1217 if (kr
!= KERN_SUCCESS
)
1219 /* space is read-locked and active */
1221 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1222 is_read_unlock(space
);
1223 return KERN_INVALID_RIGHT
;
1226 port
= (ipc_port_t
) entry
->ie_object
;
1227 assert(port
!= IP_NULL
);
1229 if (after
== MACH_PORT_NULL
)
1232 entry
= ipc_entry_lookup(space
, after
);
1233 if (entry
== IE_NULL
) {
1234 is_read_unlock(space
);
1235 return KERN_INVALID_NAME
;
1238 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1239 is_read_unlock(space
);
1240 return KERN_INVALID_RIGHT
;
1243 nset
= (ipc_pset_t
) entry
->ie_object
;
1244 assert(nset
!= IPS_NULL
);
1247 ipc_pset_remove_from_all(port
);
1249 if (nset
!= IPS_NULL
) {
1251 kr
= ipc_pset_add(nset
, port
);
1255 is_read_unlock(space
);
1260 * Routine: mach_port_request_notification [kernel call]
1262 * Requests a notification. The caller supplies
1263 * a send-once right for the notification to use,
1264 * and the call returns the previously registered
1265 * send-once right, if any. Possible types:
1267 * MACH_NOTIFY_PORT_DESTROYED
1268 * Requests a port-destroyed notification
1269 * for a receive right. Sync should be zero.
1270 * MACH_NOTIFY_NO_SENDERS
1271 * Requests a no-senders notification for a
1272 * receive right. If there are currently no
1273 * senders, sync is less than or equal to the
1274 * current make-send count, and a send-once right
1275 * is supplied, then an immediate no-senders
1276 * notification is generated.
1277 * MACH_NOTIFY_DEAD_NAME
1278 * Requests a dead-name notification for a send
1279 * or receive right. If the name is already a
1280 * dead name, sync is non-zero, and a send-once
1281 * right is supplied, then an immediate dead-name
1282 * notification is generated.
1286 * KERN_SUCCESS Requested a notification.
1287 * KERN_INVALID_TASK The space is null.
1288 * KERN_INVALID_TASK The space is dead.
1289 * KERN_INVALID_VALUE Bad id value.
1290 * KERN_INVALID_NAME Name doesn't denote a right.
1291 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1292 * KERN_INVALID_CAPABILITY The notify port is dead.
1293 * MACH_NOTIFY_PORT_DESTROYED:
1294 * KERN_INVALID_VALUE Sync isn't zero.
1295 * MACH_NOTIFY_DEAD_NAME:
1296 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1297 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1298 * sync is zero or notify is IP_NULL.
1299 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1300 * generating immediate notif. would overflow urefs.
1304 mach_port_request_notification(
1306 mach_port_name_t name
,
1308 mach_port_mscount_t sync
,
1310 ipc_port_t
*previousp
)
1314 if (space
== IS_NULL
)
1315 return KERN_INVALID_TASK
;
1317 if (notify
== IP_DEAD
)
1318 return KERN_INVALID_CAPABILITY
;
1322 * Requesting notifications on RPC ports is an error.
1328 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1329 if (kr
!= KERN_SUCCESS
)
1332 port
= (ipc_port_t
) entry
->ie_object
;
1334 if (port
->ip_subsystem
!= NULL
) {
1335 is_write_unlock(space
);
1336 panic("mach_port_request_notification: on RPC port!!");
1337 return KERN_INVALID_CAPABILITY
;
1339 is_write_unlock(space
);
1345 case MACH_NOTIFY_PORT_DESTROYED
: {
1346 ipc_port_t port
, previous
;
1349 return KERN_INVALID_VALUE
;
1351 if (!MACH_PORT_VALID(name
))
1352 return KERN_INVALID_RIGHT
;
1354 kr
= ipc_port_translate_receive(space
, name
, &port
);
1355 if (kr
!= KERN_SUCCESS
)
1357 /* port is locked and active */
1359 ipc_port_pdrequest(port
, notify
, &previous
);
1360 /* port is unlocked */
1362 *previousp
= previous
;
1366 case MACH_NOTIFY_NO_SENDERS
: {
1369 if (!MACH_PORT_VALID(name
))
1370 return KERN_INVALID_RIGHT
;
1372 kr
= ipc_port_translate_receive(space
, name
, &port
);
1373 if (kr
!= KERN_SUCCESS
)
1375 /* port is locked and active */
1377 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1378 /* port is unlocked */
1382 case MACH_NOTIFY_DEAD_NAME
:
1384 if (!MACH_PORT_VALID(name
)) {
1387 * Should do immediate delivery check -
1388 * will do that in the near future.
1390 return KERN_INVALID_ARGUMENT
;
1393 kr
= ipc_right_dnrequest(space
, name
, sync
!= 0,
1395 if (kr
!= KERN_SUCCESS
)
1400 return KERN_INVALID_VALUE
;
1403 return KERN_SUCCESS
;
1407 * Routine: mach_port_insert_right [kernel call]
1409 * Inserts a right into a space, as if the space
1410 * voluntarily received the right in a message,
1411 * except that the right gets the specified name.
1415 * KERN_SUCCESS Inserted the right.
1416 * KERN_INVALID_TASK The space is null.
1417 * KERN_INVALID_TASK The space is dead.
1418 * KERN_INVALID_VALUE The name isn't a legal name.
1419 * KERN_NAME_EXISTS The name already denotes a right.
1420 * KERN_INVALID_VALUE Message doesn't carry a port right.
1421 * KERN_INVALID_CAPABILITY Port is null or dead.
1422 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1423 * KERN_RIGHT_EXISTS Space has rights under another name.
1424 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1428 mach_port_insert_right(
1430 mach_port_name_t name
,
1432 mach_msg_type_name_t polyPoly
)
1434 if (space
== IS_NULL
)
1435 return KERN_INVALID_TASK
;
1437 if (!MACH_PORT_VALID(name
) ||
1438 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1439 return KERN_INVALID_VALUE
;
1441 if (!IO_VALID((ipc_object_t
) poly
))
1442 return KERN_INVALID_CAPABILITY
;
1444 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1445 polyPoly
, FALSE
, name
);
1449 * Routine: mach_port_extract_right [kernel call]
1451 * Extracts a right from a space, as if the space
1452 * voluntarily sent the right to the caller.
1456 * KERN_SUCCESS Extracted the right.
1457 * KERN_INVALID_TASK The space is null.
1458 * KERN_INVALID_TASK The space is dead.
1459 * KERN_INVALID_VALUE Requested type isn't a port right.
1460 * KERN_INVALID_NAME Name doesn't denote a right.
1461 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1465 mach_port_extract_right(
1467 mach_port_name_t name
,
1468 mach_msg_type_name_t msgt_name
,
1470 mach_msg_type_name_t
*polyPoly
)
1474 if (space
== IS_NULL
)
1475 return KERN_INVALID_TASK
;
1477 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1478 return KERN_INVALID_VALUE
;
1480 if (!MACH_PORT_VALID(name
)) {
1482 * really should copy out a dead name, if it is a send or
1483 * send-once right being copied, but instead return an
1486 return KERN_INVALID_RIGHT
;
1489 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1491 if (kr
== KERN_SUCCESS
)
1492 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1498 mach_port_get_attributes(
1500 mach_port_name_t name
,
1502 mach_port_info_t info
,
1503 mach_msg_type_number_t
*count
)
1508 if (space
== IS_NULL
)
1509 return KERN_INVALID_TASK
;
1512 case MACH_PORT_LIMITS_INFO
: {
1513 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1515 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1516 return KERN_FAILURE
;
1518 if (!MACH_PORT_VALID(name
)) {
1523 kr
= ipc_port_translate_receive(space
, name
, &port
);
1524 if (kr
!= KERN_SUCCESS
)
1526 /* port is locked and active */
1528 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1529 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1534 case MACH_PORT_RECEIVE_STATUS
: {
1535 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1538 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1539 return KERN_FAILURE
;
1541 if (!MACH_PORT_VALID(name
))
1542 return KERN_INVALID_RIGHT
;
1544 kr
= ipc_port_translate_receive(space
, name
, &port
);
1545 if (kr
!= KERN_SUCCESS
)
1547 /* port is locked and active */
1549 statusp
->mps_pset
= port
->ip_pset_count
;
1552 imq_lock(&port
->ip_messages
);
1553 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1554 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1555 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1556 imq_unlock(&port
->ip_messages
);
1559 statusp
->mps_mscount
= port
->ip_mscount
;
1560 statusp
->mps_sorights
= port
->ip_sorights
;
1561 statusp
->mps_srights
= port
->ip_srights
> 0;
1562 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1563 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1564 statusp
->mps_flags
= 0;
1566 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1571 case MACH_PORT_DNREQUESTS_SIZE
: {
1572 ipc_port_request_t table
;
1574 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1575 return KERN_FAILURE
;
1577 if (!MACH_PORT_VALID(name
)) {
1582 kr
= ipc_port_translate_receive(space
, name
, &port
);
1583 if (kr
!= KERN_SUCCESS
)
1585 /* port is locked and active */
1587 table
= port
->ip_dnrequests
;
1588 if (table
== IPR_NULL
)
1591 *(int *)info
= table
->ipr_size
->its_size
;
1592 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1598 return KERN_INVALID_ARGUMENT
;
1602 return KERN_SUCCESS
;
1606 mach_port_set_attributes(
1608 mach_port_name_t name
,
1610 mach_port_info_t info
,
1611 mach_msg_type_number_t count
)
1616 if (space
== IS_NULL
)
1617 return KERN_INVALID_TASK
;
1621 case MACH_PORT_LIMITS_INFO
: {
1622 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1624 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1625 return KERN_FAILURE
;
1627 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1628 return KERN_INVALID_VALUE
;
1630 if (!MACH_PORT_VALID(name
))
1631 return KERN_INVALID_RIGHT
;
1633 kr
= ipc_port_translate_receive(space
, name
, &port
);
1634 if (kr
!= KERN_SUCCESS
)
1636 /* port is locked and active */
1638 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1642 case MACH_PORT_DNREQUESTS_SIZE
: {
1643 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1644 return KERN_FAILURE
;
1646 if (!MACH_PORT_VALID(name
))
1647 return KERN_INVALID_RIGHT
;
1649 kr
= ipc_port_translate_receive(space
, name
, &port
);
1650 if (kr
!= KERN_SUCCESS
)
1652 /* port is locked and active */
1654 kr
= ipc_port_dngrow(port
, *(int *)info
);
1655 if (kr
!= KERN_SUCCESS
)
1660 return KERN_INVALID_ARGUMENT
;
1663 return KERN_SUCCESS
;
1667 * Routine: mach_port_insert_member [kernel call]
1669 * Add the receive right, specified by name, to
1671 * The port cannot already be a member of the set.
1675 * KERN_SUCCESS Moved the port.
1676 * KERN_INVALID_TASK The space is null.
1677 * KERN_INVALID_TASK The space is dead.
1678 * KERN_INVALID_NAME name didn't denote a right.
1679 * KERN_INVALID_RIGHT name didn't denote a receive right.
1680 * KERN_INVALID_NAME pset_name didn't denote a right.
1681 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1682 * KERN_ALREADY_IN_SET name was already a member of pset.
1686 mach_port_insert_member(
1688 mach_port_name_t name
,
1689 mach_port_name_t psname
)
1695 if (space
== IS_NULL
)
1696 return KERN_INVALID_TASK
;
1698 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1699 return KERN_INVALID_RIGHT
;
1701 kr
= ipc_object_translate_two(space
,
1702 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1703 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1704 if (kr
!= KERN_SUCCESS
)
1707 /* obj and psobj are locked (and were locked in that order) */
1708 assert(psobj
!= IO_NULL
);
1709 assert(obj
!= IO_NULL
);
1711 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1718 * Routine: mach_port_extract_member [kernel call]
1720 * Remove a port from one portset that it is a member of.
1724 * KERN_SUCCESS Moved the port.
1725 * KERN_INVALID_TASK The space is null.
1726 * KERN_INVALID_TASK The space is dead.
1727 * KERN_INVALID_NAME Member didn't denote a right.
1728 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1729 * KERN_INVALID_NAME After didn't denote a right.
1730 * KERN_INVALID_RIGHT After didn't denote a port set right.
1732 * After is MACH_PORT_NULL and Member isn't in a port set.
1736 mach_port_extract_member(
1738 mach_port_name_t name
,
1739 mach_port_name_t psname
)
1745 if (space
== IS_NULL
)
1746 return KERN_INVALID_TASK
;
1748 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1749 return KERN_INVALID_RIGHT
;
1751 kr
= ipc_object_translate_two(space
,
1752 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1753 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1754 if (kr
!= KERN_SUCCESS
)
1757 /* obj and psobj are both locked (and were locked in that order) */
1758 assert(psobj
!= IO_NULL
);
1759 assert(obj
!= IO_NULL
);
1761 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1768 * task_set_port_space:
1770 * Set port name space of task to specified size.
1773 task_set_port_space(
1779 is_write_lock(space
);
1780 kr
= ipc_entry_grow_table(space
, table_entries
);
1781 if (kr
== KERN_SUCCESS
)
1782 is_write_unlock(space
);