2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the 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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * @OSF_FREE_COPYRIGHT@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce
58 * support for mandatory and extensible security protections. This notice
59 * is included in support of clause 2.2 (b) of the Apple Public License,
65 * File: ipc/ipc_port.c
69 * Functions to manipulate IPC ports.
74 #include <zone_debug.h>
75 #include <mach_assert.h>
77 #include <mach/port.h>
78 #include <mach/kern_return.h>
79 #include <kern/lock.h>
80 #include <kern/ipc_kobject.h>
81 #include <kern/thread.h>
82 #include <kern/misc_protos.h>
83 #include <kern/wait_queue.h>
84 #include <ipc/ipc_entry.h>
85 #include <ipc/ipc_space.h>
86 #include <ipc/ipc_object.h>
87 #include <ipc/ipc_port.h>
88 #include <ipc/ipc_pset.h>
89 #include <ipc/ipc_kmsg.h>
90 #include <ipc/ipc_mqueue.h>
91 #include <ipc/ipc_notify.h>
92 #include <ipc/ipc_print.h>
93 #include <ipc/ipc_table.h>
95 #include <security/mac_mach_internal.h>
98 #include <machine/db_machdep.h>
99 #include <ddb/db_command.h>
100 #include <ddb/db_expr.h>
101 #endif /* MACH_KDB */
105 decl_lck_mtx_data(, ipc_port_multiple_lock_data
)
106 decl_lck_mtx_data(, ipc_port_timestamp_lock_data
)
107 lck_mtx_ext_t ipc_port_multiple_lock_data_ext
;
108 lck_mtx_ext_t ipc_port_timestamp_lock_data_ext
;
109 ipc_port_timestamp_t ipc_port_timestamp_data
;
113 void ipc_port_init_debug(
115 #endif /* MACH_ASSERT */
117 #if MACH_KDB && ZONE_DEBUG
119 void print_type_ports(unsigned, unsigned);
120 void print_ports(void);
121 #endif /* MACH_KDB && ZONE_DEBUG */
124 * Routine: ipc_port_timestamp
126 * Retrieve a timestamp value.
130 ipc_port_timestamp(void)
132 ipc_port_timestamp_t timestamp
;
134 ipc_port_timestamp_lock();
135 timestamp
= ipc_port_timestamp_data
++;
136 ipc_port_timestamp_unlock();
142 * Routine: ipc_port_dnrequest
144 * Try to allocate a dead-name request slot.
145 * If successful, returns the request index.
146 * Otherwise returns zero.
148 * The port is locked and active.
150 * KERN_SUCCESS A request index was found.
151 * KERN_NO_SPACE No index allocated.
157 mach_port_name_t name
,
159 ipc_port_request_index_t
*indexp
)
161 ipc_port_request_t ipr
, table
;
162 ipc_port_request_index_t index
;
164 assert(ip_active(port
));
165 assert(name
!= MACH_PORT_NULL
);
166 assert(soright
!= IP_NULL
);
168 table
= port
->ip_dnrequests
;
169 if (table
== IPR_NULL
)
170 return KERN_NO_SPACE
;
172 index
= table
->ipr_next
;
174 return KERN_NO_SPACE
;
177 assert(ipr
->ipr_name
== MACH_PORT_NULL
);
179 table
->ipr_next
= ipr
->ipr_next
;
180 ipr
->ipr_name
= name
;
181 ipr
->ipr_soright
= soright
;
188 * Routine: ipc_port_dngrow
190 * Grow a port's table of dead-name requests.
192 * The port must be locked and active.
193 * Nothing else locked; will allocate memory.
194 * Upon return the port is unlocked.
196 * KERN_SUCCESS Grew the table.
197 * KERN_SUCCESS Somebody else grew the table.
198 * KERN_SUCCESS The port died.
199 * KERN_RESOURCE_SHORTAGE Couldn't allocate new table.
200 * KERN_NO_SPACE Couldn't grow to desired size
206 ipc_table_elems_t target_size
)
208 ipc_table_size_t its
;
209 ipc_port_request_t otable
, ntable
;
211 assert(ip_active(port
));
213 otable
= port
->ip_dnrequests
;
214 if (otable
== IPR_NULL
)
215 its
= &ipc_table_dnrequests
[0];
217 its
= otable
->ipr_size
+ 1;
219 if (target_size
!= ITS_SIZE_NONE
) {
220 if ((otable
!= IPR_NULL
) &&
221 (target_size
<= otable
->ipr_size
->its_size
)) {
225 while ((its
->its_size
) && (its
->its_size
< target_size
)) {
228 if (its
->its_size
== 0) {
230 return KERN_NO_SPACE
;
237 if ((its
->its_size
== 0) ||
238 ((ntable
= it_dnrequests_alloc(its
)) == IPR_NULL
)) {
239 ipc_port_release(port
);
240 return KERN_RESOURCE_SHORTAGE
;
247 * Check that port is still active and that nobody else
248 * has slipped in and grown the table on us. Note that
249 * just checking port->ip_dnrequests == otable isn't
250 * sufficient; must check ipr_size.
253 if (ip_active(port
) &&
254 (port
->ip_dnrequests
== otable
) &&
255 ((otable
== IPR_NULL
) || (otable
->ipr_size
+1 == its
))) {
256 ipc_table_size_t oits
;
257 ipc_table_elems_t osize
, nsize
;
258 ipc_port_request_index_t free
, i
;
260 /* copy old table to new table */
262 if (otable
!= IPR_NULL
) {
263 oits
= otable
->ipr_size
;
264 osize
= oits
->its_size
;
265 free
= otable
->ipr_next
;
267 (void) memcpy((void *)(ntable
+ 1),
268 (const void *)(otable
+ 1),
269 (osize
- 1) * sizeof(struct ipc_port_request
));
276 nsize
= its
->its_size
;
277 assert(nsize
> osize
);
279 /* add new elements to the new table's free list */
281 for (i
= osize
; i
< nsize
; i
++) {
282 ipc_port_request_t ipr
= &ntable
[i
];
284 ipr
->ipr_name
= MACH_PORT_NULL
;
285 ipr
->ipr_next
= free
;
289 ntable
->ipr_next
= free
;
290 ntable
->ipr_size
= its
;
291 port
->ip_dnrequests
= ntable
;
294 if (otable
!= IPR_NULL
) {
295 it_dnrequests_free(oits
, otable
);
298 ip_check_unlock(port
);
299 it_dnrequests_free(its
, ntable
);
306 * Routine: ipc_port_dncancel
308 * Cancel a dead-name request and return the send-once right.
310 * The port must locked and active.
316 __assert_only mach_port_name_t name
,
317 ipc_port_request_index_t index
)
319 ipc_port_request_t ipr
, table
;
320 ipc_port_t dnrequest
;
322 assert(ip_active(port
));
323 assert(name
!= MACH_PORT_NULL
);
326 table
= port
->ip_dnrequests
;
327 assert(table
!= IPR_NULL
);
330 dnrequest
= ipr
->ipr_soright
;
331 assert(ipr
->ipr_name
== name
);
333 /* return ipr to the free list inside the table */
335 ipr
->ipr_name
= MACH_PORT_NULL
;
336 ipr
->ipr_next
= table
->ipr_next
;
337 table
->ipr_next
= index
;
343 * Routine: ipc_port_pdrequest
345 * Make a port-deleted request, returning the
346 * previously registered send-once right.
347 * Just cancels the previous request if notify is IP_NULL.
349 * The port is locked and active. It is unlocked.
350 * Consumes a ref for notify (if non-null), and
351 * returns previous with a ref (if non-null).
358 ipc_port_t
*previousp
)
362 assert(ip_active(port
));
364 previous
= port
->ip_pdrequest
;
365 port
->ip_pdrequest
= notify
;
368 *previousp
= previous
;
372 * Routine: ipc_port_nsrequest
374 * Make a no-senders request, returning the
375 * previously registered send-once right.
376 * Just cancels the previous request if notify is IP_NULL.
378 * The port is locked and active. It is unlocked.
379 * Consumes a ref for notify (if non-null), and
380 * returns previous with a ref (if non-null).
386 mach_port_mscount_t sync
,
388 ipc_port_t
*previousp
)
391 mach_port_mscount_t mscount
;
393 assert(ip_active(port
));
395 previous
= port
->ip_nsrequest
;
396 mscount
= port
->ip_mscount
;
398 if ((port
->ip_srights
== 0) && (sync
<= mscount
) &&
399 (notify
!= IP_NULL
)) {
400 port
->ip_nsrequest
= IP_NULL
;
402 ipc_notify_no_senders(notify
, mscount
);
404 port
->ip_nsrequest
= notify
;
408 *previousp
= previous
;
413 * Routine: ipc_port_clear_receiver
415 * Prepares a receive right for transmission/destruction.
417 * The port is locked and active.
421 ipc_port_clear_receiver(
426 assert(ip_active(port
));
429 * pull ourselves from any sets.
431 if (port
->ip_pset_count
!= 0) {
432 ipc_pset_remove_from_all(port
);
433 assert(port
->ip_pset_count
== 0);
437 * Send anyone waiting on the port's queue directly away.
438 * Also clear the mscount and seqno.
441 imq_lock(&port
->ip_messages
);
442 ipc_mqueue_changed(&port
->ip_messages
);
443 ipc_port_set_mscount(port
, 0);
444 port
->ip_messages
.imq_seqno
= 0;
445 imq_unlock(&port
->ip_messages
);
450 * Routine: ipc_port_init
452 * Initializes a newly-allocated port.
453 * Doesn't touch the ip_object fields.
460 mach_port_name_t name
)
462 /* port->ip_kobject doesn't have to be initialized */
464 port
->ip_receiver
= space
;
465 port
->ip_receiver_name
= name
;
467 port
->ip_mscount
= 0;
468 port
->ip_srights
= 0;
469 port
->ip_sorights
= 0;
471 port
->ip_nsrequest
= IP_NULL
;
472 port
->ip_pdrequest
= IP_NULL
;
473 port
->ip_dnrequests
= IPR_NULL
;
475 port
->ip_pset_count
= 0;
476 port
->ip_premsg
= IKM_NULL
;
477 port
->ip_context
= 0;
480 ipc_port_init_debug(port
);
481 #endif /* MACH_ASSERT */
483 ipc_mqueue_init(&port
->ip_messages
, FALSE
/* set */);
487 * Routine: ipc_port_alloc
491 * Nothing locked. If successful, the port is returned
492 * locked. (The caller doesn't have a reference.)
494 * KERN_SUCCESS The port is allocated.
495 * KERN_INVALID_TASK The space is dead.
496 * KERN_NO_SPACE No room for an entry in the space.
497 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
503 mach_port_name_t
*namep
,
507 mach_port_name_t name
;
510 kr
= ipc_object_alloc(space
, IOT_PORT
,
511 MACH_PORT_TYPE_RECEIVE
, 0,
512 &name
, (ipc_object_t
*) &port
);
513 if (kr
!= KERN_SUCCESS
)
518 ipc_port_init(port
, space
, name
);
521 task_t issuer
= current_task();
522 tasklabel_lock2 (issuer
, space
->is_task
);
523 mac_port_label_associate(&issuer
->maclabel
, &space
->is_task
->maclabel
,
525 tasklabel_unlock2 (issuer
, space
->is_task
);
535 * Routine: ipc_port_alloc_name
537 * Allocate a port, with a specific name.
539 * Nothing locked. If successful, the port is returned
540 * locked. (The caller doesn't have a reference.)
542 * KERN_SUCCESS The port is allocated.
543 * KERN_INVALID_TASK The space is dead.
544 * KERN_NAME_EXISTS The name already denotes a right.
545 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
551 mach_port_name_t name
,
557 kr
= ipc_object_alloc_name(space
, IOT_PORT
,
558 MACH_PORT_TYPE_RECEIVE
, 0,
559 name
, (ipc_object_t
*) &port
);
560 if (kr
!= KERN_SUCCESS
)
565 ipc_port_init(port
, space
, name
);
568 task_t issuer
= current_task();
569 tasklabel_lock2 (issuer
, space
->is_task
);
570 mac_port_label_associate(&issuer
->maclabel
, &space
->is_task
->maclabel
,
572 tasklabel_unlock2 (issuer
, space
->is_task
);
581 * Generate dead name notifications. Called from ipc_port_destroy.
582 * Port is unlocked but still has reference(s);
583 * dnrequests was taken from port while the port
584 * was locked but the port now has port->ip_dnrequests set to IPR_NULL.
588 __unused ipc_port_t port
,
589 ipc_port_request_t dnrequests
)
591 ipc_table_size_t its
= dnrequests
->ipr_size
;
592 ipc_table_elems_t size
= its
->its_size
;
593 ipc_port_request_index_t index
;
595 for (index
= 1; index
< size
; index
++) {
596 ipc_port_request_t ipr
= &dnrequests
[index
];
597 mach_port_name_t name
= ipr
->ipr_name
;
600 if (name
== MACH_PORT_NULL
)
603 soright
= ipr
->ipr_soright
;
604 assert(soright
!= IP_NULL
);
606 ipc_notify_dead_name(soright
, name
);
609 it_dnrequests_free(its
, dnrequests
);
613 * Routine: ipc_port_destroy
615 * Destroys a port. Cleans up queued messages.
617 * If the port has a backup, it doesn't get destroyed,
618 * but is sent in a port-destroyed notification to the backup.
620 * The port is locked and alive; nothing else locked.
621 * The caller has a reference, which is consumed.
622 * Afterwards, the port is unlocked and dead.
629 ipc_port_t pdrequest
, nsrequest
;
632 ipc_port_request_t dnrequests
;
634 assert(ip_active(port
));
635 /* port->ip_receiver_name is garbage */
636 /* port->ip_receiver/port->ip_destination is garbage */
637 assert(port
->ip_pset_count
== 0);
638 assert(port
->ip_mscount
== 0);
640 /* first check for a backup port */
642 pdrequest
= port
->ip_pdrequest
;
643 if (pdrequest
!= IP_NULL
) {
644 /* we assume the ref for pdrequest */
645 port
->ip_pdrequest
= IP_NULL
;
647 /* make port be in limbo */
648 port
->ip_receiver_name
= MACH_PORT_NULL
;
649 port
->ip_destination
= IP_NULL
;
652 /* consumes our refs for port and pdrequest */
653 ipc_notify_port_destroyed(pdrequest
, port
);
657 /* once port is dead, we don't need to keep it locked */
659 port
->ip_object
.io_bits
&= ~IO_BITS_ACTIVE
;
660 port
->ip_timestamp
= ipc_port_timestamp();
663 dnrequests
= port
->ip_dnrequests
;
664 port
->ip_dnrequests
= IPR_NULL
;
667 * If the port has a preallocated message buffer and that buffer
668 * is not inuse, free it. If it has an inuse one, then the kmsg
669 * free will detect that we freed the association and it can free it
670 * like a normal buffer.
672 if (IP_PREALLOC(port
)) {
673 kmsg
= port
->ip_premsg
;
674 assert(kmsg
!= IKM_NULL
);
675 IP_CLEAR_PREALLOC(port
, kmsg
);
676 if (!ikm_prealloc_inuse(kmsg
))
681 /* throw away no-senders request */
683 nsrequest
= port
->ip_nsrequest
;
684 if (nsrequest
!= IP_NULL
)
685 ipc_notify_send_once(nsrequest
); /* consumes ref */
687 /* destroy any queued messages */
688 mqueue
= &port
->ip_messages
;
689 ipc_mqueue_destroy(mqueue
);
691 /* generate dead-name notifications */
692 if (dnrequests
!= IPR_NULL
) {
693 ipc_port_dnnotify(port
, dnrequests
);
696 ipc_kobject_destroy(port
);
698 ipc_port_release(port
); /* consume caller's ref */
702 * Routine: ipc_port_check_circularity
704 * Check if queueing "port" in a message for "dest"
705 * would create a circular group of ports and messages.
707 * If no circularity (FALSE returned), then "port"
708 * is changed from "in limbo" to "in transit".
710 * That is, we want to set port->ip_destination == dest,
711 * but guaranteeing that this doesn't create a circle
712 * port->ip_destination->ip_destination->... == port
714 * No ports locked. References held for "port" and "dest".
718 ipc_port_check_circularity(
724 assert(port
!= IP_NULL
);
725 assert(dest
!= IP_NULL
);
732 * First try a quick check that can run in parallel.
733 * No circularity if dest is not in transit.
737 if (ip_lock_try(dest
)) {
738 if (!ip_active(dest
) ||
739 (dest
->ip_receiver_name
!= MACH_PORT_NULL
) ||
740 (dest
->ip_destination
== IP_NULL
))
743 /* dest is in transit; further checking necessary */
749 ipc_port_multiple_lock(); /* massive serialization */
752 * Search for the end of the chain (a port not in transit),
753 * acquiring locks along the way.
759 if (!ip_active(base
) ||
760 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
761 (base
->ip_destination
== IP_NULL
))
764 base
= base
->ip_destination
;
767 /* all ports in chain from dest to base, inclusive, are locked */
770 /* circularity detected! */
772 ipc_port_multiple_unlock();
774 /* port (== base) is in limbo */
776 assert(ip_active(port
));
777 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
778 assert(port
->ip_destination
== IP_NULL
);
780 while (dest
!= IP_NULL
) {
783 /* dest is in transit or in limbo */
785 assert(ip_active(dest
));
786 assert(dest
->ip_receiver_name
== MACH_PORT_NULL
);
788 next
= dest
->ip_destination
;
797 * The guarantee: lock port while the entire chain is locked.
798 * Once port is locked, we can take a reference to dest,
799 * add port to the chain, and unlock everything.
803 ipc_port_multiple_unlock();
807 /* port is in limbo */
809 assert(ip_active(port
));
810 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
811 assert(port
->ip_destination
== IP_NULL
);
814 port
->ip_destination
= dest
;
816 /* now unlock chain */
818 while (port
!= base
) {
821 /* port is in transit */
823 assert(ip_active(port
));
824 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
825 assert(port
->ip_destination
!= IP_NULL
);
827 next
= port
->ip_destination
;
832 /* base is not in transit */
834 assert(!ip_active(base
) ||
835 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
836 (base
->ip_destination
== IP_NULL
));
843 * Routine: ipc_port_lookup_notify
845 * Make a send-once notify port from a receive right.
846 * Returns IP_NULL if name doesn't denote a receive right.
848 * The space must be locked (read or write) and active.
849 * Being the active space, we can rely on thread server_id
850 * context to give us the proper server level sub-order
855 ipc_port_lookup_notify(
857 mach_port_name_t name
)
862 assert(space
->is_active
);
864 entry
= ipc_entry_lookup(space
, name
);
865 if (entry
== IE_NULL
)
867 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
870 port
= (ipc_port_t
) entry
->ie_object
;
871 assert(port
!= IP_NULL
);
874 assert(ip_active(port
));
875 assert(port
->ip_receiver_name
== name
);
876 assert(port
->ip_receiver
== space
);
886 * Routine: ipc_port_make_send_locked
888 * Make a naked send right from a receive right.
891 * port locked and active.
894 ipc_port_make_send_locked(
897 assert(ip_active(port
));
906 * Routine: ipc_port_make_send
908 * Make a naked send right from a receive right.
920 if (ip_active(port
)) {
932 * Routine: ipc_port_copy_send
934 * Make a naked send right from another naked send right.
937 * dead port -> IP_DEAD
938 * live port -> port + ref
940 * Nothing locked except possibly a space.
953 if (ip_active(port
)) {
954 assert(port
->ip_srights
> 0);
967 * Routine: ipc_port_copyout_send
969 * Copyout a naked send right (possibly null/dead),
970 * or if that fails, destroy the right.
976 ipc_port_copyout_send(
980 mach_port_name_t name
;
982 if (IP_VALID(sright
)) {
985 kr
= ipc_object_copyout(space
, (ipc_object_t
) sright
,
986 MACH_MSG_TYPE_PORT_SEND
, TRUE
, &name
);
987 if (kr
!= KERN_SUCCESS
) {
988 ipc_port_release_send(sright
);
990 if (kr
== KERN_INVALID_CAPABILITY
)
991 name
= MACH_PORT_DEAD
;
993 name
= MACH_PORT_NULL
;
996 name
= CAST_MACH_PORT_TO_NAME(sright
);
1002 * Routine: ipc_port_release_send
1004 * Release a (valid) naked send right.
1005 * Consumes a ref for the port.
1011 ipc_port_release_send(
1014 ipc_port_t nsrequest
= IP_NULL
;
1015 mach_port_mscount_t mscount
;
1017 assert(IP_VALID(port
));
1022 if (!ip_active(port
)) {
1023 ip_check_unlock(port
);
1027 assert(port
->ip_srights
> 0);
1029 if (--port
->ip_srights
== 0 &&
1030 port
->ip_nsrequest
!= IP_NULL
) {
1031 nsrequest
= port
->ip_nsrequest
;
1032 port
->ip_nsrequest
= IP_NULL
;
1033 mscount
= port
->ip_mscount
;
1035 ipc_notify_no_senders(nsrequest
, mscount
);
1041 * Routine: ipc_port_make_sonce
1043 * Make a naked send-once right from a receive right.
1045 * The port is not locked but it is active.
1049 ipc_port_make_sonce(
1052 assert(IP_VALID(port
));
1055 assert(ip_active(port
));
1056 port
->ip_sorights
++;
1064 * Routine: ipc_port_release_sonce
1066 * Release a naked send-once right.
1067 * Consumes a ref for the port.
1069 * In normal situations, this is never used.
1070 * Send-once rights are only consumed when
1071 * a message (possibly a send-once notification)
1074 * Nothing locked except possibly a space.
1078 ipc_port_release_sonce(
1081 assert(IP_VALID(port
));
1085 assert(port
->ip_sorights
> 0);
1087 port
->ip_sorights
--;
1091 if (!ip_active(port
)) {
1092 ip_check_unlock(port
);
1100 * Routine: ipc_port_release_receive
1102 * Release a naked (in limbo or in transit) receive right.
1103 * Consumes a ref for the port; destroys the port.
1109 ipc_port_release_receive(
1114 assert(IP_VALID(port
));
1117 assert(ip_active(port
));
1118 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1119 dest
= port
->ip_destination
;
1121 ipc_port_destroy(port
); /* consumes ref, unlocks */
1123 if (dest
!= IP_NULL
)
1124 ipc_port_release(dest
);
1128 * Routine: ipc_port_alloc_special
1130 * Allocate a port in a special space.
1131 * The new port is returned with one ref.
1132 * If unsuccessful, IP_NULL is returned.
1138 ipc_port_alloc_special(
1143 port
= (ipc_port_t
) io_alloc(IOT_PORT
);
1144 if (port
== IP_NULL
)
1147 bzero((char *)port
, sizeof(*port
));
1148 io_lock_init(&port
->ip_object
);
1149 port
->ip_references
= 1;
1150 port
->ip_object
.io_bits
= io_makebits(TRUE
, IOT_PORT
, 0);
1152 ipc_port_init(port
, space
, 1);
1154 #if CONFIG_MACF_MACH
1155 /* Currently, ipc_port_alloc_special is used for two things:
1156 * - Reply ports for messages from the kernel
1157 * - Ports for communication with the kernel (e.g. task ports)
1158 * Since both of these would typically be labelled as kernel objects,
1159 * we will use a new entry point for this purpose, as current_task()
1160 * is often wrong (i.e. not kernel_task) or null.
1162 mac_port_label_init(&port
->ip_label
);
1163 mac_port_label_associate_kernel(&port
->ip_label
, space
== ipc_space_reply
);
1170 * Routine: ipc_port_dealloc_special
1172 * Deallocate a port in a special space.
1173 * Consumes one ref for the port.
1179 ipc_port_dealloc_special(
1181 __assert_only ipc_space_t space
)
1184 assert(ip_active(port
));
1185 // assert(port->ip_receiver_name != MACH_PORT_NULL);
1186 assert(port
->ip_receiver
== space
);
1189 * We clear ip_receiver_name and ip_receiver to simplify
1190 * the ipc_space_kernel check in ipc_mqueue_send.
1193 port
->ip_receiver_name
= MACH_PORT_NULL
;
1194 port
->ip_receiver
= IS_NULL
;
1196 /* relevant part of ipc_port_clear_receiver */
1197 ipc_port_set_mscount(port
, 0);
1198 port
->ip_messages
.imq_seqno
= 0;
1200 ipc_port_destroy(port
);
1205 #include <kern/machine.h>
1208 * Keep a list of all allocated ports.
1209 * Allocation is intercepted via ipc_port_init;
1210 * deallocation is intercepted via io_free.
1212 queue_head_t port_alloc_queue
;
1213 decl_lck_mtx_data(,port_alloc_queue_lock
)
1214 lck_mtx_ext_t port_alloc_queue_lock_ext
;
1216 unsigned long port_count
= 0;
1217 unsigned long port_count_warning
= 20000;
1218 unsigned long port_timestamp
= 0;
1220 void db_port_stack_trace(
1225 unsigned int verbose
,
1226 unsigned int display
,
1227 unsigned int ref_search
,
1228 unsigned int ref_target
);
1231 * Initialize global state needed for run-time
1235 ipc_port_debug_init(void)
1237 queue_init(&port_alloc_queue
);
1238 lck_mtx_init_ext(&port_alloc_queue_lock
, &port_alloc_queue_lock_ext
, &ipc_lck_grp
, &ipc_lck_attr
);
1240 if (!PE_parse_boot_argn("ipc_portbt", &ipc_portbt
, sizeof (ipc_portbt
)))
1245 extern int proc_pid(struct proc
*);
1246 #endif /* MACH_BSD */
1249 * Initialize all of the debugging state in a port.
1250 * Insert the port into a global list of all allocated ports.
1253 ipc_port_init_debug(
1258 port
->ip_thread
= current_thread();
1259 port
->ip_timetrack
= port_timestamp
++;
1260 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
)
1261 port
->ip_callstack
[i
] = 0;
1262 for (i
= 0; i
< IP_NSPARES
; ++i
)
1263 port
->ip_spares
[i
] = 0;
1266 task_t task
= current_task();
1267 if (task
!= TASK_NULL
) {
1268 struct proc
* proc
= (struct proc
*) get_bsdtask_info(task
);
1270 port
->ip_spares
[0] = proc_pid(proc
);
1272 #endif /* MACH_BSD */
1275 * Machine-dependent routine to fill in an
1276 * array with up to IP_CALLSTACK_MAX levels
1277 * of return pc information.
1280 machine_callstack(&port
->ip_callstack
[0], IP_CALLSTACK_MAX
);
1283 lck_mtx_lock(&port_alloc_queue_lock
);
1285 if (port_count_warning
> 0 && port_count
>= port_count_warning
)
1286 assert(port_count
< port_count_warning
);
1287 queue_enter(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1288 lck_mtx_unlock(&port_alloc_queue_lock
);
1294 * Remove a port from the queue of allocated ports.
1295 * This routine should be invoked JUST prior to
1296 * deallocating the actual memory occupied by the port.
1300 ipc_port_track_dealloc(
1301 __unused ipc_port_t port
)
1306 ipc_port_track_dealloc(
1309 lck_mtx_lock(&port_alloc_queue_lock
);
1310 assert(port_count
> 0);
1312 queue_remove(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1313 lck_mtx_unlock(&port_alloc_queue_lock
);
1317 #endif /* MACH_ASSERT */
1322 #include <ddb/db_output.h>
1323 #include <ddb/db_print.h>
1325 #define printf kdbprintf
1328 db_port_queue_print(
1332 * Routine: ipc_port_print
1334 * Pretty-print a port for kdb.
1336 int ipc_port_print_long
= 0; /* set for more detail */
1341 __unused boolean_t have_addr
,
1342 __unused db_expr_t count
,
1350 int i
, needs_db_indent
, items_printed
;
1351 #endif /* MACH_ASSERT */
1353 if (db_option(modif
, 'l') || db_option(modif
, 'v'))
1356 printf("port 0x%x\n", port
);
1360 ipc_object_print(&port
->ip_object
);
1362 if (ipc_port_print_long
) {
1366 if (!ip_active(port
)) {
1367 iprintf("timestamp=0x%x", port
->ip_timestamp
);
1368 } else if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1369 iprintf("destination=0x%x (", port
->ip_destination
);
1370 if (port
->ip_destination
!= MACH_PORT_NULL
&&
1371 (task
= db_task_from_space(port
->ip_destination
->
1372 ip_receiver
, &task_id
)))
1373 printf("task%d at 0x%x", task_id
, task
);
1378 iprintf("receiver=0x%x (", port
->ip_receiver
);
1379 if (port
->ip_receiver
== ipc_space_kernel
)
1381 else if (port
->ip_receiver
== ipc_space_reply
)
1383 else if (port
->ip_receiver
== default_pager_space
)
1384 printf("default_pager");
1385 else if ((task
= db_task_from_space(port
->ip_receiver
, &task_id
)) != (db_addr_t
)0)
1386 printf("task%d at 0x%x", task_id
, task
);
1391 printf(", receiver_name=0x%x\n", port
->ip_receiver_name
);
1393 iprintf("mscount=%d", port
->ip_mscount
);
1394 printf(", srights=%d", port
->ip_srights
);
1395 printf(", sorights=%d\n", port
->ip_sorights
);
1397 iprintf("nsrequest=0x%x", port
->ip_nsrequest
);
1398 printf(", pdrequest=0x%x", port
->ip_pdrequest
);
1399 printf(", dnrequests=0x%x\n", port
->ip_dnrequests
);
1401 iprintf("pset_count=0x%x", port
->ip_pset_count
);
1402 printf(", seqno=%d", port
->ip_messages
.imq_seqno
);
1403 printf(", msgcount=%d", port
->ip_messages
.imq_msgcount
);
1404 printf(", qlimit=%d\n", port
->ip_messages
.imq_qlimit
);
1406 iprintf("kmsgs=0x%x", port
->ip_messages
.imq_messages
.ikmq_base
);
1407 printf(", rcvrs queue=0x%x", port
->ip_messages
.imq_wait_queue
);
1408 printf(", kobj=0x%x\n", port
->ip_kobject
);
1410 iprintf("premsg=0x%x", port
->ip_premsg
);
1413 /* don't bother printing callstack or queue links */
1414 iprintf("ip_thread=0x%x, ip_timetrack=0x%x\n",
1415 port
->ip_thread
, port
->ip_timetrack
);
1417 needs_db_indent
= 1;
1418 for (i
= 0; i
< IP_NSPARES
; ++i
) {
1419 if (port
->ip_spares
[i
] != 0) {
1420 if (needs_db_indent
) {
1422 needs_db_indent
= 0;
1424 printf("%sip_spares[%d] = %d",
1425 items_printed
? ", " : "", i
,
1426 port
->ip_spares
[i
]);
1427 if (++items_printed
>= 4) {
1428 needs_db_indent
= 1;
1434 #endif /* MACH_ASSERT */
1437 iprintf("kmsg queue contents:\n");
1439 nmsgs
= db_port_queue_print(port
);
1441 iprintf("...total kmsgs: %d\n", nmsgs
);
1450 mach_port_name_t name
)
1455 if (task
== TASK_NULL
) {
1456 db_printf("port_name_to_data: task is null\n");
1459 if ((space
= task
->itk_space
) == 0) {
1460 db_printf("port_name_to_data: task->itk_space is null\n");
1463 if (!space
->is_active
) {
1464 db_printf("port_name_to_data: task->itk_space not active\n");
1467 if ((entry
= ipc_entry_lookup(space
, name
)) == 0) {
1468 db_printf("port_name_to_data: lookup yields zero\n");
1471 return ((ipc_port_t
)entry
->ie_object
);
1476 print_type_ports(type
, dead
)
1484 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1486 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1488 if (ip_kotype(port
) == type
&&
1489 (!dead
|| !ip_active(port
))) {
1491 printf("0x%x\t", port
);
1493 printf("0x%x\n", port
);
1503 int total_port_count
;
1504 int space_null_count
;
1505 int space_kernel_count
;
1506 int space_reply_count
;
1507 int space_pager_count
;
1508 int space_other_count
;
1513 } port_types
[IKOT_MAX_TYPE
];
1515 total_port_count
= 0;
1517 bzero((char *)&port_types
[0], sizeof(port_types
));
1518 space_null_count
= 0;
1519 space_kernel_count
= 0;
1520 space_reply_count
= 0;
1521 space_pager_count
= 0;
1522 space_other_count
= 0;
1524 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1526 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1529 if (ip_kotype(port
) >= IKOT_MAX_TYPE
) {
1530 port_types
[IKOT_UNKNOWN
].total_count
++;
1531 if (!io_active(&port
->ip_object
))
1532 port_types
[IKOT_UNKNOWN
].dead_count
++;
1534 port_types
[ip_kotype(port
)].total_count
++;
1535 if (!io_active(&port
->ip_object
))
1536 port_types
[ip_kotype(port
)].dead_count
++;
1539 if (!port
->ip_receiver
)
1541 else if (port
->ip_receiver
== ipc_space_kernel
)
1542 space_kernel_count
++;
1543 else if (port
->ip_receiver
== ipc_space_reply
)
1544 space_reply_count
++;
1545 else if (port
->ip_receiver
== default_pager_space
)
1546 space_pager_count
++;
1548 space_other_count
++;
1550 printf("\n%7d total ports\n\n", total_port_count
);
1552 #define PRINT_ONE_PORT_TYPE(name) \
1553 printf("%7d %s", port_types[IKOT_##name].total_count, # name); \
1554 if (port_types[IKOT_##name].dead_count) \
1555 printf(" (%d dead ports)", port_types[IKOT_##name].dead_count);\
1558 PRINT_ONE_PORT_TYPE(NONE
);
1559 PRINT_ONE_PORT_TYPE(THREAD
);
1560 PRINT_ONE_PORT_TYPE(TASK
);
1561 PRINT_ONE_PORT_TYPE(HOST
);
1562 PRINT_ONE_PORT_TYPE(HOST_PRIV
);
1563 PRINT_ONE_PORT_TYPE(PROCESSOR
);
1564 PRINT_ONE_PORT_TYPE(PSET
);
1565 PRINT_ONE_PORT_TYPE(PSET_NAME
);
1566 PRINT_ONE_PORT_TYPE(TIMER
);
1567 PRINT_ONE_PORT_TYPE(PAGING_REQUEST
);
1568 PRINT_ONE_PORT_TYPE(MIG
);
1569 PRINT_ONE_PORT_TYPE(MEMORY_OBJECT
);
1570 PRINT_ONE_PORT_TYPE(XMM_PAGER
);
1571 PRINT_ONE_PORT_TYPE(XMM_KERNEL
);
1572 PRINT_ONE_PORT_TYPE(XMM_REPLY
);
1573 PRINT_ONE_PORT_TYPE(UND_REPLY
);
1574 PRINT_ONE_PORT_TYPE(HOST_NOTIFY
);
1575 PRINT_ONE_PORT_TYPE(HOST_SECURITY
);
1576 PRINT_ONE_PORT_TYPE(LEDGER
);
1577 PRINT_ONE_PORT_TYPE(MASTER_DEVICE
);
1578 PRINT_ONE_PORT_TYPE(TASK_NAME
);
1579 PRINT_ONE_PORT_TYPE(SUBSYSTEM
);
1580 PRINT_ONE_PORT_TYPE(IO_DONE_QUEUE
);
1581 PRINT_ONE_PORT_TYPE(SEMAPHORE
);
1582 PRINT_ONE_PORT_TYPE(LOCK_SET
);
1583 PRINT_ONE_PORT_TYPE(CLOCK
);
1584 PRINT_ONE_PORT_TYPE(CLOCK_CTRL
);
1585 PRINT_ONE_PORT_TYPE(IOKIT_SPARE
);
1586 PRINT_ONE_PORT_TYPE(NAMED_ENTRY
);
1587 PRINT_ONE_PORT_TYPE(IOKIT_CONNECT
);
1588 PRINT_ONE_PORT_TYPE(IOKIT_OBJECT
);
1589 PRINT_ONE_PORT_TYPE(UPL
);
1590 PRINT_ONE_PORT_TYPE(MEM_OBJ_CONTROL
);
1592 PRINT_ONE_PORT_TYPE(UNKNOWN
);
1593 printf("\nipc_space:\n\n");
1594 printf("NULL KERNEL REPLY PAGER OTHER\n");
1595 printf("%d %d %d %d %d\n",
1604 #endif /* ZONE_DEBUG */
1608 * Print out all the kmsgs in a queue. Aggregate kmsgs with
1609 * identical message ids into a single entry. Count up the
1610 * amount of inline and out-of-line data consumed by each
1615 #define KMSG_MATCH_FIELD(kmsg) (kmsg->ikm_header->msgh_id)
1616 #define DKQP_LONG(kmsg) FALSE
1617 const char *dkqp_long_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1618 const char *dkqp_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1621 db_kmsg_queue_print(
1624 db_kmsg_queue_print(
1627 ipc_kmsg_t ikmsg
, first_kmsg
;
1628 register int icount
;
1629 mach_msg_id_t cur_id
;
1630 unsigned int inline_total
, ool_total
;
1633 iprintf("Count msgh_id kmsg addr inline bytes ool bytes\n");
1634 inline_total
= ool_total
= (vm_size_t
) 0;
1635 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1636 for (icount
= 0, nmsgs
= 0, first_kmsg
= ikmsg
= kmsg
;
1637 kmsg
!= IKM_NULL
&& (kmsg
!= first_kmsg
|| nmsgs
== 0);
1638 kmsg
= kmsg
->ikm_next
) {
1640 if (!(KMSG_MATCH_FIELD(kmsg
) == cur_id
)) {
1641 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
:dkqp_format
,
1642 icount
, cur_id
, ikmsg
, inline_total
,ool_total
);
1643 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1646 inline_total
= ool_total
= 0;
1650 if (DKQP_LONG(kmsg
))
1651 inline_total
+= kmsg
->ikm_size
;
1653 inline_total
+= kmsg
->ikm_header
->msgh_size
;
1655 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
: dkqp_format
,
1656 icount
, cur_id
, ikmsg
, inline_total
, ool_total
);
1662 * Process all of the messages on a port - prints out the
1663 * number of occurences of each message type, and the first
1664 * kmsg with a particular msgh_id.
1667 db_port_queue_print(
1672 if (ipc_kmsg_queue_empty(&port
->ip_messages
.imq_messages
))
1674 kmsg
= ipc_kmsg_queue_first(&port
->ip_messages
.imq_messages
);
1675 return db_kmsg_queue_print(kmsg
);
1680 #include <ddb/db_sym.h>
1681 #include <ddb/db_access.h>
1683 #define FUNC_NULL ((void (*)) 0)
1684 #define MAX_REFS 5 /* bins for tracking ref counts */
1687 * Translate port's cache of call stack pointers
1688 * into symbolic names.
1691 db_port_stack_trace(
1696 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1697 iprintf("[%d] 0x%x\t", i
, port
->ip_callstack
[i
]);
1698 if (port
->ip_callstack
[i
] != 0 &&
1699 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1700 db_printsym(port
->ip_callstack
[i
], DB_STGY_PROC
);
1706 typedef struct port_item
{
1708 unsigned long count
;
1712 #define ITEM_MAX 400
1713 typedef struct port_track
{
1716 unsigned long warning
;
1717 port_item items
[ITEM_MAX
];
1720 port_track port_callers
; /* match against calling addresses */
1721 port_track port_threads
; /* match against allocating threads */
1722 port_track port_spaces
; /* match against ipc spaces */
1724 void port_track_init(
1729 unsigned long item
);
1730 void port_track_sort(
1731 port_track
*trackp
);
1732 void port_track_print(
1734 void (*func
)(port_item
*));
1735 void port_callers_print(
1745 trackp
->max
= trackp
->warning
= 0;
1746 trackp
->name
= name
;
1747 for (i
= trackp
->items
; i
< trackp
->items
+ ITEM_MAX
; ++i
)
1748 i
->item
= i
->count
= 0;
1757 port_item
*limit
, *i
;
1759 limit
= trackp
->items
+ trackp
->max
;
1760 for (i
= trackp
->items
; i
< limit
; ++i
)
1761 if (i
->item
== item
) {
1765 if (trackp
->max
>= ITEM_MAX
) {
1766 if (trackp
->warning
++ == 0)
1767 iprintf("%s: no room\n", trackp
->name
);
1777 * Simple (and slow) bubble sort.
1783 port_item
*limit
, *p
;
1787 limit
= trackp
->items
+ trackp
->max
- 1;
1790 for (p
= trackp
->items
; p
< limit
- 1; ++p
) {
1791 if (p
->count
< (p
+1)->count
) {
1798 } while (unsorted
== TRUE
);
1805 void (*func
)(port_item
*))
1807 port_item
*limit
, *p
;
1809 limit
= trackp
->items
+ trackp
->max
;
1810 iprintf("%s:\n", trackp
->name
);
1811 for (p
= trackp
->items
; p
< limit
; ++p
) {
1812 if (func
!= FUNC_NULL
)
1815 iprintf("0x%x\t%8d\n", p
->item
, p
->count
);
1824 iprintf("0x%x\t%8d\t", p
->item
, p
->count
);
1825 db_printsym(p
->item
, DB_STGY_PROC
);
1831 * Show all ports with a given reference count.
1837 db_port_walk(1, 1, 1, refs
);
1842 * Examine all currently allocated ports.
1844 * verbose display suspicious ports
1845 * display print out each port encountered
1846 * ref_search restrict examination to ports with
1847 * a specified reference count
1848 * ref_target reference count for ref_search
1852 unsigned int verbose
,
1853 unsigned int display
,
1854 unsigned int ref_search
,
1855 unsigned int ref_target
)
1858 unsigned int ref_overflow
, refs
, i
, ref_inactive_overflow
;
1859 unsigned int no_receiver
, no_match
;
1860 unsigned int ref_counts
[MAX_REFS
];
1861 unsigned int inactive
[MAX_REFS
];
1862 unsigned int ipc_ports
= 0;
1864 iprintf("Allocated port count is %d\n", port_count
);
1865 no_receiver
= no_match
= ref_overflow
= 0;
1866 ref_inactive_overflow
= 0;
1867 for (i
= 0; i
< MAX_REFS
; ++i
) {
1871 port_track_init(&port_callers
, "port callers");
1872 port_track_init(&port_threads
, "port threads");
1873 port_track_init(&port_spaces
, "port spaces");
1875 iprintf("Walking ports of ref_count=%d.\n", ref_target
);
1877 iprintf("Walking all ports.\n");
1879 queue_iterate(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
) {
1880 const char *port_type
;
1882 port_type
= " IPC port";
1883 if (ip_active(port
))
1886 refs
= port
->ip_references
;
1887 if (ref_search
&& refs
!= ref_target
)
1890 if (refs
>= MAX_REFS
) {
1891 if (ip_active(port
))
1894 ++ref_inactive_overflow
;
1896 if (refs
== 0 && verbose
)
1897 iprintf("%s 0x%x has ref count of zero!\n",
1899 if (ip_active(port
))
1904 port_item_add(&port_threads
, (unsigned long) port
->ip_thread
);
1905 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1906 if (port
->ip_callstack
[i
] != 0 &&
1907 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1908 port_item_add(&port_callers
,
1909 port
->ip_callstack
[i
]);
1911 if (!ip_active(port
)) {
1913 iprintf("%s 0x%x, inactive, refcnt %d\n",
1914 port_type
, port
, refs
);
1918 if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1919 iprintf("%s 0x%x, no receiver, refcnt %d\n",
1924 if (port
->ip_receiver
== ipc_space_kernel
||
1925 port
->ip_receiver
== ipc_space_reply
||
1926 ipc_entry_lookup(port
->ip_receiver
,
1927 port
->ip_receiver_name
)
1929 port_item_add(&port_spaces
,
1930 (unsigned long)port
->ip_receiver
);
1932 iprintf( "%s 0x%x time 0x%x ref_cnt %d\n",
1934 port
->ip_timetrack
, refs
);
1938 iprintf("%s 0x%x, rcvr 0x%x, name 0x%x, ref %d, no match\n",
1939 port_type
, port
, port
->ip_receiver
,
1940 port
->ip_receiver_name
, refs
);
1943 iprintf("Active port type summary:\n");
1944 iprintf("\tlocal IPC %6d\n", ipc_ports
);
1945 iprintf("summary:\tcallers %d threads %d spaces %d\n",
1946 port_callers
.max
, port_threads
.max
, port_spaces
.max
);
1948 iprintf("\tref_counts:\n");
1949 for (i
= 0; i
< MAX_REFS
; ++i
)
1950 iprintf("\t ref_counts[%d] = %d\n", i
, ref_counts
[i
]);
1952 iprintf("\t%d ports w/o receivers, %d w/o matches\n",
1953 no_receiver
, no_match
);
1955 iprintf("\tinactives:");
1956 if ( ref_inactive_overflow
|| inactive
[0] || inactive
[1] ||
1957 inactive
[2] || inactive
[3] || inactive
[4] )
1958 printf(" [0]=%d [1]=%d [2]=%d [3]=%d [4]=%d [5+]=%d\n",
1959 inactive
[0], inactive
[1], inactive
[2],
1960 inactive
[3], inactive
[4], ref_inactive_overflow
);
1962 printf(" No inactive ports.\n");
1964 port_track_sort(&port_spaces
);
1965 port_track_print(&port_spaces
, FUNC_NULL
);
1966 port_track_sort(&port_threads
);
1967 port_track_print(&port_threads
, FUNC_NULL
);
1968 port_track_sort(&port_callers
);
1969 port_track_print(&port_callers
, port_callers_print
);
1974 #endif /* MACH_ASSERT */
1976 #endif /* MACH_KDB */