2 * Copyright (c) 2000-2004 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.h>
73 #include <kern/kalloc.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
);
98 void mach_port_gst_helper(
101 ipc_entry_num_t maxnames
,
102 mach_port_name_t
*names
,
103 ipc_entry_num_t
*actualp
);
106 /* Zeroed template of qos flags */
108 static mach_port_qos_t qos_template
;
111 * Routine: mach_port_names_helper
113 * A helper function for mach_port_names.
117 mach_port_names_helper(
118 ipc_port_timestamp_t timestamp
,
120 mach_port_name_t name
,
121 mach_port_name_t
*names
,
122 mach_port_type_t
*types
,
123 ipc_entry_num_t
*actualp
)
125 ipc_entry_bits_t bits
;
126 ipc_port_request_index_t request
;
127 mach_port_type_t type
;
128 ipc_entry_num_t actual
;
130 bits
= entry
->ie_bits
;
131 request
= entry
->ie_request
;
132 if (bits
& MACH_PORT_TYPE_SEND_RIGHTS
) {
136 port
= (ipc_port_t
) entry
->ie_object
;
137 assert(port
!= IP_NULL
);
140 * The timestamp serializes mach_port_names
141 * with ipc_port_destroy. If the port died,
142 * but after mach_port_names started, pretend
143 * that it isn't dead.
147 died
= (!ip_active(port
) &&
148 IP_TIMESTAMP_ORDER(port
->ip_timestamp
, timestamp
));
152 /* pretend this is a dead-name entry */
154 bits
&= ~(IE_BITS_TYPE_MASK
);
155 bits
|= MACH_PORT_TYPE_DEAD_NAME
;
162 type
= IE_BITS_TYPE(bits
);
164 type
|= MACH_PORT_TYPE_DNREQUEST
;
167 names
[actual
] = name
;
168 types
[actual
] = type
;
173 * Routine: mach_port_names [kernel call]
175 * Retrieves a list of the rights present in the space,
176 * along with type information. (Same as returned
177 * by mach_port_type.) The names are returned in
178 * no particular order, but they (and the type info)
179 * are an accurate snapshot of the space.
183 * KERN_SUCCESS Arrays of names and types returned.
184 * KERN_INVALID_TASK The space is null.
185 * KERN_INVALID_TASK The space is dead.
186 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
192 mach_port_name_t
**namesp
,
193 mach_msg_type_number_t
*namesCnt
,
194 mach_port_type_t
**typesp
,
195 mach_msg_type_number_t
*typesCnt
)
197 ipc_tree_entry_t tentry
;
199 ipc_entry_num_t tsize
;
200 mach_port_index_t index
;
201 ipc_entry_num_t actual
; /* this many names */
202 ipc_port_timestamp_t timestamp
; /* logical time of this operation */
203 mach_port_name_t
*names
;
204 mach_port_type_t
*types
;
207 vm_size_t size
; /* size of allocated memory */
208 vm_offset_t addr1
; /* allocated memory, for names */
209 vm_offset_t addr2
; /* allocated memory, for types */
210 vm_map_copy_t memory1
; /* copied-in memory, for names */
211 vm_map_copy_t memory2
; /* copied-in memory, for types */
213 /* safe simplifying assumption */
214 assert_static(sizeof(mach_port_name_t
) == sizeof(mach_port_type_t
));
216 if (space
== IS_NULL
)
217 return KERN_INVALID_TASK
;
222 ipc_entry_num_t bound
;
223 vm_size_t size_needed
;
226 if (!space
->is_active
) {
227 is_read_unlock(space
);
229 kmem_free(ipc_kernel_map
, addr1
, size
);
230 kmem_free(ipc_kernel_map
, addr2
, size
);
232 return KERN_INVALID_TASK
;
235 /* upper bound on number of names in the space */
237 bound
= space
->is_table_size
+ space
->is_tree_total
;
238 size_needed
= round_page(bound
* sizeof(mach_port_name_t
));
240 if (size_needed
<= size
)
243 is_read_unlock(space
);
246 kmem_free(ipc_kernel_map
, addr1
, size
);
247 kmem_free(ipc_kernel_map
, addr2
, size
);
251 kr
= vm_allocate(ipc_kernel_map
, &addr1
, size
, VM_FLAGS_ANYWHERE
);
252 if (kr
!= KERN_SUCCESS
)
253 return KERN_RESOURCE_SHORTAGE
;
255 kr
= vm_allocate(ipc_kernel_map
, &addr2
, size
, VM_FLAGS_ANYWHERE
);
256 if (kr
!= KERN_SUCCESS
) {
257 kmem_free(ipc_kernel_map
, addr1
, size
);
258 return KERN_RESOURCE_SHORTAGE
;
261 /* can't fault while we hold locks */
263 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
264 vm_map_round_page(addr1
+ size
),
265 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
266 if (kr
!= KERN_SUCCESS
) {
267 kmem_free(ipc_kernel_map
, addr1
, size
);
268 kmem_free(ipc_kernel_map
, addr2
, size
);
269 return KERN_RESOURCE_SHORTAGE
;
272 kr
= vm_map_wire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
273 vm_map_round_page(addr2
+ size
),
274 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
275 if (kr
!= KERN_SUCCESS
) {
276 kmem_free(ipc_kernel_map
, addr1
, size
);
277 kmem_free(ipc_kernel_map
, addr2
, size
);
278 return KERN_RESOURCE_SHORTAGE
;
282 /* space is read-locked and active */
284 names
= (mach_port_name_t
*) addr1
;
285 types
= (mach_port_type_t
*) addr2
;
288 timestamp
= ipc_port_timestamp();
290 table
= space
->is_table
;
291 tsize
= space
->is_table_size
;
293 for (index
= 0; index
< tsize
; index
++) {
294 ipc_entry_t entry
= &table
[index
];
295 ipc_entry_bits_t bits
= entry
->ie_bits
;
297 if (IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
) {
298 mach_port_name_t name
;
300 name
= MACH_PORT_MAKE(index
, IE_BITS_GEN(bits
));
301 mach_port_names_helper(timestamp
, entry
, name
, names
,
306 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
308 tentry
= ipc_splay_traverse_next(&space
->is_tree
, FALSE
)) {
309 ipc_entry_t entry
= &tentry
->ite_entry
;
310 mach_port_name_t name
= tentry
->ite_name
;
312 assert(IE_BITS_TYPE(tentry
->ite_bits
) != MACH_PORT_TYPE_NONE
);
313 mach_port_names_helper(timestamp
, entry
, name
, names
,
316 ipc_splay_traverse_finish(&space
->is_tree
);
317 is_read_unlock(space
);
320 memory1
= VM_MAP_COPY_NULL
;
321 memory2
= VM_MAP_COPY_NULL
;
324 kmem_free(ipc_kernel_map
, addr1
, size
);
325 kmem_free(ipc_kernel_map
, addr2
, size
);
329 vm_size_t vm_size_used
;
331 size_used
= actual
* sizeof(mach_port_name_t
);
332 vm_size_used
= round_page(size_used
);
335 * Make used memory pageable and get it into
336 * copied-in form. Free any unused memory.
339 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr1
),
340 vm_map_round_page(addr1
+ vm_size_used
), FALSE
);
341 assert(kr
== KERN_SUCCESS
);
343 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr2
),
344 vm_map_round_page(addr2
+ vm_size_used
), FALSE
);
345 assert(kr
== KERN_SUCCESS
);
347 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr1
,
348 (vm_map_size_t
)size_used
, TRUE
, &memory1
);
349 assert(kr
== KERN_SUCCESS
);
351 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr2
,
352 (vm_map_size_t
)size_used
, TRUE
, &memory2
);
353 assert(kr
== KERN_SUCCESS
);
355 if (vm_size_used
!= size
) {
356 kmem_free(ipc_kernel_map
,
357 addr1
+ vm_size_used
, size
- vm_size_used
);
358 kmem_free(ipc_kernel_map
,
359 addr2
+ vm_size_used
, size
- vm_size_used
);
363 *namesp
= (mach_port_name_t
*) memory1
;
365 *typesp
= (mach_port_type_t
*) memory2
;
371 * Routine: mach_port_type [kernel call]
373 * Retrieves the type of a right in the space.
374 * The type is a bitwise combination of one or more
375 * of the following type bits:
376 * MACH_PORT_TYPE_SEND
377 * MACH_PORT_TYPE_RECEIVE
378 * MACH_PORT_TYPE_SEND_ONCE
379 * MACH_PORT_TYPE_PORT_SET
380 * MACH_PORT_TYPE_DEAD_NAME
381 * In addition, the following pseudo-type bits may be present:
382 * MACH_PORT_TYPE_DNREQUEST
383 * A dead-name notification is requested.
387 * KERN_SUCCESS Type is returned.
388 * KERN_INVALID_TASK The space is null.
389 * KERN_INVALID_TASK The space is dead.
390 * KERN_INVALID_NAME The name doesn't denote a right.
396 mach_port_name_t name
,
397 mach_port_type_t
*typep
)
399 mach_port_urefs_t urefs
;
403 if (space
== IS_NULL
)
404 return KERN_INVALID_TASK
;
406 if (name
== MACH_PORT_NULL
)
407 return KERN_INVALID_NAME
;
409 if (name
== MACH_PORT_DEAD
) {
410 *typep
= MACH_PORT_TYPE_DEAD_NAME
;
414 kr
= ipc_right_lookup_write(space
, name
, &entry
);
415 if (kr
!= KERN_SUCCESS
)
417 /* space is write-locked and active */
419 kr
= ipc_right_info(space
, name
, entry
, typep
, &urefs
);
420 if (kr
== KERN_SUCCESS
)
421 is_write_unlock(space
);
422 /* space is unlocked */
427 * Routine: mach_port_rename [kernel call]
429 * Changes the name denoting a right,
430 * from oname to nname.
434 * KERN_SUCCESS The right is renamed.
435 * KERN_INVALID_TASK The space is null.
436 * KERN_INVALID_TASK The space is dead.
437 * KERN_INVALID_NAME The oname doesn't denote a right.
438 * KERN_INVALID_VALUE The nname isn't a legal name.
439 * KERN_NAME_EXISTS The nname already denotes a right.
440 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
446 mach_port_name_t oname
,
447 mach_port_name_t nname
)
449 if (space
== IS_NULL
)
450 return KERN_INVALID_TASK
;
452 if (!MACH_PORT_VALID(oname
))
453 return KERN_INVALID_NAME
;
455 if (!MACH_PORT_VALID(nname
))
456 return KERN_INVALID_VALUE
;
458 return ipc_object_rename(space
, oname
, nname
);
462 * Routine: mach_port_allocate_name [kernel call]
464 * Allocates a right in a space, using a specific name
465 * for the new right. Possible rights:
466 * MACH_PORT_RIGHT_RECEIVE
467 * MACH_PORT_RIGHT_PORT_SET
468 * MACH_PORT_RIGHT_DEAD_NAME
470 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
471 * has no extant send or send-once rights and no queued
472 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
473 * and its make-send count is 0. It is not a member of
474 * a port set. It has no registered no-senders or
475 * port-destroyed notification requests.
477 * A new port set has no members.
479 * A new dead name has one user reference.
483 * KERN_SUCCESS The right is allocated.
484 * KERN_INVALID_TASK The space is null.
485 * KERN_INVALID_TASK The space is dead.
486 * KERN_INVALID_VALUE The name isn't a legal name.
487 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
488 * KERN_NAME_EXISTS The name already denotes a right.
489 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
491 * Restrictions on name allocation: NT bits are reserved by kernel,
492 * must be set on any chosen name. Can't do this at all in kernel
497 mach_port_allocate_name(
499 mach_port_right_t right
,
500 mach_port_name_t name
)
503 mach_port_qos_t qos
= qos_template
;
507 if (!MACH_PORT_VALID(name
))
508 return KERN_INVALID_VALUE
;
510 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
516 * Routine: mach_port_allocate [kernel call]
518 * Allocates a right in a space. Like mach_port_allocate_name,
519 * except that the implementation picks a name for the right.
520 * The name may be any legal name in the space that doesn't
521 * currently denote a right.
525 * KERN_SUCCESS The right is allocated.
526 * KERN_INVALID_TASK The space is null.
527 * KERN_INVALID_TASK The space is dead.
528 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
529 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
530 * KERN_NO_SPACE No room in space for another right.
536 mach_port_right_t right
,
537 mach_port_name_t
*namep
)
540 mach_port_qos_t qos
= qos_template
;
542 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
548 * Routine: mach_port_allocate_qos [kernel call]
550 * Allocates a right, with qos options, in a space. Like
551 * mach_port_allocate_name, except that the implementation
552 * picks a name for the right. The name may be any legal name
553 * in the space that doesn't currently denote a right.
557 * KERN_SUCCESS The right is allocated.
558 * KERN_INVALID_TASK The space is null.
559 * KERN_INVALID_TASK The space is dead.
560 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
561 * KERN_INVALID_ARGUMENT The qos request was invalid.
562 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
563 * KERN_NO_SPACE No room in space for another right.
567 mach_port_allocate_qos(
569 mach_port_right_t right
,
570 mach_port_qos_t
*qosp
,
571 mach_port_name_t
*namep
)
576 return KERN_INVALID_ARGUMENT
;
577 kr
= mach_port_allocate_full (space
, right
, MACH_PORT_NULL
,
583 * Routine: mach_port_allocate_full [kernel call]
585 * Allocates a right in a space. Supports all of the
586 * special cases, such as specifying a subsystem,
587 * a specific name, a real-time port, etc.
588 * The name may be any legal name in the space that doesn't
589 * currently denote a right.
593 * KERN_SUCCESS The right is allocated.
594 * KERN_INVALID_TASK The space is null.
595 * KERN_INVALID_TASK The space is dead.
596 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
597 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
598 * KERN_NO_SPACE No room in space for another right.
602 mach_port_allocate_full(
604 mach_port_right_t right
,
606 mach_port_qos_t
*qosp
,
607 mach_port_name_t
*namep
)
609 ipc_kmsg_t kmsg
= IKM_NULL
;
612 if (space
== IS_NULL
)
613 return (KERN_INVALID_TASK
);
615 if (proto
!= MACH_PORT_NULL
)
616 return (KERN_INVALID_VALUE
);
619 if (!MACH_PORT_VALID (*namep
))
620 return (KERN_INVALID_VALUE
);
621 if (is_fast_space (space
))
622 return (KERN_FAILURE
);
625 if (qosp
->prealloc
) {
626 mach_msg_size_t size
= qosp
->len
+ MAX_TRAILER_SIZE
;
627 if (right
!= MACH_PORT_RIGHT_RECEIVE
)
628 return (KERN_INVALID_VALUE
);
629 kmsg
= (ipc_kmsg_t
)ipc_kmsg_alloc(size
);
630 if (kmsg
== IKM_NULL
)
631 return (KERN_RESOURCE_SHORTAGE
);
635 case MACH_PORT_RIGHT_RECEIVE
:
640 kr
= ipc_port_alloc_name(space
, *namep
, &port
);
642 kr
= ipc_port_alloc(space
, namep
, &port
);
643 if (kr
== KERN_SUCCESS
) {
644 if (kmsg
!= IKM_NULL
)
645 ipc_kmsg_set_prealloc(kmsg
, port
);
649 } else if (kmsg
!= IKM_NULL
)
654 case MACH_PORT_RIGHT_PORT_SET
:
659 kr
= ipc_pset_alloc_name(space
, *namep
, &pset
);
661 kr
= ipc_pset_alloc(space
, namep
, &pset
);
662 if (kr
== KERN_SUCCESS
)
667 case MACH_PORT_RIGHT_DEAD_NAME
:
668 kr
= ipc_object_alloc_dead(space
, namep
);
672 kr
= KERN_INVALID_VALUE
;
680 * Routine: mach_port_destroy [kernel call]
682 * Cleans up and destroys all rights denoted by a name
683 * in a space. The destruction of a receive right
684 * destroys the port, unless a port-destroyed request
685 * has been made for it; the destruction of a port-set right
686 * destroys the port set.
690 * KERN_SUCCESS The name is destroyed.
691 * KERN_INVALID_TASK The space is null.
692 * KERN_INVALID_TASK The space is dead.
693 * KERN_INVALID_NAME The name doesn't denote a right.
699 mach_port_name_t name
)
704 if (space
== IS_NULL
)
705 return KERN_INVALID_TASK
;
707 if (!MACH_PORT_VALID(name
))
710 kr
= ipc_right_lookup_write(space
, name
, &entry
);
711 if (kr
!= KERN_SUCCESS
)
713 /* space is write-locked and active */
715 kr
= ipc_right_destroy(space
, name
, entry
);
716 is_write_unlock(space
);
721 * Routine: mach_port_deallocate [kernel call]
723 * Deallocates a user reference from a send right,
724 * send-once right, or a dead-name right. May
725 * deallocate the right, if this is the last uref,
726 * and destroy the name, if it doesn't denote
731 * KERN_SUCCESS The uref is deallocated.
732 * KERN_INVALID_TASK The space is null.
733 * KERN_INVALID_TASK The space is dead.
734 * KERN_INVALID_NAME The name doesn't denote a right.
735 * KERN_INVALID_RIGHT The right isn't correct.
739 mach_port_deallocate(
741 mach_port_name_t name
)
746 if (space
== IS_NULL
)
747 return KERN_INVALID_TASK
;
749 if (!MACH_PORT_VALID(name
))
752 kr
= ipc_right_lookup_write(space
, name
, &entry
);
753 if (kr
!= KERN_SUCCESS
)
755 /* space is write-locked */
757 kr
= ipc_right_dealloc(space
, name
, entry
); /* unlocks space */
762 * Routine: mach_port_get_refs [kernel call]
764 * Retrieves the number of user references held by a right.
765 * Receive rights, port-set rights, and send-once rights
766 * always have one user reference. Returns zero if the
767 * name denotes a right, but not the queried right.
771 * KERN_SUCCESS Number of urefs returned.
772 * KERN_INVALID_TASK The space is null.
773 * KERN_INVALID_TASK The space is dead.
774 * KERN_INVALID_VALUE "right" isn't a legal value.
775 * KERN_INVALID_NAME The name doesn't denote a right.
781 mach_port_name_t name
,
782 mach_port_right_t right
,
783 mach_port_urefs_t
*urefsp
)
785 mach_port_type_t type
;
786 mach_port_urefs_t urefs
;
790 if (space
== IS_NULL
)
791 return KERN_INVALID_TASK
;
793 if (right
>= MACH_PORT_RIGHT_NUMBER
)
794 return KERN_INVALID_VALUE
;
796 if (!MACH_PORT_VALID(name
)) {
797 if (right
== MACH_PORT_RIGHT_SEND
||
798 right
== MACH_PORT_RIGHT_SEND_ONCE
) {
802 return KERN_INVALID_NAME
;
805 kr
= ipc_right_lookup_write(space
, name
, &entry
);
806 if (kr
!= KERN_SUCCESS
)
808 /* space is write-locked and active */
810 kr
= ipc_right_info(space
, name
, entry
, &type
, &urefs
); /* unlocks */
811 if (kr
!= KERN_SUCCESS
)
812 return kr
; /* space is unlocked */
813 is_write_unlock(space
);
815 if (type
& MACH_PORT_TYPE(right
))
817 case MACH_PORT_RIGHT_SEND_ONCE
:
821 case MACH_PORT_RIGHT_PORT_SET
:
822 case MACH_PORT_RIGHT_RECEIVE
:
826 case MACH_PORT_RIGHT_DEAD_NAME
:
827 case MACH_PORT_RIGHT_SEND
:
833 panic("mach_port_get_refs: strange rights");
842 * Routine: mach_port_mod_refs
844 * Modifies the number of user references held by a right.
845 * The resulting number of user references must be non-negative.
846 * If it is zero, the right is deallocated. If the name
847 * doesn't denote other rights, it is destroyed.
851 * KERN_SUCCESS Modified number of urefs.
852 * KERN_INVALID_TASK The space is null.
853 * KERN_INVALID_TASK The space is dead.
854 * KERN_INVALID_VALUE "right" isn't a legal value.
855 * KERN_INVALID_NAME The name doesn't denote a right.
856 * KERN_INVALID_RIGHT Name doesn't denote specified right.
857 * KERN_INVALID_VALUE Impossible modification to urefs.
858 * KERN_UREFS_OVERFLOW Urefs would overflow.
864 mach_port_name_t name
,
865 mach_port_right_t right
,
866 mach_port_delta_t delta
)
871 if (space
== IS_NULL
)
872 return KERN_INVALID_TASK
;
874 if (right
>= MACH_PORT_RIGHT_NUMBER
)
875 return KERN_INVALID_VALUE
;
877 if (!MACH_PORT_VALID(name
)) {
878 if (right
== MACH_PORT_RIGHT_SEND
||
879 right
== MACH_PORT_RIGHT_SEND_ONCE
)
881 return KERN_INVALID_NAME
;
884 kr
= ipc_right_lookup_write(space
, name
, &entry
);
885 if (kr
!= KERN_SUCCESS
)
887 /* space is write-locked and active */
889 kr
= ipc_right_delta(space
, name
, entry
, right
, delta
); /* unlocks */
895 * Routine: mach_port_set_mscount [kernel call]
897 * Changes a receive right's make-send count.
901 * KERN_SUCCESS Set make-send count.
902 * KERN_INVALID_TASK The space is null.
903 * KERN_INVALID_TASK The space is dead.
904 * KERN_INVALID_NAME The name doesn't denote a right.
905 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
909 mach_port_set_mscount(
911 mach_port_name_t name
,
912 mach_port_mscount_t mscount
)
917 if (space
== IS_NULL
)
918 return KERN_INVALID_TASK
;
920 if (!MACH_PORT_VALID(name
))
921 return KERN_INVALID_RIGHT
;
923 kr
= ipc_port_translate_receive(space
, name
, &port
);
924 if (kr
!= KERN_SUCCESS
)
926 /* port is locked and active */
928 ipc_port_set_mscount(port
, mscount
);
935 * Routine: mach_port_set_seqno [kernel call]
937 * Changes a receive right's sequence number.
941 * KERN_SUCCESS Set sequence number.
942 * KERN_INVALID_TASK The space is null.
943 * KERN_INVALID_TASK The space is dead.
944 * KERN_INVALID_NAME The name doesn't denote a right.
945 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
951 mach_port_name_t name
,
952 mach_port_seqno_t seqno
)
957 if (space
== IS_NULL
)
958 return KERN_INVALID_TASK
;
960 if (!MACH_PORT_VALID(name
))
961 return KERN_INVALID_RIGHT
;
963 kr
= ipc_port_translate_receive(space
, name
, &port
);
964 if (kr
!= KERN_SUCCESS
)
966 /* port is locked and active */
968 ipc_mqueue_set_seqno(&port
->ip_messages
, seqno
);
975 * Routine: mach_port_gst_helper
977 * A helper function for mach_port_get_set_status.
981 mach_port_gst_helper(
984 ipc_entry_num_t maxnames
,
985 mach_port_name_t
*names
,
986 ipc_entry_num_t
*actualp
)
988 mach_port_name_t name
;
990 assert(port
!= IP_NULL
);
993 assert(ip_active(port
));
995 name
= port
->ip_receiver_name
;
996 assert(name
!= MACH_PORT_NULL
);
1000 if (ipc_pset_member(pset
, port
)) {
1001 ipc_entry_num_t actual
= *actualp
;
1003 if (actual
< maxnames
)
1004 names
[actual
] = name
;
1006 *actualp
= actual
+1;
1011 * Routine: mach_port_get_set_status [kernel call]
1013 * Retrieves a list of members in a port set.
1014 * Returns the space's name for each receive right member.
1018 * KERN_SUCCESS Retrieved list of members.
1019 * KERN_INVALID_TASK The space is null.
1020 * KERN_INVALID_TASK The space is dead.
1021 * KERN_INVALID_NAME The name doesn't denote a right.
1022 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1023 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1027 mach_port_get_set_status(
1029 mach_port_name_t name
,
1030 mach_port_name_t
**members
,
1031 mach_msg_type_number_t
*membersCnt
)
1033 ipc_entry_num_t actual
; /* this many members */
1034 ipc_entry_num_t maxnames
; /* space for this many members */
1037 vm_size_t size
; /* size of allocated memory */
1038 vm_offset_t addr
; /* allocated memory */
1039 vm_map_copy_t memory
; /* copied-in memory */
1041 if (space
== IS_NULL
)
1042 return KERN_INVALID_TASK
;
1044 if (!MACH_PORT_VALID(name
))
1045 return KERN_INVALID_RIGHT
;
1047 size
= PAGE_SIZE
; /* initial guess */
1050 ipc_tree_entry_t tentry
;
1051 ipc_entry_t entry
, table
;
1052 ipc_entry_num_t tsize
;
1053 mach_port_index_t index
;
1054 mach_port_name_t
*names
;
1057 kr
= vm_allocate(ipc_kernel_map
, &addr
, size
, VM_FLAGS_ANYWHERE
);
1058 if (kr
!= KERN_SUCCESS
)
1059 return KERN_RESOURCE_SHORTAGE
;
1061 /* can't fault while we hold locks */
1063 kr
= vm_map_wire(ipc_kernel_map
, addr
, addr
+ size
,
1064 VM_PROT_READ
|VM_PROT_WRITE
, FALSE
);
1065 assert(kr
== KERN_SUCCESS
);
1067 kr
= ipc_right_lookup_read(space
, name
, &entry
);
1068 if (kr
!= KERN_SUCCESS
) {
1069 kmem_free(ipc_kernel_map
, addr
, size
);
1072 /* space is read-locked and active */
1074 if (IE_BITS_TYPE(entry
->ie_bits
) != MACH_PORT_TYPE_PORT_SET
) {
1075 is_read_unlock(space
);
1076 kmem_free(ipc_kernel_map
, addr
, size
);
1077 return KERN_INVALID_RIGHT
;
1080 pset
= (ipc_pset_t
) entry
->ie_object
;
1081 assert(pset
!= IPS_NULL
);
1082 /* the port set must be active */
1084 names
= (mach_port_name_t
*) addr
;
1085 maxnames
= size
/ sizeof(mach_port_name_t
);
1088 table
= space
->is_table
;
1089 tsize
= space
->is_table_size
;
1091 for (index
= 0; index
< tsize
; index
++) {
1092 ipc_entry_t ientry
= &table
[index
];
1094 if (ientry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) {
1096 (ipc_port_t
) ientry
->ie_object
;
1098 mach_port_gst_helper(pset
, port
,
1099 maxnames
, names
, &actual
);
1103 for (tentry
= ipc_splay_traverse_start(&space
->is_tree
);
1105 tentry
= ipc_splay_traverse_next(&space
->is_tree
,FALSE
)) {
1106 ipc_entry_bits_t bits
= tentry
->ite_bits
;
1108 assert(IE_BITS_TYPE(bits
) != MACH_PORT_TYPE_NONE
);
1110 if (bits
& MACH_PORT_TYPE_RECEIVE
) {
1111 ipc_port_t port
= (ipc_port_t
) tentry
->ite_object
;
1113 mach_port_gst_helper(pset
, port
, maxnames
,
1117 ipc_splay_traverse_finish(&space
->is_tree
);
1118 is_read_unlock(space
);
1120 if (actual
<= maxnames
)
1123 /* didn't have enough memory; allocate more */
1125 kmem_free(ipc_kernel_map
, addr
, size
);
1126 size
= round_page(actual
* sizeof(mach_port_name_t
)) + PAGE_SIZE
;
1130 memory
= VM_MAP_COPY_NULL
;
1132 kmem_free(ipc_kernel_map
, addr
, size
);
1134 vm_size_t size_used
;
1135 vm_size_t vm_size_used
;
1137 size_used
= actual
* sizeof(mach_port_name_t
);
1138 vm_size_used
= round_page(size_used
);
1141 * Make used memory pageable and get it into
1142 * copied-in form. Free any unused memory.
1145 kr
= vm_map_unwire(ipc_kernel_map
, vm_map_trunc_page(addr
),
1146 vm_map_round_page(addr
+ vm_size_used
), FALSE
);
1147 assert(kr
== KERN_SUCCESS
);
1149 kr
= vm_map_copyin(ipc_kernel_map
, (vm_map_address_t
)addr
,
1150 (vm_map_size_t
)size_used
, TRUE
, &memory
);
1151 assert(kr
== KERN_SUCCESS
);
1153 if (vm_size_used
!= size
)
1154 kmem_free(ipc_kernel_map
,
1155 addr
+ vm_size_used
, size
- vm_size_used
);
1158 *members
= (mach_port_name_t
*) memory
;
1159 *membersCnt
= actual
;
1160 return KERN_SUCCESS
;
1164 * Routine: mach_port_move_member [kernel call]
1166 * If after is MACH_PORT_NULL, removes member
1167 * from the port set it is in. Otherwise, adds
1168 * member to after, removing it from any set
1169 * it might already be in.
1173 * KERN_SUCCESS Moved the port.
1174 * KERN_INVALID_TASK The space is null.
1175 * KERN_INVALID_TASK The space is dead.
1176 * KERN_INVALID_NAME Member didn't denote a right.
1177 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1178 * KERN_INVALID_NAME After didn't denote a right.
1179 * KERN_INVALID_RIGHT After didn't denote a port set right.
1181 * After is MACH_PORT_NULL and Member isn't in a port set.
1185 mach_port_move_member(
1187 mach_port_name_t member
,
1188 mach_port_name_t after
)
1195 if (space
== IS_NULL
)
1196 return KERN_INVALID_TASK
;
1198 if (!MACH_PORT_VALID(member
))
1199 return KERN_INVALID_RIGHT
;
1201 if (after
== MACH_PORT_DEAD
)
1202 return KERN_INVALID_RIGHT
;
1204 kr
= ipc_right_lookup_read(space
, member
, &entry
);
1205 if (kr
!= KERN_SUCCESS
)
1207 /* space is read-locked and active */
1209 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0) {
1210 is_read_unlock(space
);
1211 return KERN_INVALID_RIGHT
;
1214 port
= (ipc_port_t
) entry
->ie_object
;
1215 assert(port
!= IP_NULL
);
1217 if (after
== MACH_PORT_NULL
)
1220 entry
= ipc_entry_lookup(space
, after
);
1221 if (entry
== IE_NULL
) {
1222 is_read_unlock(space
);
1223 return KERN_INVALID_NAME
;
1226 if ((entry
->ie_bits
& MACH_PORT_TYPE_PORT_SET
) == 0) {
1227 is_read_unlock(space
);
1228 return KERN_INVALID_RIGHT
;
1231 nset
= (ipc_pset_t
) entry
->ie_object
;
1232 assert(nset
!= IPS_NULL
);
1235 ipc_pset_remove_from_all(port
);
1237 if (nset
!= IPS_NULL
) {
1239 kr
= ipc_pset_add(nset
, port
);
1243 is_read_unlock(space
);
1248 * Routine: mach_port_request_notification [kernel call]
1250 * Requests a notification. The caller supplies
1251 * a send-once right for the notification to use,
1252 * and the call returns the previously registered
1253 * send-once right, if any. Possible types:
1255 * MACH_NOTIFY_PORT_DESTROYED
1256 * Requests a port-destroyed notification
1257 * for a receive right. Sync should be zero.
1258 * MACH_NOTIFY_NO_SENDERS
1259 * Requests a no-senders notification for a
1260 * receive right. If there are currently no
1261 * senders, sync is less than or equal to the
1262 * current make-send count, and a send-once right
1263 * is supplied, then an immediate no-senders
1264 * notification is generated.
1265 * MACH_NOTIFY_DEAD_NAME
1266 * Requests a dead-name notification for a send
1267 * or receive right. If the name is already a
1268 * dead name, sync is non-zero, and a send-once
1269 * right is supplied, then an immediate dead-name
1270 * notification is generated.
1274 * KERN_SUCCESS Requested a notification.
1275 * KERN_INVALID_TASK The space is null.
1276 * KERN_INVALID_TASK The space is dead.
1277 * KERN_INVALID_VALUE Bad id value.
1278 * KERN_INVALID_NAME Name doesn't denote a right.
1279 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1280 * KERN_INVALID_CAPABILITY The notify port is dead.
1281 * MACH_NOTIFY_PORT_DESTROYED:
1282 * KERN_INVALID_VALUE Sync isn't zero.
1283 * MACH_NOTIFY_DEAD_NAME:
1284 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1285 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1286 * sync is zero or notify is IP_NULL.
1287 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1288 * generating immediate notif. would overflow urefs.
1292 mach_port_request_notification(
1294 mach_port_name_t name
,
1296 mach_port_mscount_t sync
,
1298 ipc_port_t
*previousp
)
1302 if (space
== IS_NULL
)
1303 return KERN_INVALID_TASK
;
1305 if (notify
== IP_DEAD
)
1306 return KERN_INVALID_CAPABILITY
;
1310 * Requesting notifications on RPC ports is an error.
1316 kr
= ipc_right_lookup_write(space
, name
, &entry
);
1317 if (kr
!= KERN_SUCCESS
)
1320 port
= (ipc_port_t
) entry
->ie_object
;
1322 if (port
->ip_subsystem
!= NULL
) {
1323 is_write_unlock(space
);
1324 panic("mach_port_request_notification: on RPC port!!");
1325 return KERN_INVALID_CAPABILITY
;
1327 is_write_unlock(space
);
1333 case MACH_NOTIFY_PORT_DESTROYED
: {
1334 ipc_port_t port
, previous
;
1337 return KERN_INVALID_VALUE
;
1339 if (!MACH_PORT_VALID(name
))
1340 return KERN_INVALID_RIGHT
;
1342 kr
= ipc_port_translate_receive(space
, name
, &port
);
1343 if (kr
!= KERN_SUCCESS
)
1345 /* port is locked and active */
1347 ipc_port_pdrequest(port
, notify
, &previous
);
1348 /* port is unlocked */
1350 *previousp
= previous
;
1354 case MACH_NOTIFY_NO_SENDERS
: {
1357 if (!MACH_PORT_VALID(name
))
1358 return KERN_INVALID_RIGHT
;
1360 kr
= ipc_port_translate_receive(space
, name
, &port
);
1361 if (kr
!= KERN_SUCCESS
)
1363 /* port is locked and active */
1365 ipc_port_nsrequest(port
, sync
, notify
, previousp
);
1366 /* port is unlocked */
1370 case MACH_NOTIFY_DEAD_NAME
:
1372 if (!MACH_PORT_VALID(name
)) {
1375 * Should do immediate delivery check -
1376 * will do that in the near future.
1378 return KERN_INVALID_ARGUMENT
;
1381 kr
= ipc_right_dnrequest(space
, name
, sync
!= 0,
1383 if (kr
!= KERN_SUCCESS
)
1388 return KERN_INVALID_VALUE
;
1391 return KERN_SUCCESS
;
1395 * Routine: mach_port_insert_right [kernel call]
1397 * Inserts a right into a space, as if the space
1398 * voluntarily received the right in a message,
1399 * except that the right gets the specified name.
1403 * KERN_SUCCESS Inserted the right.
1404 * KERN_INVALID_TASK The space is null.
1405 * KERN_INVALID_TASK The space is dead.
1406 * KERN_INVALID_VALUE The name isn't a legal name.
1407 * KERN_NAME_EXISTS The name already denotes a right.
1408 * KERN_INVALID_VALUE Message doesn't carry a port right.
1409 * KERN_INVALID_CAPABILITY Port is null or dead.
1410 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1411 * KERN_RIGHT_EXISTS Space has rights under another name.
1412 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1416 mach_port_insert_right(
1418 mach_port_name_t name
,
1420 mach_msg_type_name_t polyPoly
)
1422 if (space
== IS_NULL
)
1423 return KERN_INVALID_TASK
;
1425 if (!MACH_PORT_VALID(name
) ||
1426 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly
))
1427 return KERN_INVALID_VALUE
;
1429 if (!IO_VALID((ipc_object_t
) poly
))
1430 return KERN_INVALID_CAPABILITY
;
1432 return ipc_object_copyout_name(space
, (ipc_object_t
) poly
,
1433 polyPoly
, FALSE
, name
);
1437 * Routine: mach_port_extract_right [kernel call]
1439 * Extracts a right from a space, as if the space
1440 * voluntarily sent the right to the caller.
1444 * KERN_SUCCESS Extracted the right.
1445 * KERN_INVALID_TASK The space is null.
1446 * KERN_INVALID_TASK The space is dead.
1447 * KERN_INVALID_VALUE Requested type isn't a port right.
1448 * KERN_INVALID_NAME Name doesn't denote a right.
1449 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1453 mach_port_extract_right(
1455 mach_port_name_t name
,
1456 mach_msg_type_name_t msgt_name
,
1458 mach_msg_type_name_t
*polyPoly
)
1462 if (space
== IS_NULL
)
1463 return KERN_INVALID_TASK
;
1465 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name
))
1466 return KERN_INVALID_VALUE
;
1468 if (!MACH_PORT_VALID(name
)) {
1470 * really should copy out a dead name, if it is a send or
1471 * send-once right being copied, but instead return an
1474 return KERN_INVALID_RIGHT
;
1477 kr
= ipc_object_copyin(space
, name
, msgt_name
, (ipc_object_t
*) poly
);
1479 if (kr
== KERN_SUCCESS
)
1480 *polyPoly
= ipc_object_copyin_type(msgt_name
);
1486 mach_port_get_attributes(
1488 mach_port_name_t name
,
1490 mach_port_info_t info
,
1491 mach_msg_type_number_t
*count
)
1496 if (space
== IS_NULL
)
1497 return KERN_INVALID_TASK
;
1500 case MACH_PORT_LIMITS_INFO
: {
1501 mach_port_limits_t
*lp
= (mach_port_limits_t
*)info
;
1503 if (*count
< MACH_PORT_LIMITS_INFO_COUNT
)
1504 return KERN_FAILURE
;
1506 if (!MACH_PORT_VALID(name
)) {
1511 kr
= ipc_port_translate_receive(space
, name
, &port
);
1512 if (kr
!= KERN_SUCCESS
)
1514 /* port is locked and active */
1516 lp
->mpl_qlimit
= port
->ip_messages
.imq_qlimit
;
1517 *count
= MACH_PORT_LIMITS_INFO_COUNT
;
1522 case MACH_PORT_RECEIVE_STATUS
: {
1523 mach_port_status_t
*statusp
= (mach_port_status_t
*)info
;
1526 if (*count
< MACH_PORT_RECEIVE_STATUS_COUNT
)
1527 return KERN_FAILURE
;
1529 if (!MACH_PORT_VALID(name
))
1530 return KERN_INVALID_RIGHT
;
1532 kr
= ipc_port_translate_receive(space
, name
, &port
);
1533 if (kr
!= KERN_SUCCESS
)
1535 /* port is locked and active */
1537 statusp
->mps_pset
= port
->ip_pset_count
;
1540 imq_lock(&port
->ip_messages
);
1541 statusp
->mps_seqno
= port
->ip_messages
.imq_seqno
;
1542 statusp
->mps_qlimit
= port
->ip_messages
.imq_qlimit
;
1543 statusp
->mps_msgcount
= port
->ip_messages
.imq_msgcount
;
1544 imq_unlock(&port
->ip_messages
);
1547 statusp
->mps_mscount
= port
->ip_mscount
;
1548 statusp
->mps_sorights
= port
->ip_sorights
;
1549 statusp
->mps_srights
= port
->ip_srights
> 0;
1550 statusp
->mps_pdrequest
= port
->ip_pdrequest
!= IP_NULL
;
1551 statusp
->mps_nsrequest
= port
->ip_nsrequest
!= IP_NULL
;
1552 statusp
->mps_flags
= 0;
1554 *count
= MACH_PORT_RECEIVE_STATUS_COUNT
;
1559 case MACH_PORT_DNREQUESTS_SIZE
: {
1560 ipc_port_request_t table
;
1562 if (*count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1563 return KERN_FAILURE
;
1565 if (!MACH_PORT_VALID(name
)) {
1570 kr
= ipc_port_translate_receive(space
, name
, &port
);
1571 if (kr
!= KERN_SUCCESS
)
1573 /* port is locked and active */
1575 table
= port
->ip_dnrequests
;
1576 if (table
== IPR_NULL
)
1579 *(int *)info
= table
->ipr_size
->its_size
;
1580 *count
= MACH_PORT_DNREQUESTS_SIZE_COUNT
;
1586 return KERN_INVALID_ARGUMENT
;
1590 return KERN_SUCCESS
;
1594 mach_port_set_attributes(
1596 mach_port_name_t name
,
1598 mach_port_info_t info
,
1599 mach_msg_type_number_t count
)
1604 if (space
== IS_NULL
)
1605 return KERN_INVALID_TASK
;
1609 case MACH_PORT_LIMITS_INFO
: {
1610 mach_port_limits_t
*mplp
= (mach_port_limits_t
*)info
;
1612 if (count
< MACH_PORT_LIMITS_INFO_COUNT
)
1613 return KERN_FAILURE
;
1615 if (mplp
->mpl_qlimit
> MACH_PORT_QLIMIT_MAX
)
1616 return KERN_INVALID_VALUE
;
1618 if (!MACH_PORT_VALID(name
))
1619 return KERN_INVALID_RIGHT
;
1621 kr
= ipc_port_translate_receive(space
, name
, &port
);
1622 if (kr
!= KERN_SUCCESS
)
1624 /* port is locked and active */
1626 ipc_mqueue_set_qlimit(&port
->ip_messages
, mplp
->mpl_qlimit
);
1630 case MACH_PORT_DNREQUESTS_SIZE
: {
1631 if (count
< MACH_PORT_DNREQUESTS_SIZE_COUNT
)
1632 return KERN_FAILURE
;
1634 if (!MACH_PORT_VALID(name
))
1635 return KERN_INVALID_RIGHT
;
1637 kr
= ipc_port_translate_receive(space
, name
, &port
);
1638 if (kr
!= KERN_SUCCESS
)
1640 /* port is locked and active */
1642 kr
= ipc_port_dngrow(port
, *(int *)info
);
1643 if (kr
!= KERN_SUCCESS
)
1648 return KERN_INVALID_ARGUMENT
;
1651 return KERN_SUCCESS
;
1655 * Routine: mach_port_insert_member [kernel call]
1657 * Add the receive right, specified by name, to
1659 * The port cannot already be a member of the set.
1663 * KERN_SUCCESS Moved the port.
1664 * KERN_INVALID_TASK The space is null.
1665 * KERN_INVALID_TASK The space is dead.
1666 * KERN_INVALID_NAME name didn't denote a right.
1667 * KERN_INVALID_RIGHT name didn't denote a receive right.
1668 * KERN_INVALID_NAME pset_name didn't denote a right.
1669 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1670 * KERN_ALREADY_IN_SET name was already a member of pset.
1674 mach_port_insert_member(
1676 mach_port_name_t name
,
1677 mach_port_name_t psname
)
1683 if (space
== IS_NULL
)
1684 return KERN_INVALID_TASK
;
1686 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1687 return KERN_INVALID_RIGHT
;
1689 kr
= ipc_object_translate_two(space
,
1690 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1691 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1692 if (kr
!= KERN_SUCCESS
)
1695 /* obj and psobj are locked (and were locked in that order) */
1696 assert(psobj
!= IO_NULL
);
1697 assert(obj
!= IO_NULL
);
1699 kr
= ipc_pset_add((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1706 * Routine: mach_port_extract_member [kernel call]
1708 * Remove a port from one portset that it is a member of.
1712 * KERN_SUCCESS Moved the port.
1713 * KERN_INVALID_TASK The space is null.
1714 * KERN_INVALID_TASK The space is dead.
1715 * KERN_INVALID_NAME Member didn't denote a right.
1716 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1717 * KERN_INVALID_NAME After didn't denote a right.
1718 * KERN_INVALID_RIGHT After didn't denote a port set right.
1720 * After is MACH_PORT_NULL and Member isn't in a port set.
1724 mach_port_extract_member(
1726 mach_port_name_t name
,
1727 mach_port_name_t psname
)
1733 if (space
== IS_NULL
)
1734 return KERN_INVALID_TASK
;
1736 if (!MACH_PORT_VALID(name
) || !MACH_PORT_VALID(psname
))
1737 return KERN_INVALID_RIGHT
;
1739 kr
= ipc_object_translate_two(space
,
1740 name
, MACH_PORT_RIGHT_RECEIVE
, &obj
,
1741 psname
, MACH_PORT_RIGHT_PORT_SET
, &psobj
);
1742 if (kr
!= KERN_SUCCESS
)
1745 /* obj and psobj are both locked (and were locked in that order) */
1746 assert(psobj
!= IO_NULL
);
1747 assert(obj
!= IO_NULL
);
1749 kr
= ipc_pset_remove((ipc_pset_t
)psobj
, (ipc_port_t
)obj
);
1756 * task_set_port_space:
1758 * Set port name space of task to specified size.
1761 task_set_port_space(
1767 is_write_lock(space
);
1768 kr
= ipc_entry_grow_table(space
, table_entries
);
1769 if (kr
== KERN_SUCCESS
)
1770 is_write_unlock(space
);