]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/ipc_host.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / osfmk / kern / ipc_host.c
CommitLineData
1c79356b 1/*
b0d623f7 2 * Copyright (c) 2000-2009 Apple Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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 License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56/*
57 */
58
59/*
60 * kern/ipc_host.c
61 *
62 * Routines to implement host ports.
63 */
64#include <mach/message.h>
65#include <mach/mach_traps.h>
66#include <mach/mach_host_server.h>
91447636 67#include <mach/host_priv_server.h>
1c79356b
A
68#include <kern/host.h>
69#include <kern/processor.h>
70#include <kern/task.h>
71#include <kern/thread.h>
72#include <kern/ipc_host.h>
73#include <kern/ipc_kobject.h>
74#include <kern/misc_protos.h>
75#include <kern/spl.h>
76#include <ipc/ipc_port.h>
77#include <ipc/ipc_space.h>
78
79/*
80 * Forward declarations
81 */
82
1c79356b
A
83boolean_t
84ref_pset_port_locked(
85 ipc_port_t port, boolean_t matchn, processor_set_t *ppset);
86
87/*
88 * ipc_host_init: set up various things.
89 */
90
b0d623f7
A
91extern lck_grp_t host_notify_lock_grp;
92extern lck_attr_t host_notify_lock_attr;
93
1c79356b
A
94void ipc_host_init(void)
95{
96 ipc_port_t port;
97 int i;
98
b0d623f7 99 lck_mtx_init(&realhost.lock, &host_notify_lock_grp, &host_notify_lock_attr);
0b4e3aa0 100
1c79356b
A
101 /*
102 * Allocate and set up the two host ports.
103 */
104 port = ipc_port_alloc_kernel();
105 if (port == IP_NULL)
106 panic("ipc_host_init");
107
55e303ae
A
108 ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST_SECURITY);
109 kernel_set_special_port(&realhost, HOST_SECURITY_PORT,
110 ipc_port_make_send(port));
1c79356b
A
111
112 port = ipc_port_alloc_kernel();
113 if (port == IP_NULL)
114 panic("ipc_host_init");
115
55e303ae
A
116 ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST);
117 kernel_set_special_port(&realhost, HOST_PORT,
118 ipc_port_make_send(port));
1c79356b
A
119
120 port = ipc_port_alloc_kernel();
121 if (port == IP_NULL)
122 panic("ipc_host_init");
123
55e303ae
A
124 ipc_kobject_set(port, (ipc_kobject_t) &realhost, IKOT_HOST_PRIV);
125 kernel_set_special_port(&realhost, HOST_PRIV_PORT,
126 ipc_port_make_send(port));
1c79356b 127
55e303ae 128 /* the rest of the special ports will be set up later */
1c79356b
A
129
130 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
131 realhost.exc_actions[i].port = IP_NULL;
132 }/* for */
133
134 /*
135 * Set up ipc for default processor set.
136 */
2d21ac55
A
137 ipc_pset_init(&pset0);
138 ipc_pset_enable(&pset0);
1c79356b
A
139
140 /*
141 * And for master processor
142 */
143 ipc_processor_init(master_processor);
144 ipc_processor_enable(master_processor);
145}
146
147/*
148 * Routine: host_self_trap [mach trap]
149 * Purpose:
150 * Give the caller send rights for his own host port.
151 * Conditions:
152 * Nothing locked.
153 * Returns:
154 * MACH_PORT_NULL if there are any resource failures
155 * or other errors.
156 */
157
158mach_port_name_t
91447636
A
159host_self_trap(
160 __unused struct host_self_trap_args *args)
1c79356b
A
161{
162 ipc_port_t sright;
91447636 163 mach_port_name_t name;
1c79356b
A
164
165 sright = ipc_port_copy_send(current_task()->itk_host);
91447636
A
166 name = ipc_port_copyout_send(sright, current_space());
167 return name;
1c79356b
A
168}
169
170/*
171 * ipc_processor_init:
172 *
173 * Initialize ipc access to processor by allocating port.
174 */
175
176void
177ipc_processor_init(
178 processor_t processor)
179{
180 ipc_port_t port;
181
182 port = ipc_port_alloc_kernel();
183 if (port == IP_NULL)
184 panic("ipc_processor_init");
185 processor->processor_self = port;
186}
187
188/*
189 * ipc_processor_enable:
190 *
191 * Enable ipc control of processor by setting port object.
192 */
193void
194ipc_processor_enable(
195 processor_t processor)
196{
197 ipc_port_t myport;
198
199 myport = processor->processor_self;
200 ipc_kobject_set(myport, (ipc_kobject_t) processor, IKOT_PROCESSOR);
201}
1c79356b
A
202
203/*
204 * ipc_pset_init:
205 *
206 * Initialize ipc control of a processor set by allocating its ports.
207 */
208
209void
210ipc_pset_init(
211 processor_set_t pset)
212{
213 ipc_port_t port;
214
215 port = ipc_port_alloc_kernel();
216 if (port == IP_NULL)
217 panic("ipc_pset_init");
218 pset->pset_self = port;
219
220 port = ipc_port_alloc_kernel();
221 if (port == IP_NULL)
222 panic("ipc_pset_init");
223 pset->pset_name_self = port;
224}
225
226/*
227 * ipc_pset_enable:
228 *
229 * Enable ipc access to a processor set.
230 */
231void
232ipc_pset_enable(
233 processor_set_t pset)
234{
2d21ac55
A
235 ipc_kobject_set(pset->pset_self, (ipc_kobject_t) pset, IKOT_PSET);
236 ipc_kobject_set(pset->pset_name_self, (ipc_kobject_t) pset, IKOT_PSET_NAME);
1c79356b
A
237}
238
239/*
2d21ac55 240 * processor_set_default:
1c79356b 241 *
2d21ac55 242 * Return ports for manipulating default_processor set.
1c79356b
A
243 */
244kern_return_t
245processor_set_default(
246 host_t host,
247 processor_set_t *pset)
248{
249 if (host == HOST_NULL)
250 return(KERN_INVALID_ARGUMENT);
251
2d21ac55
A
252 *pset = &pset0;
253
254 return (KERN_SUCCESS);
1c79356b
A
255}
256
257/*
258 * Routine: convert_port_to_host
259 * Purpose:
260 * Convert from a port to a host.
261 * Doesn't consume the port ref; the host produced may be null.
262 * Conditions:
263 * Nothing locked.
264 */
265
266host_t
267convert_port_to_host(
268 ipc_port_t port)
269{
270 host_t host = HOST_NULL;
271
272 if (IP_VALID(port)) {
273 ip_lock(port);
274 if (ip_active(port) &&
275 ((ip_kotype(port) == IKOT_HOST) ||
276 (ip_kotype(port) == IKOT_HOST_PRIV)
277 ))
278 host = (host_t) port->ip_kobject;
279 ip_unlock(port);
280 }
281
282 return host;
283}
284
285/*
286 * Routine: convert_port_to_host_priv
287 * Purpose:
288 * Convert from a port to a host.
289 * Doesn't consume the port ref; the host produced may be null.
290 * Conditions:
291 * Nothing locked.
292 */
293
294host_t
295convert_port_to_host_priv(
296 ipc_port_t port)
297{
298 host_t host = HOST_NULL;
299
300 if (IP_VALID(port)) {
301 ip_lock(port);
302 if (ip_active(port) &&
303 (ip_kotype(port) == IKOT_HOST_PRIV))
304 host = (host_t) port->ip_kobject;
305 ip_unlock(port);
306 }
307
308 return host;
309}
310
311/*
312 * Routine: convert_port_to_processor
313 * Purpose:
314 * Convert from a port to a processor.
315 * Doesn't consume the port ref;
316 * the processor produced may be null.
317 * Conditions:
318 * Nothing locked.
319 */
320
321processor_t
322convert_port_to_processor(
323 ipc_port_t port)
324{
325 processor_t processor = PROCESSOR_NULL;
326
327 if (IP_VALID(port)) {
328 ip_lock(port);
329 if (ip_active(port) &&
330 (ip_kotype(port) == IKOT_PROCESSOR))
331 processor = (processor_t) port->ip_kobject;
332 ip_unlock(port);
333 }
334
335 return processor;
336}
337
338/*
339 * Routine: convert_port_to_pset
340 * Purpose:
341 * Convert from a port to a pset.
342 * Doesn't consume the port ref; produces a pset ref,
343 * which may be null.
344 * Conditions:
345 * Nothing locked.
346 */
347
348processor_set_t
349convert_port_to_pset(
350 ipc_port_t port)
351{
352 boolean_t r;
353 processor_set_t pset = PROCESSOR_SET_NULL;
354
355 r = FALSE;
356 while (!r && IP_VALID(port)) {
357 ip_lock(port);
358 r = ref_pset_port_locked(port, FALSE, &pset);
359 /* port unlocked */
360 }
361 return pset;
362}
363
364/*
365 * Routine: convert_port_to_pset_name
366 * Purpose:
367 * Convert from a port to a pset.
368 * Doesn't consume the port ref; produces a pset ref,
369 * which may be null.
370 * Conditions:
371 * Nothing locked.
372 */
373
374processor_set_name_t
375convert_port_to_pset_name(
376 ipc_port_t port)
377{
378 boolean_t r;
379 processor_set_t pset = PROCESSOR_SET_NULL;
380
381 r = FALSE;
382 while (!r && IP_VALID(port)) {
383 ip_lock(port);
384 r = ref_pset_port_locked(port, TRUE, &pset);
385 /* port unlocked */
386 }
387 return pset;
388}
389
390boolean_t
391ref_pset_port_locked(ipc_port_t port, boolean_t matchn, processor_set_t *ppset)
392{
393 processor_set_t pset;
394
395 pset = PROCESSOR_SET_NULL;
396 if (ip_active(port) &&
397 ((ip_kotype(port) == IKOT_PSET) ||
2d21ac55 398 (matchn && (ip_kotype(port) == IKOT_PSET_NAME)))) {
1c79356b 399 pset = (processor_set_t) port->ip_kobject;
1c79356b 400 }
2d21ac55 401
1c79356b
A
402 *ppset = pset;
403 ip_unlock(port);
2d21ac55 404
1c79356b
A
405 return (TRUE);
406}
407
408/*
409 * Routine: convert_host_to_port
410 * Purpose:
411 * Convert from a host to a port.
412 * Produces a naked send right which may be invalid.
413 * Conditions:
414 * Nothing locked.
415 */
416
417ipc_port_t
418convert_host_to_port(
419 host_t host)
420{
421 ipc_port_t port;
422
55e303ae 423 host_get_host_port(host, &port);
1c79356b
A
424 return port;
425}
426
427/*
428 * Routine: convert_processor_to_port
429 * Purpose:
430 * Convert from a processor to a port.
431 * Produces a naked send right which may be invalid.
b0d623f7 432 * Processors are not reference counted, so nothing to release.
1c79356b
A
433 * Conditions:
434 * Nothing locked.
435 */
436
437ipc_port_t
438convert_processor_to_port(
439 processor_t processor)
440{
b0d623f7 441 ipc_port_t port = processor->processor_self;
1c79356b 442
b0d623f7
A
443 if (port != IP_NULL)
444 port = ipc_port_make_send(port);
1c79356b
A
445 return port;
446}
447
448/*
449 * Routine: convert_pset_to_port
450 * Purpose:
451 * Convert from a pset to a port.
b0d623f7
A
452 * Produces a naked send right which may be invalid.
453 * Processor sets are not reference counted, so nothing to release.
1c79356b
A
454 * Conditions:
455 * Nothing locked.
456 */
457
458ipc_port_t
459convert_pset_to_port(
460 processor_set_t pset)
461{
2d21ac55 462 ipc_port_t port = pset->pset_self;
1c79356b 463
2d21ac55
A
464 if (port != IP_NULL)
465 port = ipc_port_make_send(port);
1c79356b 466
1c79356b
A
467 return port;
468}
469
470/*
471 * Routine: convert_pset_name_to_port
472 * Purpose:
473 * Convert from a pset to a port.
b0d623f7
A
474 * Produces a naked send right which may be invalid.
475 * Processor sets are not reference counted, so nothing to release.
1c79356b
A
476 * Conditions:
477 * Nothing locked.
478 */
479
480ipc_port_t
481convert_pset_name_to_port(
482 processor_set_name_t pset)
483{
2d21ac55 484 ipc_port_t port = pset->pset_name_self;
1c79356b 485
2d21ac55
A
486 if (port != IP_NULL)
487 port = ipc_port_make_send(port);
1c79356b 488
1c79356b
A
489 return port;
490}
491
492/*
493 * Routine: convert_port_to_host_security
494 * Purpose:
495 * Convert from a port to a host security.
496 * Doesn't consume the port ref; the port produced may be null.
497 * Conditions:
498 * Nothing locked.
499 */
500
501host_t
502convert_port_to_host_security(
503 ipc_port_t port)
504{
505 host_t host = HOST_NULL;
506
507 if (IP_VALID(port)) {
508 ip_lock(port);
509 if (ip_active(port) &&
510 (ip_kotype(port) == IKOT_HOST_SECURITY))
511 host = (host_t) port->ip_kobject;
512 ip_unlock(port);
513 }
514
515 return host;
516}
517
518/*
519 * Routine: host_set_exception_ports [kernel call]
520 * Purpose:
521 * Sets the host exception port, flavor and
522 * behavior for the exception types specified by the mask.
523 * There will be one send right per exception per valid
524 * port.
525 * Conditions:
526 * Nothing locked. If successful, consumes
527 * the supplied send right.
528 * Returns:
529 * KERN_SUCCESS Changed the special port.
530 * KERN_INVALID_ARGUMENT The host_priv is not valid,
531 * Illegal mask bit set.
532 * Illegal exception behavior
533 */
534kern_return_t
535host_set_exception_ports(
536 host_priv_t host_priv,
537 exception_mask_t exception_mask,
538 ipc_port_t new_port,
539 exception_behavior_t new_behavior,
540 thread_state_flavor_t new_flavor)
541{
542 register int i;
543 ipc_port_t old_port[EXC_TYPES_COUNT];
544
545 if (host_priv == HOST_PRIV_NULL) {
546 return KERN_INVALID_ARGUMENT;
547 }
548
549 assert(host_priv == &realhost);
550
b0d623f7 551 if (exception_mask & ~EXC_MASK_VALID) {
1c79356b
A
552 return KERN_INVALID_ARGUMENT;
553 }
554
555 if (IP_VALID(new_port)) {
2d21ac55 556 switch (new_behavior & ~MACH_EXCEPTION_CODES) {
1c79356b
A
557 case EXCEPTION_DEFAULT:
558 case EXCEPTION_STATE:
559 case EXCEPTION_STATE_IDENTITY:
560 break;
561 default:
562 return KERN_INVALID_ARGUMENT;
563 }
564 }
fe8ab488
A
565
566 /*
567 * Check the validity of the thread_state_flavor by calling the
568 * VALID_THREAD_STATE_FLAVOR architecture dependent macro defined in
569 * osfmk/mach/ARCHITECTURE/thread_status.h
1c79356b 570 */
fe8ab488
A
571 if (new_flavor != 0 && !VALID_THREAD_STATE_FLAVOR(new_flavor))
572 return (KERN_INVALID_ARGUMENT);
573
1c79356b
A
574 host_lock(host_priv);
575
576 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
577 if (exception_mask & (1 << i)) {
578 old_port[i] = host_priv->exc_actions[i].port;
579 host_priv->exc_actions[i].port =
580 ipc_port_copy_send(new_port);
581 host_priv->exc_actions[i].behavior = new_behavior;
582 host_priv->exc_actions[i].flavor = new_flavor;
583 } else
584 old_port[i] = IP_NULL;
585 }/* for */
586
587 /*
588 * Consume send rights without any lock held.
589 */
590 host_unlock(host_priv);
591 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++)
592 if (IP_VALID(old_port[i]))
593 ipc_port_release_send(old_port[i]);
594 if (IP_VALID(new_port)) /* consume send right */
595 ipc_port_release_send(new_port);
596
597 return KERN_SUCCESS;
598}
599
600/*
601 * Routine: host_get_exception_ports [kernel call]
602 * Purpose:
603 * Clones a send right for each of the host's exception
604 * ports specified in the mask and returns the behaviour
605 * and flavor of said port.
606 *
607 * Returns upto [in} CountCnt elements.
608 *
609 * Conditions:
610 * Nothing locked.
611 * Returns:
612 * KERN_SUCCESS Extracted a send right.
613 * KERN_INVALID_ARGUMENT Invalid host_priv specified,
614 * Invalid special port,
615 * Illegal mask bit set.
616 * KERN_FAILURE The thread is dead.
617 */
618kern_return_t
619host_get_exception_ports(
620 host_priv_t host_priv,
621 exception_mask_t exception_mask,
622 exception_mask_array_t masks,
623 mach_msg_type_number_t * CountCnt,
624 exception_port_array_t ports,
625 exception_behavior_array_t behaviors,
626 thread_state_flavor_array_t flavors )
627{
91447636 628 unsigned int i, j, count;
1c79356b
A
629
630 if (host_priv == HOST_PRIV_NULL)
631 return KERN_INVALID_ARGUMENT;
632
b0d623f7 633 if (exception_mask & ~EXC_MASK_VALID) {
1c79356b
A
634 return KERN_INVALID_ARGUMENT;
635 }
636
637 assert (host_priv == &realhost);
638
639 host_lock(host_priv);
640
641 count = 0;
642
643 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
644 if (exception_mask & (1 << i)) {
645 for (j = 0; j < count; j++) {
646/*
647 * search for an identical entry, if found
648 * set corresponding mask for this exception.
649 */
650 if (host_priv->exc_actions[i].port == ports[j] &&
651 host_priv->exc_actions[i].behavior == behaviors[j]
652 && host_priv->exc_actions[i].flavor == flavors[j])
653 {
654 masks[j] |= (1 << i);
655 break;
656 }
657 }/* for */
658 if (j == count) {
659 masks[j] = (1 << i);
660 ports[j] =
661 ipc_port_copy_send(host_priv->exc_actions[i].port);
662 behaviors[j] = host_priv->exc_actions[i].behavior;
663 flavors[j] = host_priv->exc_actions[i].flavor;
664 count++;
665 if (count > *CountCnt) {
666 break;
667 }
668 }
669 }
670 }/* for */
671 host_unlock(host_priv);
672
673 *CountCnt = count;
674 return KERN_SUCCESS;
675}
676
677kern_return_t
678host_swap_exception_ports(
679 host_priv_t host_priv,
680 exception_mask_t exception_mask,
681 ipc_port_t new_port,
682 exception_behavior_t new_behavior,
683 thread_state_flavor_t new_flavor,
684 exception_mask_array_t masks,
685 mach_msg_type_number_t * CountCnt,
686 exception_port_array_t ports,
687 exception_behavior_array_t behaviors,
688 thread_state_flavor_array_t flavors )
689{
91447636 690 unsigned int i,
1c79356b
A
691 j,
692 count;
693 ipc_port_t old_port[EXC_TYPES_COUNT];
694
695 if (host_priv == HOST_PRIV_NULL)
696 return KERN_INVALID_ARGUMENT;
697
b0d623f7 698 if (exception_mask & ~EXC_MASK_VALID) {
1c79356b
A
699 return KERN_INVALID_ARGUMENT;
700 }
701
702 if (IP_VALID(new_port)) {
703 switch (new_behavior) {
704 case EXCEPTION_DEFAULT:
705 case EXCEPTION_STATE:
706 case EXCEPTION_STATE_IDENTITY:
707 break;
708 default:
709 return KERN_INVALID_ARGUMENT;
710 }
711 }
39236c6e 712
fe8ab488
A
713 if (new_flavor != 0 && !VALID_THREAD_STATE_FLAVOR(new_flavor))
714 return (KERN_INVALID_ARGUMENT);
1c79356b
A
715
716 host_lock(host_priv);
717
39236c6e
A
718 assert(EXC_TYPES_COUNT > FIRST_EXCEPTION);
719 for (count=0, i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT && count < *CountCnt; i++) {
1c79356b
A
720 if (exception_mask & (1 << i)) {
721 for (j = 0; j < count; j++) {
722/*
723 * search for an identical entry, if found
724 * set corresponding mask for this exception.
725 */
726 if (host_priv->exc_actions[i].port == ports[j] &&
727 host_priv->exc_actions[i].behavior == behaviors[j]
728 && host_priv->exc_actions[i].flavor == flavors[j])
729 {
730 masks[j] |= (1 << i);
731 break;
732 }
733 }/* for */
734 if (j == count) {
735 masks[j] = (1 << i);
736 ports[j] =
737 ipc_port_copy_send(host_priv->exc_actions[i].port);
738 behaviors[j] = host_priv->exc_actions[i].behavior;
739 flavors[j] = host_priv->exc_actions[i].flavor;
740 count++;
741 }
742 old_port[i] = host_priv->exc_actions[i].port;
743 host_priv->exc_actions[i].port =
744 ipc_port_copy_send(new_port);
745 host_priv->exc_actions[i].behavior = new_behavior;
746 host_priv->exc_actions[i].flavor = new_flavor;
1c79356b
A
747 } else
748 old_port[i] = IP_NULL;
749 }/* for */
750 host_unlock(host_priv);
751
752 /*
753 * Consume send rights without any lock held.
754 */
39236c6e 755 while (--i >= FIRST_EXCEPTION) {
1c79356b
A
756 if (IP_VALID(old_port[i]))
757 ipc_port_release_send(old_port[i]);
39236c6e
A
758 }
759
1c79356b
A
760 if (IP_VALID(new_port)) /* consume send right */
761 ipc_port_release_send(new_port);
762 *CountCnt = count;
763
764 return KERN_SUCCESS;
765}