]> git.saurik.com Git - apple/xnu.git/blob - osfmk/kern/ipc_host.c
xnu-517.11.1.tar.gz
[apple/xnu.git] / osfmk / kern / ipc_host.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_COPYRIGHT@
24 */
25 /*
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
28 * All Rights Reserved.
29 *
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.
35 *
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.
39 *
40 * Carnegie Mellon requests users of this software to return to
41 *
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
46 *
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
49 */
50 /*
51 */
52
53 /*
54 * kern/ipc_host.c
55 *
56 * Routines to implement host ports.
57 */
58 #include <mach/message.h>
59 #include <mach/mach_traps.h>
60 #include <mach/etap_events.h>
61 #include <mach/mach_host_server.h>
62 #include <kern/host.h>
63 #include <kern/processor.h>
64 #include <kern/lock.h>
65 #include <kern/task.h>
66 #include <kern/thread.h>
67 #include <kern/ipc_host.h>
68 #include <kern/ipc_kobject.h>
69 #include <kern/misc_protos.h>
70 #include <kern/spl.h>
71 #include <ipc/ipc_port.h>
72 #include <ipc/ipc_space.h>
73
74 /*
75 * Forward declarations
76 */
77
78 void
79 ipc_processor_terminate(
80 processor_t processor);
81
82 void
83 ipc_processor_disable(
84 processor_t processor);
85
86 boolean_t
87 ref_pset_port_locked(
88 ipc_port_t port, boolean_t matchn, processor_set_t *ppset);
89
90 /*
91 * ipc_host_init: set up various things.
92 */
93
94 void ipc_host_init(void)
95 {
96 ipc_port_t port;
97 int i;
98
99 mutex_init(&realhost.lock, ETAP_MISC_MASTER);
100
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
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));
111
112 port = ipc_port_alloc_kernel();
113 if (port == IP_NULL)
114 panic("ipc_host_init");
115
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));
119
120 port = ipc_port_alloc_kernel();
121 if (port == IP_NULL)
122 panic("ipc_host_init");
123
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));
127
128 /* the rest of the special ports will be set up later */
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 */
137 ipc_pset_init(&default_pset);
138 ipc_pset_enable(&default_pset);
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
158 mach_port_name_t
159 host_self_trap(void)
160 {
161 ipc_port_t sright;
162
163 sright = ipc_port_copy_send(current_task()->itk_host);
164 return ipc_port_copyout_send(sright, current_space());
165 }
166
167 /*
168 * ipc_processor_init:
169 *
170 * Initialize ipc access to processor by allocating port.
171 */
172
173 void
174 ipc_processor_init(
175 processor_t processor)
176 {
177 ipc_port_t port;
178
179 port = ipc_port_alloc_kernel();
180 if (port == IP_NULL)
181 panic("ipc_processor_init");
182 processor->processor_self = port;
183 }
184
185 /*
186 * ipc_processor_enable:
187 *
188 * Enable ipc control of processor by setting port object.
189 */
190 void
191 ipc_processor_enable(
192 processor_t processor)
193 {
194 ipc_port_t myport;
195
196 myport = processor->processor_self;
197 ipc_kobject_set(myport, (ipc_kobject_t) processor, IKOT_PROCESSOR);
198 }
199
200 /*
201 * ipc_processor_disable:
202 *
203 * Disable ipc control of processor by clearing port object.
204 */
205 void
206 ipc_processor_disable(
207 processor_t processor)
208 {
209 ipc_port_t myport;
210
211 myport = processor->processor_self;
212 if (myport == IP_NULL)
213 return;
214 ipc_kobject_set(myport, IKO_NULL, IKOT_NONE);
215 }
216
217 /*
218 * ipc_processor_terminate:
219 *
220 * Processor is off-line. Destroy ipc control port.
221 */
222 void
223 ipc_processor_terminate(
224 processor_t processor)
225 {
226 ipc_port_t myport;
227 spl_t s;
228
229 s = splsched();
230 processor_lock(processor);
231 myport = processor->processor_self;
232 if (myport == IP_NULL) {
233 processor_unlock(processor);
234 splx(s);
235 return;
236 }
237
238 processor->processor_self = IP_NULL;
239 processor_unlock(processor);
240 splx(s);
241
242 ipc_port_dealloc_kernel(myport);
243 }
244
245 /*
246 * ipc_pset_init:
247 *
248 * Initialize ipc control of a processor set by allocating its ports.
249 */
250
251 void
252 ipc_pset_init(
253 processor_set_t pset)
254 {
255 ipc_port_t port;
256
257 port = ipc_port_alloc_kernel();
258 if (port == IP_NULL)
259 panic("ipc_pset_init");
260 pset->pset_self = port;
261
262 port = ipc_port_alloc_kernel();
263 if (port == IP_NULL)
264 panic("ipc_pset_init");
265 pset->pset_name_self = port;
266 }
267
268 /*
269 * ipc_pset_enable:
270 *
271 * Enable ipc access to a processor set.
272 */
273 void
274 ipc_pset_enable(
275 processor_set_t pset)
276 {
277 pset_lock(pset);
278 if (pset->active) {
279 ipc_kobject_set(pset->pset_self,
280 (ipc_kobject_t) pset, IKOT_PSET);
281 ipc_kobject_set(pset->pset_name_self,
282 (ipc_kobject_t) pset, IKOT_PSET_NAME);
283 pset->ref_count += 2;
284 }
285 pset_unlock(pset);
286 }
287
288 /*
289 * ipc_pset_disable:
290 *
291 * Disable ipc access to a processor set by clearing the port objects.
292 * Caller must hold pset lock and a reference to the pset. Ok to
293 * just decrement pset reference count as a result.
294 */
295 void
296 ipc_pset_disable(
297 processor_set_t pset)
298 {
299 ipc_kobject_set(pset->pset_self, IKO_NULL, IKOT_NONE);
300 ipc_kobject_set(pset->pset_name_self, IKO_NULL, IKOT_NONE);
301 pset->ref_count -= 2;
302 }
303
304 /*
305 * ipc_pset_terminate:
306 *
307 * Processor set is dead. Deallocate the ipc control structures.
308 */
309 void
310 ipc_pset_terminate(
311 processor_set_t pset)
312 {
313 ipc_port_dealloc_kernel(pset->pset_self);
314 ipc_port_dealloc_kernel(pset->pset_name_self);
315 }
316
317 /*
318 * processor_set_default, processor_set_default_priv:
319 *
320 * Return ports for manipulating default_processor set. MiG code
321 * differentiates between these two routines.
322 */
323 kern_return_t
324 processor_set_default(
325 host_t host,
326 processor_set_t *pset)
327 {
328 if (host == HOST_NULL)
329 return(KERN_INVALID_ARGUMENT);
330
331 *pset = &default_pset;
332 pset_reference(*pset);
333 return(KERN_SUCCESS);
334 }
335
336 /*
337 * Routine: convert_port_to_host
338 * Purpose:
339 * Convert from a port to a host.
340 * Doesn't consume the port ref; the host produced may be null.
341 * Conditions:
342 * Nothing locked.
343 */
344
345 host_t
346 convert_port_to_host(
347 ipc_port_t port)
348 {
349 host_t host = HOST_NULL;
350
351 if (IP_VALID(port)) {
352 ip_lock(port);
353 if (ip_active(port) &&
354 ((ip_kotype(port) == IKOT_HOST) ||
355 (ip_kotype(port) == IKOT_HOST_PRIV)
356 ))
357 host = (host_t) port->ip_kobject;
358 ip_unlock(port);
359 }
360
361 return host;
362 }
363
364 /*
365 * Routine: convert_port_to_host_priv
366 * Purpose:
367 * Convert from a port to a host.
368 * Doesn't consume the port ref; the host produced may be null.
369 * Conditions:
370 * Nothing locked.
371 */
372
373 host_t
374 convert_port_to_host_priv(
375 ipc_port_t port)
376 {
377 host_t host = HOST_NULL;
378
379 if (IP_VALID(port)) {
380 ip_lock(port);
381 if (ip_active(port) &&
382 (ip_kotype(port) == IKOT_HOST_PRIV))
383 host = (host_t) port->ip_kobject;
384 ip_unlock(port);
385 }
386
387 return host;
388 }
389
390 /*
391 * Routine: convert_port_to_processor
392 * Purpose:
393 * Convert from a port to a processor.
394 * Doesn't consume the port ref;
395 * the processor produced may be null.
396 * Conditions:
397 * Nothing locked.
398 */
399
400 processor_t
401 convert_port_to_processor(
402 ipc_port_t port)
403 {
404 processor_t processor = PROCESSOR_NULL;
405
406 if (IP_VALID(port)) {
407 ip_lock(port);
408 if (ip_active(port) &&
409 (ip_kotype(port) == IKOT_PROCESSOR))
410 processor = (processor_t) port->ip_kobject;
411 ip_unlock(port);
412 }
413
414 return processor;
415 }
416
417 /*
418 * Routine: convert_port_to_pset
419 * Purpose:
420 * Convert from a port to a pset.
421 * Doesn't consume the port ref; produces a pset ref,
422 * which may be null.
423 * Conditions:
424 * Nothing locked.
425 */
426
427 processor_set_t
428 convert_port_to_pset(
429 ipc_port_t port)
430 {
431 boolean_t r;
432 processor_set_t pset = PROCESSOR_SET_NULL;
433
434 r = FALSE;
435 while (!r && IP_VALID(port)) {
436 ip_lock(port);
437 r = ref_pset_port_locked(port, FALSE, &pset);
438 /* port unlocked */
439 }
440 return pset;
441 }
442
443 /*
444 * Routine: convert_port_to_pset_name
445 * Purpose:
446 * Convert from a port to a pset.
447 * Doesn't consume the port ref; produces a pset ref,
448 * which may be null.
449 * Conditions:
450 * Nothing locked.
451 */
452
453 processor_set_name_t
454 convert_port_to_pset_name(
455 ipc_port_t port)
456 {
457 boolean_t r;
458 processor_set_t pset = PROCESSOR_SET_NULL;
459
460 r = FALSE;
461 while (!r && IP_VALID(port)) {
462 ip_lock(port);
463 r = ref_pset_port_locked(port, TRUE, &pset);
464 /* port unlocked */
465 }
466 return pset;
467 }
468
469 boolean_t
470 ref_pset_port_locked(ipc_port_t port, boolean_t matchn, processor_set_t *ppset)
471 {
472 processor_set_t pset;
473
474 pset = PROCESSOR_SET_NULL;
475 if (ip_active(port) &&
476 ((ip_kotype(port) == IKOT_PSET) ||
477 (matchn && (ip_kotype(port) == IKOT_PSET_NAME)))) {
478 pset = (processor_set_t) port->ip_kobject;
479 if (!pset_lock_try(pset)) {
480 ip_unlock(port);
481 mutex_pause();
482 return (FALSE);
483 }
484 pset->ref_count++;
485 pset_unlock(pset);
486 }
487 *ppset = pset;
488 ip_unlock(port);
489 return (TRUE);
490 }
491
492 /*
493 * Routine: convert_host_to_port
494 * Purpose:
495 * Convert from a host to a port.
496 * Produces a naked send right which may be invalid.
497 * Conditions:
498 * Nothing locked.
499 */
500
501 ipc_port_t
502 convert_host_to_port(
503 host_t host)
504 {
505 ipc_port_t port;
506
507 host_get_host_port(host, &port);
508 return port;
509 }
510
511 /*
512 * Routine: convert_processor_to_port
513 * Purpose:
514 * Convert from a processor to a port.
515 * Produces a naked send right which may be invalid.
516 * Conditions:
517 * Nothing locked.
518 */
519
520 ipc_port_t
521 convert_processor_to_port(
522 processor_t processor)
523 {
524 ipc_port_t port;
525 spl_t s;
526
527 s = splsched();
528 processor_lock(processor);
529
530 if (processor->processor_self != IP_NULL)
531 port = ipc_port_make_send(processor->processor_self);
532 else
533 port = IP_NULL;
534
535 processor_unlock(processor);
536 splx(s);
537
538 return port;
539 }
540
541 /*
542 * Routine: convert_pset_to_port
543 * Purpose:
544 * Convert from a pset to a port.
545 * Consumes a pset ref; produces a naked send right
546 * which may be invalid.
547 * Conditions:
548 * Nothing locked.
549 */
550
551 ipc_port_t
552 convert_pset_to_port(
553 processor_set_t pset)
554 {
555 ipc_port_t port;
556
557 pset_lock(pset);
558 if (pset->active)
559 port = ipc_port_make_send(pset->pset_self);
560 else
561 port = IP_NULL;
562 pset_unlock(pset);
563
564 pset_deallocate(pset);
565 return port;
566 }
567
568 /*
569 * Routine: convert_pset_name_to_port
570 * Purpose:
571 * Convert from a pset to a port.
572 * Consumes a pset ref; produces a naked send right
573 * which may be invalid.
574 * Conditions:
575 * Nothing locked.
576 */
577
578 ipc_port_t
579 convert_pset_name_to_port(
580 processor_set_name_t pset)
581 {
582 ipc_port_t port;
583
584 pset_lock(pset);
585 if (pset->active)
586 port = ipc_port_make_send(pset->pset_name_self);
587 else
588 port = IP_NULL;
589 pset_unlock(pset);
590
591 pset_deallocate(pset);
592 return port;
593 }
594
595 /*
596 * Routine: convert_port_to_host_security
597 * Purpose:
598 * Convert from a port to a host security.
599 * Doesn't consume the port ref; the port produced may be null.
600 * Conditions:
601 * Nothing locked.
602 */
603
604 host_t
605 convert_port_to_host_security(
606 ipc_port_t port)
607 {
608 host_t host = HOST_NULL;
609
610 if (IP_VALID(port)) {
611 ip_lock(port);
612 if (ip_active(port) &&
613 (ip_kotype(port) == IKOT_HOST_SECURITY))
614 host = (host_t) port->ip_kobject;
615 ip_unlock(port);
616 }
617
618 return host;
619 }
620
621 /*
622 * Routine: host_set_exception_ports [kernel call]
623 * Purpose:
624 * Sets the host exception port, flavor and
625 * behavior for the exception types specified by the mask.
626 * There will be one send right per exception per valid
627 * port.
628 * Conditions:
629 * Nothing locked. If successful, consumes
630 * the supplied send right.
631 * Returns:
632 * KERN_SUCCESS Changed the special port.
633 * KERN_INVALID_ARGUMENT The host_priv is not valid,
634 * Illegal mask bit set.
635 * Illegal exception behavior
636 */
637 kern_return_t
638 host_set_exception_ports(
639 host_priv_t host_priv,
640 exception_mask_t exception_mask,
641 ipc_port_t new_port,
642 exception_behavior_t new_behavior,
643 thread_state_flavor_t new_flavor)
644 {
645 register int i;
646 ipc_port_t old_port[EXC_TYPES_COUNT];
647
648 if (host_priv == HOST_PRIV_NULL) {
649 return KERN_INVALID_ARGUMENT;
650 }
651
652 assert(host_priv == &realhost);
653
654 if (exception_mask & ~EXC_MASK_ALL) {
655 return KERN_INVALID_ARGUMENT;
656 }
657
658 if (IP_VALID(new_port)) {
659 switch (new_behavior) {
660 case EXCEPTION_DEFAULT:
661 case EXCEPTION_STATE:
662 case EXCEPTION_STATE_IDENTITY:
663 break;
664 default:
665 return KERN_INVALID_ARGUMENT;
666 }
667 }
668 /* Cannot easily check "new_flavor", but that just means that
669 * the flavor in the generated exception message might be garbage:
670 * GIGO
671 */
672 host_lock(host_priv);
673
674 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
675 if (exception_mask & (1 << i)) {
676 old_port[i] = host_priv->exc_actions[i].port;
677 host_priv->exc_actions[i].port =
678 ipc_port_copy_send(new_port);
679 host_priv->exc_actions[i].behavior = new_behavior;
680 host_priv->exc_actions[i].flavor = new_flavor;
681 } else
682 old_port[i] = IP_NULL;
683 }/* for */
684
685 /*
686 * Consume send rights without any lock held.
687 */
688 host_unlock(host_priv);
689 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++)
690 if (IP_VALID(old_port[i]))
691 ipc_port_release_send(old_port[i]);
692 if (IP_VALID(new_port)) /* consume send right */
693 ipc_port_release_send(new_port);
694
695 return KERN_SUCCESS;
696 }
697
698 /*
699 * Routine: host_get_exception_ports [kernel call]
700 * Purpose:
701 * Clones a send right for each of the host's exception
702 * ports specified in the mask and returns the behaviour
703 * and flavor of said port.
704 *
705 * Returns upto [in} CountCnt elements.
706 *
707 * Conditions:
708 * Nothing locked.
709 * Returns:
710 * KERN_SUCCESS Extracted a send right.
711 * KERN_INVALID_ARGUMENT Invalid host_priv specified,
712 * Invalid special port,
713 * Illegal mask bit set.
714 * KERN_FAILURE The thread is dead.
715 */
716 kern_return_t
717 host_get_exception_ports(
718 host_priv_t host_priv,
719 exception_mask_t exception_mask,
720 exception_mask_array_t masks,
721 mach_msg_type_number_t * CountCnt,
722 exception_port_array_t ports,
723 exception_behavior_array_t behaviors,
724 thread_state_flavor_array_t flavors )
725 {
726 register int i,
727 j,
728 count;
729
730 if (host_priv == HOST_PRIV_NULL)
731 return KERN_INVALID_ARGUMENT;
732
733 if (exception_mask & ~EXC_MASK_ALL) {
734 return KERN_INVALID_ARGUMENT;
735 }
736
737 assert (host_priv == &realhost);
738
739 host_lock(host_priv);
740
741 count = 0;
742
743 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
744 if (exception_mask & (1 << i)) {
745 for (j = 0; j < count; j++) {
746 /*
747 * search for an identical entry, if found
748 * set corresponding mask for this exception.
749 */
750 if (host_priv->exc_actions[i].port == ports[j] &&
751 host_priv->exc_actions[i].behavior == behaviors[j]
752 && host_priv->exc_actions[i].flavor == flavors[j])
753 {
754 masks[j] |= (1 << i);
755 break;
756 }
757 }/* for */
758 if (j == count) {
759 masks[j] = (1 << i);
760 ports[j] =
761 ipc_port_copy_send(host_priv->exc_actions[i].port);
762 behaviors[j] = host_priv->exc_actions[i].behavior;
763 flavors[j] = host_priv->exc_actions[i].flavor;
764 count++;
765 if (count > *CountCnt) {
766 break;
767 }
768 }
769 }
770 }/* for */
771 host_unlock(host_priv);
772
773 *CountCnt = count;
774 return KERN_SUCCESS;
775 }
776
777 kern_return_t
778 host_swap_exception_ports(
779 host_priv_t host_priv,
780 exception_mask_t exception_mask,
781 ipc_port_t new_port,
782 exception_behavior_t new_behavior,
783 thread_state_flavor_t new_flavor,
784 exception_mask_array_t masks,
785 mach_msg_type_number_t * CountCnt,
786 exception_port_array_t ports,
787 exception_behavior_array_t behaviors,
788 thread_state_flavor_array_t flavors )
789 {
790 register int i,
791 j,
792 count;
793 ipc_port_t old_port[EXC_TYPES_COUNT];
794
795 if (host_priv == HOST_PRIV_NULL)
796 return KERN_INVALID_ARGUMENT;
797
798 if (exception_mask & ~EXC_MASK_ALL) {
799 return KERN_INVALID_ARGUMENT;
800 }
801
802 if (IP_VALID(new_port)) {
803 switch (new_behavior) {
804 case EXCEPTION_DEFAULT:
805 case EXCEPTION_STATE:
806 case EXCEPTION_STATE_IDENTITY:
807 break;
808 default:
809 return KERN_INVALID_ARGUMENT;
810 }
811 }
812 /* Cannot easily check "new_flavor", but that just means that
813 * the flavor in the generated exception message might be garbage:
814 * GIGO */
815
816 host_lock(host_priv);
817
818 count = 0;
819
820 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++) {
821 if (exception_mask & (1 << i)) {
822 for (j = 0; j < count; j++) {
823 /*
824 * search for an identical entry, if found
825 * set corresponding mask for this exception.
826 */
827 if (host_priv->exc_actions[i].port == ports[j] &&
828 host_priv->exc_actions[i].behavior == behaviors[j]
829 && host_priv->exc_actions[i].flavor == flavors[j])
830 {
831 masks[j] |= (1 << i);
832 break;
833 }
834 }/* for */
835 if (j == count) {
836 masks[j] = (1 << i);
837 ports[j] =
838 ipc_port_copy_send(host_priv->exc_actions[i].port);
839 behaviors[j] = host_priv->exc_actions[i].behavior;
840 flavors[j] = host_priv->exc_actions[i].flavor;
841 count++;
842 }
843 old_port[i] = host_priv->exc_actions[i].port;
844 host_priv->exc_actions[i].port =
845 ipc_port_copy_send(new_port);
846 host_priv->exc_actions[i].behavior = new_behavior;
847 host_priv->exc_actions[i].flavor = new_flavor;
848 if (count > *CountCnt) {
849 break;
850 }
851 } else
852 old_port[i] = IP_NULL;
853 }/* for */
854 host_unlock(host_priv);
855
856 /*
857 * Consume send rights without any lock held.
858 */
859 for (i = FIRST_EXCEPTION; i < EXC_TYPES_COUNT; i++)
860 if (IP_VALID(old_port[i]))
861 ipc_port_release_send(old_port[i]);
862 if (IP_VALID(new_port)) /* consume send right */
863 ipc_port_release_send(new_port);
864 *CountCnt = count;
865
866 return KERN_SUCCESS;
867 }