2 * Copyright (c) 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@
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/mach_port.c
57 * Exported kernel calls. See mach/mach_port.defs.
60 #include <mach_debug.h>
63 #include <mach/port.h>
64 #include <mach/kern_return.h>
65 #include <mach/notify.h>
66 #include <mach/mach_param.h>
67 #include <mach/vm_param.h>
68 #include <mach/vm_prot.h>
69 #include <mach/vm_map.h>
70 #include <kern/task.h>
71 #include <kern/counters.h>
72 #include <kern/thread_act.h>
73 #include <kern/thread_pool.h>
74 #include <mach/mach_port_server.h>
75 #include <vm/vm_map.h>
76 #include <vm/vm_kern.h>
77 #include <ipc/ipc_entry.h>
78 #include <ipc/ipc_space.h>
79 #include <ipc/ipc_object.h>
80 #include <ipc/ipc_notify.h>
81 #include <ipc/ipc_port.h>
82 #include <ipc/ipc_pset.h>
83 #include <ipc/ipc_right.h>
84 #include <ipc/ipc_kmsg.h>
85 #include <kern/misc_protos.h>
88 * Forward declarations
90 void mach_port_names_helper(
91 ipc_port_timestamp_t timestamp
,
93 mach_port_name_t name
,
94 mach_port_name_t
*names
,
95 mach_port_type_t
*types
,
96 ipc_entry_num_t
*actualp
,
99 void mach_port_gst_helper(
102 ipc_entry_num_t maxnames
,
103 mach_port_name_t
*names
,
104 ipc_entry_num_t
*actualp
);
107 /* Zeroed template of qos flags */
109 static mach_port_qos_t qos_template
;
112 * Routine: mach_port_names_helper
114 * A helper function for mach_port_names.
118 mach_port_names_helper(
119 ipc_port_timestamp_t timestamp
,
121 mach_port_name_t name
,
122 mach_port_name_t
*names
,
123 mach_port_type_t
*types
,
124 ipc_entry_num_t
*actualp
,
127 ipc_entry_bits_t bits
;
128 ipc_port_request_index_t request
;
129 mach_port_type_t type
;
130 ipc_entry_num_t actual
;
132 bits
= entry
->ie_bits
;
133 request
= entry
->ie_request
;
134 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
138 port
= (ipc_port_t
) entry
->ie_object
;
139 assert(port
!= IP_NULL
);
142 * The timestamp serializes mach_port_names
143 * with ipc_port_destroy. If the port died,
144 * but after mach_port_names started, pretend
145 * that it isn't dead.
149 died
= (!ip_active(port
) &&
150 IP_TIMESTAMP_ORDER(port
->ip_timestamp
, timestamp
));
154 /* pretend this is a dead-name entry */
156 bits
&= ~(IE_BITS_TYPE_MASK
);
157 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
164 type
= IE_BITS_TYPE(bits
);
166 type
|= MACH_PORT_TYPE_DNREQUEST
;
169 names
[actual
] = name
;
170 types
[actual
] = type
;
175 * Routine: mach_port_names [kernel call]
177 * Retrieves a list of the rights present in the space,
178 * along with type information. (Same as returned
179 * by mach_port_type.) The names are returned in
180 * no particular order, but they (and the type info)
181 * are an accurate snapshot of the space.
185 * KERN_SUCCESS Arrays of names and types returned.
186 * KERN_INVALID_TASK The space is null.
187 * KERN_INVALID_TASK The space is dead.
188 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
194 mach_port_name_t
**namesp
,
195 mach_msg_type_number_t
*namesCnt
,
196 mach_port_type_t
**typesp
,
197 mach_msg_type_number_t
*typesCnt
)
199 ipc_entry_bits_t
*capability
;
200 ipc_tree_entry_t tentry
;
202 ipc_entry_num_t tsize
;
203 mach_port_index_t index
;
204 ipc_entry_num_t actual
; /* this many names */
205 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
206 mach_port_name_t
*names
;
207 mach_port_type_t
*types
;
210 vm_size_t size
; /* size of allocated memory */
211 vm_offset_t addr1
; /* allocated memory, for names */
212 vm_offset_t addr2
; /* allocated memory, for types */
213 vm_map_copy_t memory1
; /* copied-in memory, for names */
214 vm_map_copy_t memory2
; /* copied-in memory, for types */
216 /* safe simplifying assumption */
217 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
219 if (space
== IS_NULL
)
220 return KERN_INVALID_TASK
;
225 ipc_entry_num_t bound
;
226 vm_size_t size_needed
;
229 if (!space
->is_active
) {
230 is_read_unlock(space
);
232 kmem_free(ipc_kernel_map
, addr1
, size
);
233 kmem_free(ipc_kernel_map
, addr2
, size
);
235 return KERN_INVALID_TASK
;
238 /* upper bound on number of names in the space */
240 bound
= space
->is_table_size
+ space
->is_tree_total
;
241 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
243 if (size_needed
<= size
)
246 is_read_unlock(space
);
249 kmem_free(ipc_kernel_map
, addr1
, size
);
250 kmem_free(ipc_kernel_map
, addr2
, size
);
254 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, TRUE
);
255 if (kr
!= KERN_SUCCESS
)
256 return KERN_RESOURCE_SHORTAGE
;
258 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, TRUE
);
259 if (kr
!= KERN_SUCCESS
) {
260 kmem_free(ipc_kernel_map
, addr1
, size
);
261 return KERN_RESOURCE_SHORTAGE
;
264 /* can't fault while we hold locks */
266 kr
= vm_map_wire(ipc_kernel_map
, addr1
, addr1
+ size
,
267 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
268 assert(kr
== KERN_SUCCESS
);
270 kr
= vm_map_wire(ipc_kernel_map
, addr2
, addr2
+ size
,
271 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
272 assert(kr
== KERN_SUCCESS
);
274 /* space is read-locked and active */
276 names
= (mach_port_name_t
*) addr1
;
277 types
= (mach_port_type_t
*) addr2
;
280 timestamp
= ipc_port_timestamp();
282 table
= space
->is_table
;
283 tsize
= space
->is_table_size
;
285 for (index
= 0; index
< tsize
; index
++) {
286 ipc_entry_t entry
= &table
[index
];
287 ipc_entry_bits_t bits
= entry
->ie_bits
;
289 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
290 mach_port_name_t name
;
292 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
293 mach_port_names_helper(timestamp
, entry
, name
, names
,
294 types
, &actual
, space
);
298 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
300 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
301 ipc_entry_t entry
= &tentry
->ite_entry
;
302 mach_port_name_t name
= tentry
->ite_name
;
304 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
305 mach_port_names_helper(timestamp
, entry
, name
, names
,
306 types
, &actual
, space
);
308 ipc_splay_traverse_finish(&space
->is_tree
);
309 is_read_unlock(space
);
312 memory1
= VM_MAP_COPY_NULL
;
313 memory2
= VM_MAP_COPY_NULL
;
316 kmem_free(ipc_kernel_map
, addr1
, size
);
317 kmem_free(ipc_kernel_map
, addr2
, size
);
321 vm_size_t vm_size_used
;
323 size_used
= actual
* sizeof(mach_port_name_t
);
324 vm_size_used
= round_page(size_used
);
327 * Make used memory pageable and get it into
328 * copied-in form. Free any unused memory.
331 kr
= vm_map_unwire(ipc_kernel_map
,
332 addr1
, addr1
+ vm_size_used
, FALSE
);
333 assert(kr
== KERN_SUCCESS
);
335 kr
= vm_map_unwire(ipc_kernel_map
,
336 addr2
, addr2
+ vm_size_used
, FALSE
);
337 assert(kr
== KERN_SUCCESS
);
339 kr
= vm_map_copyin(ipc_kernel_map
, addr1
, size_used
,
341 assert(kr
== KERN_SUCCESS
);
343 kr
= vm_map_copyin(ipc_kernel_map
, addr2
, size_used
,
345 assert(kr
== KERN_SUCCESS
);
347 if (vm_size_used
!= size
) {
348 kmem_free(ipc_kernel_map
,
349 addr1
+ vm_size_used
, size
- vm_size_used
);
350 kmem_free(ipc_kernel_map
,
351 addr2
+ vm_size_used
, size
- vm_size_used
);
355 *namesp
= (mach_port_name_t
*) memory1
;
357 *typesp
= (mach_port_type_t
*) memory2
;
363 * Routine: mach_port_type [kernel call]
365 * Retrieves the type of a right in the space.
366 * The type is a bitwise combination of one or more
367 * of the following type bits:
368 * MACH_PORT_TYPE_SEND
369 * MACH_PORT_TYPE_RECEIVE
370 * MACH_PORT_TYPE_SEND_ONCE
371 * MACH_PORT_TYPE_PORT_SET
372 * MACH_PORT_TYPE_DEAD_NAME
373 * In addition, the following pseudo-type bits may be present:
374 * MACH_PORT_TYPE_DNREQUEST
375 * A dead-name notification is requested.
379 * KERN_SUCCESS Type is returned.
380 * KERN_INVALID_TASK The space is null.
381 * KERN_INVALID_TASK The space is dead.
382 * KERN_INVALID_NAME The name doesn't denote a right.
388 mach_port_name_t name
,
389 mach_port_type_t
*typep
)
391 mach_port_urefs_t urefs
;
395 if (space
== IS_NULL
)
396 return KERN_INVALID_TASK
;
398 if (name
== MACH_PORT_NULL
)
399 return KERN_INVALID_NAME
;
401 if (name
== MACH_PORT_DEAD
) {
402 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
406 kr
= ipc_right_lookup_write(space
, name
, &entry
);
407 if (kr
!= KERN_SUCCESS
)
409 /* space is write-locked and active */
411 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
412 if (kr
== KERN_SUCCESS
)
413 is_write_unlock(space
);
414 /* space is unlocked */
419 * Routine: mach_port_rename [kernel call]
421 * Changes the name denoting a right,
422 * from oname to nname.
426 * KERN_SUCCESS The right is renamed.
427 * KERN_INVALID_TASK The space is null.
428 * KERN_INVALID_TASK The space is dead.
429 * KERN_INVALID_NAME The oname doesn't denote a right.
430 * KERN_INVALID_VALUE The nname isn't a legal name.
431 * KERN_NAME_EXISTS The nname already denotes a right.
432 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
438 mach_port_name_t oname
,
439 mach_port_name_t nname
)
441 if (space
== IS_NULL
)
442 return KERN_INVALID_TASK
;
444 if (!MACH_PORT_VALID(oname
))
445 return KERN_INVALID_NAME
;
447 if (!MACH_PORT_VALID(nname
))
448 return KERN_INVALID_VALUE
;
450 return ipc_object_rename(space
, oname
, nname
);
454 * Routine: mach_port_allocate_name [kernel call]
456 * Allocates a right in a space, using a specific name
457 * for the new right. Possible rights:
458 * MACH_PORT_RIGHT_RECEIVE
459 * MACH_PORT_RIGHT_PORT_SET
460 * MACH_PORT_RIGHT_DEAD_NAME
462 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
463 * has no extant send or send-once rights and no queued
464 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
465 * and its make-send count is 0. It is not a member of
466 * a port set. It has no registered no-senders or
467 * port-destroyed notification requests.
469 * A new port set has no members.
471 * A new dead name has one user reference.
475 * KERN_SUCCESS The right is allocated.
476 * KERN_INVALID_TASK The space is null.
477 * KERN_INVALID_TASK The space is dead.
478 * KERN_INVALID_VALUE The name isn't a legal name.
479 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
480 * KERN_NAME_EXISTS The name already denotes a right.
481 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
483 * Restrictions on name allocation: NT bits are reserved by kernel,
484 * must be set on any chosen name. Can't do this at all in kernel
489 mach_port_allocate_name(
491 mach_port_right_t right
,
492 mach_port_name_t name
)
495 mach_port_qos_t qos
= qos_template
;
499 if (!MACH_PORT_VALID(name
))
500 return KERN_INVALID_VALUE
;
502 kr
= mach_port_allocate_full (space
, right
, SUBSYSTEM_NULL
,
508 * Routine: mach_port_allocate [kernel call]
510 * Allocates a right in a space. Like mach_port_allocate_name,
511 * except that the implementation picks a name for the right.
512 * The name may be any legal name in the space that doesn't
513 * currently denote a right.
517 * KERN_SUCCESS The right is allocated.
518 * KERN_INVALID_TASK The space is null.
519 * KERN_INVALID_TASK The space is dead.
520 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
521 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
522 * KERN_NO_SPACE No room in space for another right.
528 mach_port_right_t right
,
529 mach_port_name_t
*namep
)
532 mach_port_qos_t qos
= qos_template
;
534 kr
= mach_port_allocate_full (space
, right
, SUBSYSTEM_NULL
,
540 * Routine: mach_port_allocate_qos [kernel call]
542 * Allocates a right, with qos options, in a space. Like
543 * mach_port_allocate_name, except that the implementation
544 * picks a name for the right. The name may be any legal name
545 * in the space that doesn't currently denote a right.
549 * KERN_SUCCESS The right is allocated.
550 * KERN_INVALID_TASK The space is null.
551 * KERN_INVALID_TASK The space is dead.
552 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
553 * KERN_INVALID_ARGUMENT The qos request was invalid.
554 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
555 * KERN_NO_SPACE No room in space for another right.
559 mach_port_allocate_qos(
561 mach_port_right_t right
,
562 mach_port_qos_t
*qosp
,
563 mach_port_name_t
*namep
)
567 if (qosp
->name
== TRUE
)
568 return KERN_INVALID_ARGUMENT
;
569 kr
= mach_port_allocate_full (space
, right
, SUBSYSTEM_NULL
,
575 * Routine: mach_port_allocate_subsystem [kernel call]
577 * Allocates a receive right in a space. Like
578 * mach_port_allocate, except that the caller specifies an
579 * RPC subsystem that is to be used to implement RPC's to the
580 * port. When possible, allocate rpc subsystem ports without
581 * nms, since within RPC ports are intended to be used for
582 * identity only (i.e. nms is painful in the distributed case
583 * and we don't need or want it for RPC anyway).
587 * KERN_SUCCESS The right is allocated.
588 * KERN_INVALID_TASK The space is null.
589 * KERN_INVALID_TASK The space is dead.
590 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
591 * KERN_NO_SPACE No room in space for another right.
592 * KERN_INVALID_ARGUMENT bogus subsystem
596 mach_port_allocate_subsystem(
598 subsystem_t subsystem
,
599 mach_port_name_t
*namep
)
603 mach_port_qos_t qos
= qos_template
;
605 kr
= mach_port_allocate_full (space
,
606 MACH_PORT_RIGHT_RECEIVE
,
607 subsystem
, &qos
, namep
);
612 * Routine: mach_port_allocate_full [kernel call]
614 * Allocates a right in a space. Supports all of the
615 * special cases, such as specifying a subsystem,
616 * a specific name, a real-time port, etc.
617 * The name may be any legal name in the space that doesn't
618 * currently denote a right.
622 * KERN_SUCCESS The right is allocated.
623 * KERN_INVALID_TASK The space is null.
624 * KERN_INVALID_TASK The space is dead.
625 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
626 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
627 * KERN_NO_SPACE No room in space for another right.
631 mach_port_allocate_full(
633 mach_port_right_t right
,
634 subsystem_t subsystem
,
635 mach_port_qos_t
*qosp
,
636 mach_port_name_t
*namep
)
641 if (space
== IS_NULL
)
642 return (KERN_INVALID_TASK
);
645 if (!MACH_PORT_VALID (*namep
))
646 return (KERN_INVALID_VALUE
);
647 if (is_fast_space (space
))
648 return (KERN_FAILURE
);
651 if (subsystem
!= SUBSYSTEM_NULL
) {
652 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
653 return (KERN_INVALID_VALUE
);
656 if (qosp
->prealloc
) {
657 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
658 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
659 return (KERN_INVALID_VALUE
);
660 kmsg
= (ipc_kmsg_t
)kalloc(ikm_plus_overhead(size
));
661 if (kmsg
== IKM_NULL
)
662 return (KERN_RESOURCE_SHORTAGE
);
663 ikm_init(kmsg
, size
);
667 case MACH_PORT_RIGHT_RECEIVE
:
672 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
674 kr
= ipc_port_alloc(space
, namep
, &port
);
675 if (kr
== KERN_SUCCESS
) {
677 ipc_kmsg_set_prealloc(kmsg
, port
);
679 if (subsystem
!= SUBSYSTEM_NULL
) {
680 port
->ip_subsystem
= &subsystem
->user
;
681 subsystem_reference (subsystem
);
685 } else if (qosp
->prealloc
)
690 case MACH_PORT_RIGHT_PORT_SET
:
695 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
697 kr
= ipc_pset_alloc(space
, namep
, &pset
);
698 if (kr
== KERN_SUCCESS
)
703 case MACH_PORT_RIGHT_DEAD_NAME
:
704 kr
= ipc_object_alloc_dead(space
, namep
);
708 kr
= KERN_INVALID_VALUE
;
716 * Routine: mach_port_destroy [kernel call]
718 * Cleans up and destroys all rights denoted by a name
719 * in a space. The destruction of a receive right
720 * destroys the port, unless a port-destroyed request
721 * has been made for it; the destruction of a port-set right
722 * destroys the port set.
726 * KERN_SUCCESS The name is destroyed.
727 * KERN_INVALID_TASK The space is null.
728 * KERN_INVALID_TASK The space is dead.
729 * KERN_INVALID_NAME The name doesn't denote a right.
735 mach_port_name_t name
)
740 if (space
== IS_NULL
)
741 return KERN_INVALID_TASK
;
743 if (!MACH_PORT_VALID(name
))
746 kr
= ipc_right_lookup_write(space
, name
, &entry
);
747 if (kr
!= KERN_SUCCESS
)
749 /* space is write-locked and active */
751 kr
= ipc_right_destroy(space
, name
, entry
);
752 is_write_unlock(space
);
757 * Routine: mach_port_deallocate [kernel call]
759 * Deallocates a user reference from a send right,
760 * send-once right, or a dead-name right. May
761 * deallocate the right, if this is the last uref,
762 * and destroy the name, if it doesn't denote
767 * KERN_SUCCESS The uref is deallocated.
768 * KERN_INVALID_TASK The space is null.
769 * KERN_INVALID_TASK The space is dead.
770 * KERN_INVALID_NAME The name doesn't denote a right.
771 * KERN_INVALID_RIGHT The right isn't correct.
775 mach_port_deallocate(
777 mach_port_name_t name
)
782 if (space
== IS_NULL
)
783 return KERN_INVALID_TASK
;
785 if (!MACH_PORT_VALID(name
))
788 kr
= ipc_right_lookup_write(space
, name
, &entry
);
789 if (kr
!= KERN_SUCCESS
)
791 /* space is write-locked */
793 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
798 * Routine: mach_port_get_refs [kernel call]
800 * Retrieves the number of user references held by a right.
801 * Receive rights, port-set rights, and send-once rights
802 * always have one user reference. Returns zero if the
803 * name denotes a right, but not the queried right.
807 * KERN_SUCCESS Number of urefs returned.
808 * KERN_INVALID_TASK The space is null.
809 * KERN_INVALID_TASK The space is dead.
810 * KERN_INVALID_VALUE "right" isn't a legal value.
811 * KERN_INVALID_NAME The name doesn't denote a right.
817 mach_port_name_t name
,
818 mach_port_right_t right
,
819 mach_port_urefs_t
*urefsp
)
821 mach_port_type_t type
;
822 mach_port_urefs_t urefs
;
826 if (space
== IS_NULL
)
827 return KERN_INVALID_TASK
;
829 if (right
>= MACH_PORT_RIGHT_NUMBER
)
830 return KERN_INVALID_VALUE
;
832 if (!MACH_PORT_VALID(name
)) {
833 if (right
== MACH_PORT_RIGHT_SEND
||
834 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
838 return KERN_INVALID_NAME
;
841 kr
= ipc_right_lookup_write(space
, name
, &entry
);
842 if (kr
!= KERN_SUCCESS
)
844 /* space is write-locked and active */
846 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
847 if (kr
!= KERN_SUCCESS
)
848 return kr
; /* space is unlocked */
849 is_write_unlock(space
);
851 if (type
& MACH_PORT_TYPE(right
))
853 case MACH_PORT_RIGHT_SEND_ONCE
:
857 case MACH_PORT_RIGHT_PORT_SET
:
858 case MACH_PORT_RIGHT_RECEIVE
:
862 case MACH_PORT_RIGHT_DEAD_NAME
:
863 case MACH_PORT_RIGHT_SEND
:
869 panic("mach_port_get_refs: strange rights");
878 * Routine: mach_port_mod_refs
880 * Modifies the number of user references held by a right.
881 * The resulting number of user references must be non-negative.
882 * If it is zero, the right is deallocated. If the name
883 * doesn't denote other rights, it is destroyed.
887 * KERN_SUCCESS Modified number of urefs.
888 * KERN_INVALID_TASK The space is null.
889 * KERN_INVALID_TASK The space is dead.
890 * KERN_INVALID_VALUE "right" isn't a legal value.
891 * KERN_INVALID_NAME The name doesn't denote a right.
892 * KERN_INVALID_RIGHT Name doesn't denote specified right.
893 * KERN_INVALID_VALUE Impossible modification to urefs.
894 * KERN_UREFS_OVERFLOW Urefs would overflow.
900 mach_port_name_t name
,
901 mach_port_right_t right
,
902 mach_port_delta_t delta
)
907 if (space
== IS_NULL
)
908 return KERN_INVALID_TASK
;
910 if (right
>= MACH_PORT_RIGHT_NUMBER
)
911 return KERN_INVALID_VALUE
;
913 if (!MACH_PORT_VALID(name
)) {
914 if (right
== MACH_PORT_RIGHT_SEND
||
915 right
== MACH_PORT_RIGHT_SEND_ONCE
)
917 return KERN_INVALID_NAME
;
920 kr
= ipc_right_lookup_write(space
, name
, &entry
);
921 if (kr
!= KERN_SUCCESS
)
923 /* space is write-locked and active */
925 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
931 * Routine: mach_port_set_mscount [kernel call]
933 * Changes a receive right's make-send count.
937 * KERN_SUCCESS Set make-send count.
938 * KERN_INVALID_TASK The space is null.
939 * KERN_INVALID_TASK The space is dead.
940 * KERN_INVALID_NAME The name doesn't denote a right.
941 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
945 mach_port_set_mscount(
947 mach_port_name_t name
,
948 mach_port_mscount_t mscount
)
953 if (space
== IS_NULL
)
954 return KERN_INVALID_TASK
;
956 if (!MACH_PORT_VALID(name
))
957 return KERN_INVALID_RIGHT
;
959 kr
= ipc_port_translate_receive(space
, name
, &port
);
960 if (kr
!= KERN_SUCCESS
)
962 /* port is locked and active */
964 ipc_port_set_mscount(port
, mscount
);
971 * Routine: mach_port_set_seqno [kernel call]
973 * Changes a receive right's sequence number.
977 * KERN_SUCCESS Set sequence number.
978 * KERN_INVALID_TASK The space is null.
979 * KERN_INVALID_TASK The space is dead.
980 * KERN_INVALID_NAME The name doesn't denote a right.
981 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
987 mach_port_name_t name
,
988 mach_port_seqno_t seqno
)
993 if (space
== IS_NULL
)
994 return KERN_INVALID_TASK
;
996 if (!MACH_PORT_VALID(name
))
997 return KERN_INVALID_RIGHT
;
999 kr
= ipc_port_translate_receive(space
, name
, &port
);
1000 if (kr
!= KERN_SUCCESS
)
1002 /* port is locked and active */
1004 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
1007 return KERN_SUCCESS
;
1011 * Routine: mach_port_gst_helper
1013 * A helper function for mach_port_get_set_status.
1017 mach_port_gst_helper(
1020 ipc_entry_num_t maxnames
,
1021 mach_port_name_t
*names
,
1022 ipc_entry_num_t
*actualp
)
1025 mach_port_name_t name
;
1027 assert(port
!= IP_NULL
);
1030 assert(ip_active(port
));
1032 name
= port
->ip_receiver_name
;
1033 assert(name
!= MACH_PORT_NULL
);
1037 if (ipc_pset_member(pset
, port
)) {
1038 ipc_entry_num_t actual
= *actualp
;
1040 if (actual
< maxnames
)
1041 names
[actual
] = name
;
1043 *actualp
= actual
+1;
1048 * Routine: mach_port_get_set_status [kernel call]
1050 * Retrieves a list of members in a port set.
1051 * Returns the space's name for each receive right member.
1055 * KERN_SUCCESS Retrieved list of members.
1056 * KERN_INVALID_TASK The space is null.
1057 * KERN_INVALID_TASK The space is dead.
1058 * KERN_INVALID_NAME The name doesn't denote a right.
1059 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1060 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1064 mach_port_get_set_status(
1066 mach_port_name_t name
,
1067 mach_port_name_t
**members
,
1068 mach_msg_type_number_t
*membersCnt
)
1070 ipc_entry_num_t actual
; /* this many members */
1071 ipc_entry_num_t maxnames
; /* space for this many members */
1074 vm_size_t size
; /* size of allocated memory */
1075 vm_offset_t addr
; /* allocated memory */
1076 vm_map_copy_t memory
; /* copied-in memory */
1078 if (space
== IS_NULL
)
1079 return KERN_INVALID_TASK
;
1081 if (!MACH_PORT_VALID(name
))
1082 return KERN_INVALID_RIGHT
;
1084 size
= PAGE_SIZE
; /* initial guess */
1087 ipc_tree_entry_t tentry
;
1088 ipc_entry_t entry
, table
;
1089 ipc_entry_num_t tsize
;
1090 mach_port_index_t index
;
1091 mach_port_name_t
*names
;
1094 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, TRUE
);
1095 if (kr
!= KERN_SUCCESS
)
1096 return KERN_RESOURCE_SHORTAGE
;
1098 /* can't fault while we hold locks */
1100 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1101 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1102 assert(kr
== KERN_SUCCESS
);
1104 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1105 if (kr
!= KERN_SUCCESS
) {
1106 kmem_free(ipc_kernel_map
, addr
, size
);
1109 /* space is read-locked and active */
1111 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1112 is_read_unlock(space
);
1113 kmem_free(ipc_kernel_map
, addr
, size
);
1114 return KERN_INVALID_RIGHT
;
1117 pset
= (ipc_pset_t
) entry
->ie_object
;
1118 assert(pset
!= IPS_NULL
);
1119 /* the port set must be active */
1121 names
= (mach_port_name_t
*) addr
;
1122 maxnames
= size
/ sizeof(mach_port_name_t
);
1125 table
= space
->is_table
;
1126 tsize
= space
->is_table_size
;
1128 for (index
= 0; index
< tsize
; index
++) {
1129 ipc_entry_t ientry
= &table
[index
];
1131 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1133 (ipc_port_t
) ientry
->ie_object
;
1135 mach_port_gst_helper(pset
, port
,
1136 maxnames
, names
, &actual
);
1140 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1142 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1143 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1145 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1147 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1148 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1150 mach_port_gst_helper(pset
, port
, maxnames
,
1154 ipc_splay_traverse_finish(&space
->is_tree
);
1155 is_read_unlock(space
);
1157 if (actual
<= maxnames
)
1160 /* didn't have enough memory; allocate more */
1162 kmem_free(ipc_kernel_map
, addr
, size
);
1163 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1167 memory
= VM_MAP_COPY_NULL
;
1169 kmem_free(ipc_kernel_map
, addr
, size
);
1171 vm_size_t size_used
;
1172 vm_size_t vm_size_used
;
1174 size_used
= actual
* sizeof(mach_port_name_t
);
1175 vm_size_used
= round_page(size_used
);
1178 * Make used memory pageable and get it into
1179 * copied-in form. Free any unused memory.
1182 kr
= vm_map_unwire(ipc_kernel_map
,
1183 addr
, addr
+ vm_size_used
, FALSE
);
1184 assert(kr
== KERN_SUCCESS
);
1186 kr
= vm_map_copyin(ipc_kernel_map
, addr
, size_used
,
1188 assert(kr
== KERN_SUCCESS
);
1190 if (vm_size_used
!= size
)
1191 kmem_free(ipc_kernel_map
,
1192 addr
+ vm_size_used
, size
- vm_size_used
);
1195 *members
= (mach_port_name_t
*) memory
;
1196 *membersCnt
= actual
;
1197 return KERN_SUCCESS
;
1201 * Routine: mach_port_move_member [kernel call]
1203 * If after is MACH_PORT_NULL, removes member
1204 * from the port set it is in. Otherwise, adds
1205 * member to after, removing it from any set
1206 * it might already be in.
1210 * KERN_SUCCESS Moved the port.
1211 * KERN_INVALID_TASK The space is null.
1212 * KERN_INVALID_TASK The space is dead.
1213 * KERN_INVALID_NAME Member didn't denote a right.
1214 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1215 * KERN_INVALID_NAME After didn't denote a right.
1216 * KERN_INVALID_RIGHT After didn't denote a port set right.
1218 * After is MACH_PORT_NULL and Member isn't in a port set.
1222 mach_port_move_member(
1224 mach_port_name_t member
,
1225 mach_port_name_t after
)
1232 if (space
== IS_NULL
)
1233 return KERN_INVALID_TASK
;
1235 if (!MACH_PORT_VALID(member
))
1236 return KERN_INVALID_RIGHT
;
1238 if (after
== MACH_PORT_DEAD
)
1239 return KERN_INVALID_RIGHT
;
1241 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1242 if (kr
!= KERN_SUCCESS
)
1244 /* space is read-locked and active */
1246 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1247 is_read_unlock(space
);
1248 return KERN_INVALID_RIGHT
;
1251 port
= (ipc_port_t
) entry
->ie_object
;
1252 assert(port
!= IP_NULL
);
1254 if (after
== MACH_PORT_NULL
)
1257 entry
= ipc_entry_lookup(space
, after
);
1258 if (entry
== IE_NULL
) {
1259 is_read_unlock(space
);
1260 return KERN_INVALID_NAME
;
1263 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1264 is_read_unlock(space
);
1265 return KERN_INVALID_RIGHT
;
1268 nset
= (ipc_pset_t
) entry
->ie_object
;
1269 assert(nset
!= IPS_NULL
);
1272 ipc_pset_remove_all(port
);
1274 if (nset
!= IPS_NULL
) {
1276 kr
= ipc_pset_add(nset
, port
);
1280 is_read_unlock(space
);
1285 * Routine: mach_port_request_notification [kernel call]
1287 * Requests a notification. The caller supplies
1288 * a send-once right for the notification to use,
1289 * and the call returns the previously registered
1290 * send-once right, if any. Possible types:
1292 * MACH_NOTIFY_PORT_DESTROYED
1293 * Requests a port-destroyed notification
1294 * for a receive right. Sync should be zero.
1295 * MACH_NOTIFY_NO_SENDERS
1296 * Requests a no-senders notification for a
1297 * receive right. If there are currently no
1298 * senders, sync is less than or equal to the
1299 * current make-send count, and a send-once right
1300 * is supplied, then an immediate no-senders
1301 * notification is generated.
1302 * MACH_NOTIFY_DEAD_NAME
1303 * Requests a dead-name notification for a send
1304 * or receive right. If the name is already a
1305 * dead name, sync is non-zero, and a send-once
1306 * right is supplied, then an immediate dead-name
1307 * notification is generated.
1311 * KERN_SUCCESS Requested a notification.
1312 * KERN_INVALID_TASK The space is null.
1313 * KERN_INVALID_TASK The space is dead.
1314 * KERN_INVALID_VALUE Bad id value.
1315 * KERN_INVALID_NAME Name doesn't denote a right.
1316 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1317 * KERN_INVALID_CAPABILITY The notify port is dead.
1318 * MACH_NOTIFY_PORT_DESTROYED:
1319 * KERN_INVALID_VALUE Sync isn't zero.
1320 * MACH_NOTIFY_DEAD_NAME:
1321 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1322 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1323 * sync is zero or notify is IP_NULL.
1324 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1325 * generating immediate notif. would overflow urefs.
1329 mach_port_request_notification(
1331 mach_port_name_t name
,
1333 mach_port_mscount_t sync
,
1335 ipc_port_t
*previousp
)
1342 if (space
== IS_NULL
)
1343 return KERN_INVALID_TASK
;
1345 if (notify
== IP_DEAD
)
1346 return KERN_INVALID_CAPABILITY
;
1350 * Requesting notifications on RPC ports is an error.
1352 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1353 if (kr
!= KERN_SUCCESS
)
1356 port
= (ipc_port_t
) entry
->ie_object
;
1358 if (port
->ip_subsystem
!= NULL
) {
1359 is_write_unlock(space
);
1360 panic("mach_port_request_notification: on RPC port!!");
1361 return KERN_INVALID_CAPABILITY
;
1363 is_write_unlock(space
);
1368 case MACH_NOTIFY_PORT_DESTROYED
: {
1369 ipc_port_t port
, previous
;
1372 return KERN_INVALID_VALUE
;
1374 if (!MACH_PORT_VALID(name
))
1375 return KERN_INVALID_RIGHT
;
1377 kr
= ipc_port_translate_receive(space
, name
, &port
);
1378 if (kr
!= KERN_SUCCESS
)
1380 /* port is locked and active */
1382 ipc_port_pdrequest(port
, notify
, &previous
);
1383 /* port is unlocked */
1385 *previousp
= previous
;
1389 case MACH_NOTIFY_NO_SENDERS
: {
1392 if (!MACH_PORT_VALID(name
))
1393 return KERN_INVALID_RIGHT
;
1395 kr
= ipc_port_translate_receive(space
, name
, &port
);
1396 if (kr
!= KERN_SUCCESS
)
1398 /* port is locked and active */
1400 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1401 /* port is unlocked */
1405 case MACH_NOTIFY_DEAD_NAME
:
1407 if (!MACH_PORT_VALID(name
)) {
1410 * Should do immediate delivery check -
1411 * will do that in the near future.
1413 return KERN_INVALID_ARGUMENT
;
1416 kr
= ipc_right_dnrequest(space
, name
, sync
!= 0,
1418 if (kr
!= KERN_SUCCESS
)
1423 return KERN_INVALID_VALUE
;
1426 return KERN_SUCCESS
;
1430 * Routine: mach_port_insert_right [kernel call]
1432 * Inserts a right into a space, as if the space
1433 * voluntarily received the right in a message,
1434 * except that the right gets the specified name.
1438 * KERN_SUCCESS Inserted the right.
1439 * KERN_INVALID_TASK The space is null.
1440 * KERN_INVALID_TASK The space is dead.
1441 * KERN_INVALID_VALUE The name isn't a legal name.
1442 * KERN_NAME_EXISTS The name already denotes a right.
1443 * KERN_INVALID_VALUE Message doesn't carry a port right.
1444 * KERN_INVALID_CAPABILITY Port is null or dead.
1445 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1446 * KERN_RIGHT_EXISTS Space has rights under another name.
1447 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1451 mach_port_insert_right(
1453 mach_port_name_t name
,
1455 mach_msg_type_name_t polyPoly
)
1457 if (space
== IS_NULL
)
1458 return KERN_INVALID_TASK
;
1460 if (!MACH_PORT_VALID(name
) ||
1461 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1462 return KERN_INVALID_VALUE
;
1464 if (!IO_VALID((ipc_object_t
) poly
))
1465 return KERN_INVALID_CAPABILITY
;
1467 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1468 polyPoly
, FALSE
, name
);
1472 * Routine: mach_port_extract_right [kernel call]
1474 * Extracts a right from a space, as if the space
1475 * voluntarily sent the right to the caller.
1479 * KERN_SUCCESS Extracted the right.
1480 * KERN_INVALID_TASK The space is null.
1481 * KERN_INVALID_TASK The space is dead.
1482 * KERN_INVALID_VALUE Requested type isn't a port right.
1483 * KERN_INVALID_NAME Name doesn't denote a right.
1484 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1488 mach_port_extract_right(
1490 mach_port_name_t name
,
1491 mach_msg_type_name_t msgt_name
,
1493 mach_msg_type_name_t
*polyPoly
)
1497 if (space
== IS_NULL
)
1498 return KERN_INVALID_TASK
;
1500 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1501 return KERN_INVALID_VALUE
;
1503 if (!MACH_PORT_VALID(name
)) {
1505 * really should copy out a dead name, if it is a send or
1506 * send-once right being copied, but instead return an
1509 return KERN_INVALID_RIGHT
;
1512 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1514 if (kr
== KERN_SUCCESS
)
1515 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1521 mach_port_get_attributes(
1523 mach_port_name_t name
,
1525 mach_port_info_t info
,
1526 mach_msg_type_number_t
*count
)
1531 if (space
== IS_NULL
)
1532 return KERN_INVALID_TASK
;
1535 case MACH_PORT_LIMITS_INFO
: {
1536 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1538 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1539 return KERN_FAILURE
;
1541 if (!MACH_PORT_VALID(name
)) {
1546 kr
= ipc_port_translate_receive(space
, name
, &port
);
1547 if (kr
!= KERN_SUCCESS
)
1549 /* port is locked and active */
1551 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1552 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1557 case MACH_PORT_RECEIVE_STATUS
: {
1558 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1561 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1562 return KERN_FAILURE
;
1564 if (!MACH_PORT_VALID(name
))
1565 return KERN_INVALID_RIGHT
;
1567 kr
= ipc_port_translate_receive(space
, name
, &port
);
1568 if (kr
!= KERN_SUCCESS
)
1570 /* port is locked and active */
1572 statusp
->mps_pset
= port
->ip_pset_count
;
1575 imq_lock(&port
->ip_messages
);
1576 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1577 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1578 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1579 imq_unlock(&port
->ip_messages
);
1582 statusp
->mps_mscount
= port
->ip_mscount
;
1583 statusp
->mps_sorights
= port
->ip_sorights
;
1584 statusp
->mps_srights
= port
->ip_srights
> 0;
1585 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1586 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1587 statusp
->mps_flags
= 0;
1589 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1594 case MACH_PORT_DNREQUESTS_SIZE
: {
1595 ipc_port_request_t table
;
1597 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1598 return KERN_FAILURE
;
1600 if (!MACH_PORT_VALID(name
)) {
1605 kr
= ipc_port_translate_receive(space
, name
, &port
);
1606 if (kr
!= KERN_SUCCESS
)
1608 /* port is locked and active */
1610 table
= port
->ip_dnrequests
;
1611 if (table
== IPR_NULL
)
1614 *(int *)info
= table
->ipr_size
->its_size
;
1615 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1621 return KERN_INVALID_ARGUMENT
;
1625 return KERN_SUCCESS
;
1629 mach_port_set_attributes(
1631 mach_port_name_t name
,
1633 mach_port_info_t info
,
1634 mach_msg_type_number_t count
)
1639 if (space
== IS_NULL
)
1640 return KERN_INVALID_TASK
;
1644 case MACH_PORT_LIMITS_INFO
: {
1645 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1647 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1648 return KERN_FAILURE
;
1650 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1651 return KERN_INVALID_VALUE
;
1653 if (!MACH_PORT_VALID(name
))
1654 return KERN_INVALID_RIGHT
;
1656 kr
= ipc_port_translate_receive(space
, name
, &port
);
1657 if (kr
!= KERN_SUCCESS
)
1659 /* port is locked and active */
1661 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1665 case MACH_PORT_DNREQUESTS_SIZE
: {
1666 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1667 return KERN_FAILURE
;
1669 if (!MACH_PORT_VALID(name
))
1670 return KERN_INVALID_RIGHT
;
1672 kr
= ipc_port_translate_receive(space
, name
, &port
);
1673 if (kr
!= KERN_SUCCESS
)
1675 /* port is locked and active */
1677 kr
= ipc_port_dngrow(port
, *(int *)info
);
1678 if (kr
!= KERN_SUCCESS
)
1683 return KERN_INVALID_ARGUMENT
;
1686 return KERN_SUCCESS
;
1690 * Routine: mach_port_insert_member [kernel call]
1692 * Add the receive right, specified by name, to
1694 * The port cannot already be a member of the set.
1698 * KERN_SUCCESS Moved the port.
1699 * KERN_INVALID_TASK The space is null.
1700 * KERN_INVALID_TASK The space is dead.
1701 * KERN_INVALID_NAME name didn't denote a right.
1702 * KERN_INVALID_RIGHT name didn't denote a receive right.
1703 * KERN_INVALID_NAME pset_name didn't denote a right.
1704 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1705 * KERN_ALREADY_IN_SET name was already a member of pset.
1709 mach_port_insert_member(
1711 mach_port_name_t name
,
1712 mach_port_name_t psname
)
1718 if (space
== IS_NULL
)
1719 return KERN_INVALID_TASK
;
1721 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1722 return KERN_INVALID_RIGHT
;
1724 kr
= ipc_object_translate_two(space
,
1725 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1726 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1727 if (kr
!= KERN_SUCCESS
)
1730 /* obj and psobj are locked (and were locked in that order) */
1731 assert(psobj
!= IO_NULL
);
1732 assert(obj
!= IO_NULL
);
1734 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1741 * Routine: mach_port_extract_member [kernel call]
1743 * Remove a port from one portset that it is a member of.
1747 * KERN_SUCCESS Moved the port.
1748 * KERN_INVALID_TASK The space is null.
1749 * KERN_INVALID_TASK The space is dead.
1750 * KERN_INVALID_NAME Member didn't denote a right.
1751 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1752 * KERN_INVALID_NAME After didn't denote a right.
1753 * KERN_INVALID_RIGHT After didn't denote a port set right.
1755 * After is MACH_PORT_NULL and Member isn't in a port set.
1759 mach_port_extract_member(
1761 mach_port_name_t name
,
1762 mach_port_name_t psname
)
1764 mach_port_name_t oldname
;
1769 if (space
== IS_NULL
)
1770 return KERN_INVALID_TASK
;
1772 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1773 return KERN_INVALID_RIGHT
;
1775 kr
= ipc_object_translate_two(space
,
1776 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1777 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1778 if (kr
!= KERN_SUCCESS
)
1781 /* obj and psobj are both locked (and were locked in that order) */
1782 assert(psobj
!= IO_NULL
);
1783 assert(obj
!= IO_NULL
);
1785 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);