2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
31 * @OSF_FREE_COPYRIGHT@
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
36 * All Rights Reserved.
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 * Carnegie Mellon requests users of this software to return to
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
61 * File: ipc/ipc_port.c
65 * Functions to manipulate IPC ports.
70 #include <zone_debug.h>
71 #include <mach_assert.h>
73 #include <mach/port.h>
74 #include <mach/kern_return.h>
75 #include <kern/lock.h>
76 #include <kern/ipc_kobject.h>
77 #include <kern/thread.h>
78 #include <kern/misc_protos.h>
79 #include <kern/wait_queue.h>
80 #include <ipc/ipc_entry.h>
81 #include <ipc/ipc_space.h>
82 #include <ipc/ipc_object.h>
83 #include <ipc/ipc_port.h>
84 #include <ipc/ipc_pset.h>
85 #include <ipc/ipc_kmsg.h>
86 #include <ipc/ipc_mqueue.h>
87 #include <ipc/ipc_notify.h>
88 #include <ipc/ipc_print.h>
89 #include <ipc/ipc_table.h>
92 #include <machine/db_machdep.h>
93 #include <ddb/db_command.h>
94 #include <ddb/db_expr.h>
99 decl_mutex_data(, ipc_port_multiple_lock_data
)
100 decl_mutex_data(, ipc_port_timestamp_lock_data
)
101 ipc_port_timestamp_t ipc_port_timestamp_data
;
104 void ipc_port_init_debug(
106 #endif /* MACH_ASSERT */
108 #if MACH_KDB && ZONE_DEBUG
110 void print_type_ports(unsigned, unsigned);
111 void print_ports(void);
112 #endif /* MACH_KDB && ZONE_DEBUG */
115 * Routine: ipc_port_timestamp
117 * Retrieve a timestamp value.
121 ipc_port_timestamp(void)
123 ipc_port_timestamp_t timestamp
;
125 ipc_port_timestamp_lock();
126 timestamp
= ipc_port_timestamp_data
++;
127 ipc_port_timestamp_unlock();
133 * Routine: ipc_port_dnrequest
135 * Try to allocate a dead-name request slot.
136 * If successful, returns the request index.
137 * Otherwise returns zero.
139 * The port is locked and active.
141 * KERN_SUCCESS A request index was found.
142 * KERN_NO_SPACE No index allocated.
148 mach_port_name_t name
,
150 ipc_port_request_index_t
*indexp
)
152 ipc_port_request_t ipr
, table
;
153 ipc_port_request_index_t index
;
155 assert(ip_active(port
));
156 assert(name
!= MACH_PORT_NULL
);
157 assert(soright
!= IP_NULL
);
159 table
= port
->ip_dnrequests
;
160 if (table
== IPR_NULL
)
161 return KERN_NO_SPACE
;
163 index
= table
->ipr_next
;
165 return KERN_NO_SPACE
;
168 assert(ipr
->ipr_name
== MACH_PORT_NULL
);
170 table
->ipr_next
= ipr
->ipr_next
;
171 ipr
->ipr_name
= name
;
172 ipr
->ipr_soright
= soright
;
179 * Routine: ipc_port_dngrow
181 * Grow a port's table of dead-name requests.
183 * The port must be locked and active.
184 * Nothing else locked; will allocate memory.
185 * Upon return the port is unlocked.
187 * KERN_SUCCESS Grew the table.
188 * KERN_SUCCESS Somebody else grew the table.
189 * KERN_SUCCESS The port died.
190 * KERN_RESOURCE_SHORTAGE Couldn't allocate new table.
191 * KERN_NO_SPACE Couldn't grow to desired size
197 ipc_table_elems_t target_size
)
199 ipc_table_size_t its
;
200 ipc_port_request_t otable
, ntable
;
202 assert(ip_active(port
));
204 otable
= port
->ip_dnrequests
;
205 if (otable
== IPR_NULL
)
206 its
= &ipc_table_dnrequests
[0];
208 its
= otable
->ipr_size
+ 1;
210 if (target_size
!= ITS_SIZE_NONE
) {
211 if ((otable
!= IPR_NULL
) &&
212 (target_size
<= otable
->ipr_size
->its_size
)) {
216 while ((its
->its_size
) && (its
->its_size
< target_size
)) {
219 if (its
->its_size
== 0) {
221 return KERN_NO_SPACE
;
228 if ((its
->its_size
== 0) ||
229 ((ntable
= it_dnrequests_alloc(its
)) == IPR_NULL
)) {
230 ipc_port_release(port
);
231 return KERN_RESOURCE_SHORTAGE
;
238 * Check that port is still active and that nobody else
239 * has slipped in and grown the table on us. Note that
240 * just checking port->ip_dnrequests == otable isn't
241 * sufficient; must check ipr_size.
244 if (ip_active(port
) &&
245 (port
->ip_dnrequests
== otable
) &&
246 ((otable
== IPR_NULL
) || (otable
->ipr_size
+1 == its
))) {
247 ipc_table_size_t oits
;
248 ipc_table_elems_t osize
, nsize
;
249 ipc_port_request_index_t free
, i
;
251 /* copy old table to new table */
253 if (otable
!= IPR_NULL
) {
254 oits
= otable
->ipr_size
;
255 osize
= oits
->its_size
;
256 free
= otable
->ipr_next
;
258 (void) memcpy((void *)(ntable
+ 1),
259 (const void *)(otable
+ 1),
260 (osize
- 1) * sizeof(struct ipc_port_request
));
267 nsize
= its
->its_size
;
268 assert(nsize
> osize
);
270 /* add new elements to the new table's free list */
272 for (i
= osize
; i
< nsize
; i
++) {
273 ipc_port_request_t ipr
= &ntable
[i
];
275 ipr
->ipr_name
= MACH_PORT_NULL
;
276 ipr
->ipr_next
= free
;
280 ntable
->ipr_next
= free
;
281 ntable
->ipr_size
= its
;
282 port
->ip_dnrequests
= ntable
;
285 if (otable
!= IPR_NULL
) {
286 it_dnrequests_free(oits
, otable
);
289 ip_check_unlock(port
);
290 it_dnrequests_free(its
, ntable
);
297 * Routine: ipc_port_dncancel
299 * Cancel a dead-name request and return the send-once right.
301 * The port must locked and active.
307 __assert_only mach_port_name_t name
,
308 ipc_port_request_index_t index
)
310 ipc_port_request_t ipr
, table
;
311 ipc_port_t dnrequest
;
313 assert(ip_active(port
));
314 assert(name
!= MACH_PORT_NULL
);
317 table
= port
->ip_dnrequests
;
318 assert(table
!= IPR_NULL
);
321 dnrequest
= ipr
->ipr_soright
;
322 assert(ipr
->ipr_name
== name
);
324 /* return ipr to the free list inside the table */
326 ipr
->ipr_name
= MACH_PORT_NULL
;
327 ipr
->ipr_next
= table
->ipr_next
;
328 table
->ipr_next
= index
;
334 * Routine: ipc_port_pdrequest
336 * Make a port-deleted request, returning the
337 * previously registered send-once right.
338 * Just cancels the previous request if notify is IP_NULL.
340 * The port is locked and active. It is unlocked.
341 * Consumes a ref for notify (if non-null), and
342 * returns previous with a ref (if non-null).
349 ipc_port_t
*previousp
)
353 assert(ip_active(port
));
355 previous
= port
->ip_pdrequest
;
356 port
->ip_pdrequest
= notify
;
359 *previousp
= previous
;
363 * Routine: ipc_port_nsrequest
365 * Make a no-senders request, returning the
366 * previously registered send-once right.
367 * Just cancels the previous request if notify is IP_NULL.
369 * The port is locked and active. It is unlocked.
370 * Consumes a ref for notify (if non-null), and
371 * returns previous with a ref (if non-null).
377 mach_port_mscount_t sync
,
379 ipc_port_t
*previousp
)
382 mach_port_mscount_t mscount
;
384 assert(ip_active(port
));
386 previous
= port
->ip_nsrequest
;
387 mscount
= port
->ip_mscount
;
389 if ((port
->ip_srights
== 0) && (sync
<= mscount
) &&
390 (notify
!= IP_NULL
)) {
391 port
->ip_nsrequest
= IP_NULL
;
393 ipc_notify_no_senders(notify
, mscount
);
395 port
->ip_nsrequest
= notify
;
399 *previousp
= previous
;
404 * Routine: ipc_port_clear_receiver
406 * Prepares a receive right for transmission/destruction.
408 * The port is locked and active.
412 ipc_port_clear_receiver(
417 assert(ip_active(port
));
420 * pull ourselves from any sets.
422 if (port
->ip_pset_count
!= 0) {
423 ipc_pset_remove_from_all(port
);
424 assert(port
->ip_pset_count
== 0);
428 * Send anyone waiting on the port's queue directly away.
429 * Also clear the mscount and seqno.
432 imq_lock(&port
->ip_messages
);
433 ipc_mqueue_changed(&port
->ip_messages
);
434 ipc_port_set_mscount(port
, 0);
435 port
->ip_messages
.imq_seqno
= 0;
436 imq_unlock(&port
->ip_messages
);
441 * Routine: ipc_port_init
443 * Initializes a newly-allocated port.
444 * Doesn't touch the ip_object fields.
451 mach_port_name_t name
)
453 /* port->ip_kobject doesn't have to be initialized */
455 port
->ip_receiver
= space
;
456 port
->ip_receiver_name
= name
;
458 port
->ip_mscount
= 0;
459 port
->ip_srights
= 0;
460 port
->ip_sorights
= 0;
462 port
->ip_nsrequest
= IP_NULL
;
463 port
->ip_pdrequest
= IP_NULL
;
464 port
->ip_dnrequests
= IPR_NULL
;
466 port
->ip_pset_count
= 0;
467 port
->ip_premsg
= IKM_NULL
;
470 ipc_port_init_debug(port
);
471 #endif /* MACH_ASSERT */
473 ipc_mqueue_init(&port
->ip_messages
, FALSE
/* set */);
477 * Routine: ipc_port_alloc
481 * Nothing locked. If successful, the port is returned
482 * locked. (The caller doesn't have a reference.)
484 * KERN_SUCCESS The port is allocated.
485 * KERN_INVALID_TASK The space is dead.
486 * KERN_NO_SPACE No room for an entry in the space.
487 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
493 mach_port_name_t
*namep
,
497 mach_port_name_t name
;
500 kr
= ipc_object_alloc(space
, IOT_PORT
,
501 MACH_PORT_TYPE_RECEIVE
, 0,
502 &name
, (ipc_object_t
*) &port
);
503 if (kr
!= KERN_SUCCESS
)
508 ipc_port_init(port
, space
, name
);
517 * Routine: ipc_port_alloc_name
519 * Allocate a port, with a specific name.
521 * Nothing locked. If successful, the port is returned
522 * locked. (The caller doesn't have a reference.)
524 * KERN_SUCCESS The port is allocated.
525 * KERN_INVALID_TASK The space is dead.
526 * KERN_NAME_EXISTS The name already denotes a right.
527 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
533 mach_port_name_t name
,
539 kr
= ipc_object_alloc_name(space
, IOT_PORT
,
540 MACH_PORT_TYPE_RECEIVE
, 0,
541 name
, (ipc_object_t
*) &port
);
542 if (kr
!= KERN_SUCCESS
)
547 ipc_port_init(port
, space
, name
);
555 * Generate dead name notifications. Called from ipc_port_destroy.
556 * Port is unlocked but still has reference(s);
557 * dnrequests was taken from port while the port
558 * was locked but the port now has port->ip_dnrequests set to IPR_NULL.
562 __unused ipc_port_t port
,
563 ipc_port_request_t dnrequests
)
565 ipc_table_size_t its
= dnrequests
->ipr_size
;
566 ipc_table_elems_t size
= its
->its_size
;
567 ipc_port_request_index_t index
;
569 for (index
= 1; index
< size
; index
++) {
570 ipc_port_request_t ipr
= &dnrequests
[index
];
571 mach_port_name_t name
= ipr
->ipr_name
;
574 if (name
== MACH_PORT_NULL
)
577 soright
= ipr
->ipr_soright
;
578 assert(soright
!= IP_NULL
);
580 ipc_notify_dead_name(soright
, name
);
583 it_dnrequests_free(its
, dnrequests
);
587 * Routine: ipc_port_destroy
589 * Destroys a port. Cleans up queued messages.
591 * If the port has a backup, it doesn't get destroyed,
592 * but is sent in a port-destroyed notification to the backup.
594 * The port is locked and alive; nothing else locked.
595 * The caller has a reference, which is consumed.
596 * Afterwards, the port is unlocked and dead.
603 ipc_port_t pdrequest
, nsrequest
;
606 ipc_port_request_t dnrequests
;
608 assert(ip_active(port
));
609 /* port->ip_receiver_name is garbage */
610 /* port->ip_receiver/port->ip_destination is garbage */
611 assert(port
->ip_pset_count
== 0);
612 assert(port
->ip_mscount
== 0);
614 /* first check for a backup port */
616 pdrequest
= port
->ip_pdrequest
;
617 if (pdrequest
!= IP_NULL
) {
618 /* we assume the ref for pdrequest */
619 port
->ip_pdrequest
= IP_NULL
;
621 /* make port be in limbo */
622 port
->ip_receiver_name
= MACH_PORT_NULL
;
623 port
->ip_destination
= IP_NULL
;
626 /* consumes our refs for port and pdrequest */
627 ipc_notify_port_destroyed(pdrequest
, port
);
631 /* once port is dead, we don't need to keep it locked */
633 port
->ip_object
.io_bits
&= ~IO_BITS_ACTIVE
;
634 port
->ip_timestamp
= ipc_port_timestamp();
637 dnrequests
= port
->ip_dnrequests
;
638 port
->ip_dnrequests
= IPR_NULL
;
641 * If the port has a preallocated message buffer and that buffer
642 * is not inuse, free it. If it has an inuse one, then the kmsg
643 * free will detect that we freed the association and it can free it
644 * like a normal buffer.
646 if (IP_PREALLOC(port
)) {
647 kmsg
= port
->ip_premsg
;
648 assert(kmsg
!= IKM_NULL
);
649 IP_CLEAR_PREALLOC(port
, kmsg
);
650 if (!ikm_prealloc_inuse(kmsg
))
655 /* throw away no-senders request */
657 nsrequest
= port
->ip_nsrequest
;
658 if (nsrequest
!= IP_NULL
)
659 ipc_notify_send_once(nsrequest
); /* consumes ref */
661 /* destroy any queued messages */
662 mqueue
= &port
->ip_messages
;
663 ipc_mqueue_destroy(mqueue
);
665 /* generate dead-name notifications */
666 if (dnrequests
!= IPR_NULL
) {
667 ipc_port_dnnotify(port
, dnrequests
);
670 ipc_kobject_destroy(port
);
672 ipc_port_release(port
); /* consume caller's ref */
676 * Routine: ipc_port_check_circularity
678 * Check if queueing "port" in a message for "dest"
679 * would create a circular group of ports and messages.
681 * If no circularity (FALSE returned), then "port"
682 * is changed from "in limbo" to "in transit".
684 * That is, we want to set port->ip_destination == dest,
685 * but guaranteeing that this doesn't create a circle
686 * port->ip_destination->ip_destination->... == port
688 * No ports locked. References held for "port" and "dest".
692 ipc_port_check_circularity(
698 assert(port
!= IP_NULL
);
699 assert(dest
!= IP_NULL
);
706 * First try a quick check that can run in parallel.
707 * No circularity if dest is not in transit.
711 if (ip_lock_try(dest
)) {
712 if (!ip_active(dest
) ||
713 (dest
->ip_receiver_name
!= MACH_PORT_NULL
) ||
714 (dest
->ip_destination
== IP_NULL
))
717 /* dest is in transit; further checking necessary */
723 ipc_port_multiple_lock(); /* massive serialization */
726 * Search for the end of the chain (a port not in transit),
727 * acquiring locks along the way.
733 if (!ip_active(base
) ||
734 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
735 (base
->ip_destination
== IP_NULL
))
738 base
= base
->ip_destination
;
741 /* all ports in chain from dest to base, inclusive, are locked */
744 /* circularity detected! */
746 ipc_port_multiple_unlock();
748 /* port (== base) is in limbo */
750 assert(ip_active(port
));
751 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
752 assert(port
->ip_destination
== IP_NULL
);
754 while (dest
!= IP_NULL
) {
757 /* dest is in transit or in limbo */
759 assert(ip_active(dest
));
760 assert(dest
->ip_receiver_name
== MACH_PORT_NULL
);
762 next
= dest
->ip_destination
;
771 * The guarantee: lock port while the entire chain is locked.
772 * Once port is locked, we can take a reference to dest,
773 * add port to the chain, and unlock everything.
777 ipc_port_multiple_unlock();
781 /* port is in limbo */
783 assert(ip_active(port
));
784 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
785 assert(port
->ip_destination
== IP_NULL
);
788 port
->ip_destination
= dest
;
790 /* now unlock chain */
792 while (port
!= base
) {
795 /* port is in transit */
797 assert(ip_active(port
));
798 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
799 assert(port
->ip_destination
!= IP_NULL
);
801 next
= port
->ip_destination
;
806 /* base is not in transit */
808 assert(!ip_active(base
) ||
809 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
810 (base
->ip_destination
== IP_NULL
));
817 * Routine: ipc_port_lookup_notify
819 * Make a send-once notify port from a receive right.
820 * Returns IP_NULL if name doesn't denote a receive right.
822 * The space must be locked (read or write) and active.
823 * Being the active space, we can rely on thread server_id
824 * context to give us the proper server level sub-order
829 ipc_port_lookup_notify(
831 mach_port_name_t name
)
836 assert(space
->is_active
);
838 entry
= ipc_entry_lookup(space
, name
);
839 if (entry
== IE_NULL
)
841 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
844 port
= (ipc_port_t
) entry
->ie_object
;
845 assert(port
!= IP_NULL
);
848 assert(ip_active(port
));
849 assert(port
->ip_receiver_name
== name
);
850 assert(port
->ip_receiver
== space
);
860 * Routine: ipc_port_make_send_locked
862 * Make a naked send right from a receive right.
865 * port locked and active.
868 ipc_port_make_send_locked(
871 assert(ip_active(port
));
880 * Routine: ipc_port_make_send
882 * Make a naked send right from a receive right.
894 if (ip_active(port
)) {
906 * Routine: ipc_port_copy_send
908 * Make a naked send right from another naked send right.
911 * dead port -> IP_DEAD
912 * live port -> port + ref
914 * Nothing locked except possibly a space.
927 if (ip_active(port
)) {
928 assert(port
->ip_srights
> 0);
941 * Routine: ipc_port_copyout_send
943 * Copyout a naked send right (possibly null/dead),
944 * or if that fails, destroy the right.
950 ipc_port_copyout_send(
954 mach_port_name_t name
;
956 if (IP_VALID(sright
)) {
959 kr
= ipc_object_copyout(space
, (ipc_object_t
) sright
,
960 MACH_MSG_TYPE_PORT_SEND
, TRUE
, &name
);
961 if (kr
!= KERN_SUCCESS
) {
962 ipc_port_release_send(sright
);
964 if (kr
== KERN_INVALID_CAPABILITY
)
965 name
= MACH_PORT_DEAD
;
967 name
= MACH_PORT_NULL
;
970 name
= (mach_port_name_t
) sright
;
976 * Routine: ipc_port_release_send
978 * Release a (valid) naked send right.
979 * Consumes a ref for the port.
985 ipc_port_release_send(
988 ipc_port_t nsrequest
= IP_NULL
;
989 mach_port_mscount_t mscount
;
991 assert(IP_VALID(port
));
996 if (!ip_active(port
)) {
997 ip_check_unlock(port
);
1001 assert(port
->ip_srights
> 0);
1003 if (--port
->ip_srights
== 0 &&
1004 port
->ip_nsrequest
!= IP_NULL
) {
1005 nsrequest
= port
->ip_nsrequest
;
1006 port
->ip_nsrequest
= IP_NULL
;
1007 mscount
= port
->ip_mscount
;
1009 ipc_notify_no_senders(nsrequest
, mscount
);
1015 * Routine: ipc_port_make_sonce
1017 * Make a naked send-once right from a receive right.
1019 * The port is not locked but it is active.
1023 ipc_port_make_sonce(
1026 assert(IP_VALID(port
));
1029 assert(ip_active(port
));
1030 port
->ip_sorights
++;
1038 * Routine: ipc_port_release_sonce
1040 * Release a naked send-once right.
1041 * Consumes a ref for the port.
1043 * In normal situations, this is never used.
1044 * Send-once rights are only consumed when
1045 * a message (possibly a send-once notification)
1048 * Nothing locked except possibly a space.
1052 ipc_port_release_sonce(
1055 assert(IP_VALID(port
));
1059 assert(port
->ip_sorights
> 0);
1061 port
->ip_sorights
--;
1065 if (!ip_active(port
)) {
1066 ip_check_unlock(port
);
1074 * Routine: ipc_port_release_receive
1076 * Release a naked (in limbo or in transit) receive right.
1077 * Consumes a ref for the port; destroys the port.
1083 ipc_port_release_receive(
1088 assert(IP_VALID(port
));
1091 assert(ip_active(port
));
1092 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1093 dest
= port
->ip_destination
;
1095 ipc_port_destroy(port
); /* consumes ref, unlocks */
1097 if (dest
!= IP_NULL
)
1098 ipc_port_release(dest
);
1102 * Routine: ipc_port_alloc_special
1104 * Allocate a port in a special space.
1105 * The new port is returned with one ref.
1106 * If unsuccessful, IP_NULL is returned.
1112 ipc_port_alloc_special(
1117 port
= (ipc_port_t
) io_alloc(IOT_PORT
);
1118 if (port
== IP_NULL
)
1121 bzero((char *)port
, sizeof(*port
));
1122 io_lock_init(&port
->ip_object
);
1123 port
->ip_references
= 1;
1124 port
->ip_object
.io_bits
= io_makebits(TRUE
, IOT_PORT
, 0);
1126 ipc_port_init(port
, space
, 1);
1132 * Routine: ipc_port_dealloc_special
1134 * Deallocate a port in a special space.
1135 * Consumes one ref for the port.
1141 ipc_port_dealloc_special(
1143 __assert_only ipc_space_t space
)
1146 assert(ip_active(port
));
1147 // assert(port->ip_receiver_name != MACH_PORT_NULL);
1148 assert(port
->ip_receiver
== space
);
1151 * We clear ip_receiver_name and ip_receiver to simplify
1152 * the ipc_space_kernel check in ipc_mqueue_send.
1155 port
->ip_receiver_name
= MACH_PORT_NULL
;
1156 port
->ip_receiver
= IS_NULL
;
1158 /* relevant part of ipc_port_clear_receiver */
1159 ipc_port_set_mscount(port
, 0);
1160 port
->ip_messages
.imq_seqno
= 0;
1162 ipc_port_destroy(port
);
1167 #include <kern/machine.h>
1170 * Keep a list of all allocated ports.
1171 * Allocation is intercepted via ipc_port_init;
1172 * deallocation is intercepted via io_free.
1174 queue_head_t port_alloc_queue
;
1175 decl_mutex_data(,port_alloc_queue_lock
)
1177 unsigned long port_count
= 0;
1178 unsigned long port_count_warning
= 20000;
1179 unsigned long port_timestamp
= 0;
1181 void db_port_stack_trace(
1186 unsigned int verbose
,
1187 unsigned int display
,
1188 unsigned int ref_search
,
1189 unsigned int ref_target
);
1192 * Initialize global state needed for run-time
1196 ipc_port_debug_init(void)
1198 queue_init(&port_alloc_queue
);
1199 mutex_init(&port_alloc_queue_lock
, 0);
1204 * Initialize all of the debugging state in a port.
1205 * Insert the port into a global list of all allocated ports.
1208 ipc_port_init_debug(
1213 port
->ip_thread
= current_thread();
1214 port
->ip_timetrack
= port_timestamp
++;
1215 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
)
1216 port
->ip_callstack
[i
] = 0;
1217 for (i
= 0; i
< IP_NSPARES
; ++i
)
1218 port
->ip_spares
[i
] = 0;
1221 * Machine-dependent routine to fill in an
1222 * array with up to IP_CALLSTACK_MAX levels
1223 * of return pc information.
1225 machine_callstack(&port
->ip_callstack
[0], IP_CALLSTACK_MAX
);
1228 mutex_lock(&port_alloc_queue_lock
);
1230 if (port_count_warning
> 0 && port_count
>= port_count_warning
)
1231 assert(port_count
< port_count_warning
);
1232 queue_enter(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1233 mutex_unlock(&port_alloc_queue_lock
);
1239 * Remove a port from the queue of allocated ports.
1240 * This routine should be invoked JUST prior to
1241 * deallocating the actual memory occupied by the port.
1245 ipc_port_track_dealloc(
1246 __unused ipc_port_t port
)
1251 ipc_port_track_dealloc(
1254 mutex_lock(&port_alloc_queue_lock
);
1255 assert(port_count
> 0);
1257 queue_remove(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1258 mutex_unlock(&port_alloc_queue_lock
);
1262 #endif /* MACH_ASSERT */
1267 #include <ddb/db_output.h>
1268 #include <ddb/db_print.h>
1270 #define printf kdbprintf
1273 db_port_queue_print(
1277 * Routine: ipc_port_print
1279 * Pretty-print a port for kdb.
1281 int ipc_port_print_long
= 0; /* set for more detail */
1286 __unused boolean_t have_addr
,
1287 __unused db_expr_t count
,
1295 int i
, needs_db_indent
, items_printed
;
1296 #endif /* MACH_ASSERT */
1298 if (db_option(modif
, 'l') || db_option(modif
, 'v'))
1301 printf("port 0x%x\n", port
);
1305 ipc_object_print(&port
->ip_object
);
1307 if (ipc_port_print_long
) {
1311 if (!ip_active(port
)) {
1312 iprintf("timestamp=0x%x", port
->ip_timestamp
);
1313 } else if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1314 iprintf("destination=0x%x (", port
->ip_destination
);
1315 if (port
->ip_destination
!= MACH_PORT_NULL
&&
1316 (task
= db_task_from_space(port
->ip_destination
->
1317 ip_receiver
, &task_id
)))
1318 printf("task%d at 0x%x", task_id
, task
);
1323 iprintf("receiver=0x%x (", port
->ip_receiver
);
1324 if (port
->ip_receiver
== ipc_space_kernel
)
1326 else if (port
->ip_receiver
== ipc_space_reply
)
1328 else if (port
->ip_receiver
== default_pager_space
)
1329 printf("default_pager");
1330 else if ((task
= db_task_from_space(port
->ip_receiver
, &task_id
)) != (db_addr_t
)0)
1331 printf("task%d at 0x%x", task_id
, task
);
1336 printf(", receiver_name=0x%x\n", port
->ip_receiver_name
);
1338 iprintf("mscount=%d", port
->ip_mscount
);
1339 printf(", srights=%d", port
->ip_srights
);
1340 printf(", sorights=%d\n", port
->ip_sorights
);
1342 iprintf("nsrequest=0x%x", port
->ip_nsrequest
);
1343 printf(", pdrequest=0x%x", port
->ip_pdrequest
);
1344 printf(", dnrequests=0x%x\n", port
->ip_dnrequests
);
1346 iprintf("pset_count=0x%x", port
->ip_pset_count
);
1347 printf(", seqno=%d", port
->ip_messages
.imq_seqno
);
1348 printf(", msgcount=%d", port
->ip_messages
.imq_msgcount
);
1349 printf(", qlimit=%d\n", port
->ip_messages
.imq_qlimit
);
1351 iprintf("kmsgs=0x%x", port
->ip_messages
.imq_messages
.ikmq_base
);
1352 printf(", rcvrs queue=0x%x", port
->ip_messages
.imq_wait_queue
);
1353 printf(", kobj=0x%x\n", port
->ip_kobject
);
1355 iprintf("premsg=0x%x", port
->ip_premsg
);
1358 /* don't bother printing callstack or queue links */
1359 iprintf("ip_thread=0x%x, ip_timetrack=0x%x\n",
1360 port
->ip_thread
, port
->ip_timetrack
);
1362 needs_db_indent
= 1;
1363 for (i
= 0; i
< IP_NSPARES
; ++i
) {
1364 if (port
->ip_spares
[i
] != 0) {
1365 if (needs_db_indent
) {
1367 needs_db_indent
= 0;
1369 printf("%sip_spares[%d] = %d",
1370 items_printed
? ", " : "", i
,
1371 port
->ip_spares
[i
]);
1372 if (++items_printed
>= 4) {
1373 needs_db_indent
= 1;
1379 #endif /* MACH_ASSERT */
1382 iprintf("kmsg queue contents:\n");
1384 nmsgs
= db_port_queue_print(port
);
1386 iprintf("...total kmsgs: %d\n", nmsgs
);
1395 mach_port_name_t name
)
1400 if (task
== TASK_NULL
) {
1401 db_printf("port_name_to_data: task is null\n");
1404 if ((space
= task
->itk_space
) == 0) {
1405 db_printf("port_name_to_data: task->itk_space is null\n");
1408 if (!space
->is_active
) {
1409 db_printf("port_name_to_data: task->itk_space not active\n");
1412 if ((entry
= ipc_entry_lookup(space
, name
)) == 0) {
1413 db_printf("port_name_to_data: lookup yields zero\n");
1416 return ((ipc_port_t
)entry
->ie_object
);
1421 print_type_ports(type
, dead
)
1429 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1431 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1433 if (ip_kotype(port
) == type
&&
1434 (!dead
|| !ip_active(port
))) {
1436 printf("0x%x\t", port
);
1438 printf("0x%x\n", port
);
1448 int total_port_count
;
1449 int space_null_count
;
1450 int space_kernel_count
;
1451 int space_reply_count
;
1452 int space_pager_count
;
1453 int space_other_count
;
1458 } port_types
[IKOT_MAX_TYPE
];
1460 total_port_count
= 0;
1462 bzero((char *)&port_types
[0], sizeof(port_types
));
1463 space_null_count
= 0;
1464 space_kernel_count
= 0;
1465 space_reply_count
= 0;
1466 space_pager_count
= 0;
1467 space_other_count
= 0;
1469 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1471 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1474 if (ip_kotype(port
) >= IKOT_MAX_TYPE
) {
1475 port_types
[IKOT_UNKNOWN
].total_count
++;
1476 if (!io_active(&port
->ip_object
))
1477 port_types
[IKOT_UNKNOWN
].dead_count
++;
1479 port_types
[ip_kotype(port
)].total_count
++;
1480 if (!io_active(&port
->ip_object
))
1481 port_types
[ip_kotype(port
)].dead_count
++;
1484 if (!port
->ip_receiver
)
1486 else if (port
->ip_receiver
== ipc_space_kernel
)
1487 space_kernel_count
++;
1488 else if (port
->ip_receiver
== ipc_space_reply
)
1489 space_reply_count
++;
1490 else if (port
->ip_receiver
== default_pager_space
)
1491 space_pager_count
++;
1493 space_other_count
++;
1495 printf("\n%7d total ports\n\n", total_port_count
);
1497 #define PRINT_ONE_PORT_TYPE(name) \
1498 printf("%7d %s", port_types[IKOT_##name].total_count, # name); \
1499 if (port_types[IKOT_##name].dead_count) \
1500 printf(" (%d dead ports)", port_types[IKOT_##name].dead_count);\
1503 PRINT_ONE_PORT_TYPE(NONE
);
1504 PRINT_ONE_PORT_TYPE(THREAD
);
1505 PRINT_ONE_PORT_TYPE(TASK
);
1506 PRINT_ONE_PORT_TYPE(HOST
);
1507 PRINT_ONE_PORT_TYPE(HOST_PRIV
);
1508 PRINT_ONE_PORT_TYPE(PROCESSOR
);
1509 PRINT_ONE_PORT_TYPE(PSET
);
1510 PRINT_ONE_PORT_TYPE(PSET_NAME
);
1511 PRINT_ONE_PORT_TYPE(PAGING_REQUEST
);
1512 PRINT_ONE_PORT_TYPE(MEMORY_OBJECT
);
1513 PRINT_ONE_PORT_TYPE(MIG
);
1514 PRINT_ONE_PORT_TYPE(XMM_PAGER
);
1515 PRINT_ONE_PORT_TYPE(XMM_KERNEL
);
1516 PRINT_ONE_PORT_TYPE(XMM_REPLY
);
1517 PRINT_ONE_PORT_TYPE(CLOCK
);
1518 PRINT_ONE_PORT_TYPE(CLOCK_CTRL
);
1519 PRINT_ONE_PORT_TYPE(MASTER_DEVICE
);
1520 PRINT_ONE_PORT_TYPE(UNKNOWN
);
1521 printf("\nipc_space:\n\n");
1522 printf("NULL KERNEL REPLY PAGER OTHER\n");
1523 printf("%d %d %d %d %d\n",
1532 #endif /* ZONE_DEBUG */
1536 * Print out all the kmsgs in a queue. Aggregate kmsgs with
1537 * identical message ids into a single entry. Count up the
1538 * amount of inline and out-of-line data consumed by each
1543 #define KMSG_MATCH_FIELD(kmsg) (kmsg->ikm_header->msgh_id)
1544 #define DKQP_LONG(kmsg) FALSE
1545 const char *dkqp_long_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1546 const char *dkqp_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1549 db_kmsg_queue_print(
1552 db_kmsg_queue_print(
1555 ipc_kmsg_t ikmsg
, first_kmsg
;
1556 register int icount
;
1557 mach_msg_id_t cur_id
;
1558 unsigned int inline_total
, ool_total
;
1561 iprintf("Count msgh_id kmsg addr inline bytes ool bytes\n");
1562 inline_total
= ool_total
= (vm_size_t
) 0;
1563 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1564 for (icount
= 0, nmsgs
= 0, first_kmsg
= ikmsg
= kmsg
;
1565 kmsg
!= IKM_NULL
&& (kmsg
!= first_kmsg
|| nmsgs
== 0);
1566 kmsg
= kmsg
->ikm_next
) {
1568 if (!(KMSG_MATCH_FIELD(kmsg
) == cur_id
)) {
1569 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
:dkqp_format
,
1570 icount
, cur_id
, ikmsg
, inline_total
,ool_total
);
1571 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1574 inline_total
= ool_total
= 0;
1578 if (DKQP_LONG(kmsg
))
1579 inline_total
+= kmsg
->ikm_size
;
1581 inline_total
+= kmsg
->ikm_header
->msgh_size
;
1583 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
: dkqp_format
,
1584 icount
, cur_id
, ikmsg
, inline_total
, ool_total
);
1590 * Process all of the messages on a port - prints out the
1591 * number of occurences of each message type, and the first
1592 * kmsg with a particular msgh_id.
1595 db_port_queue_print(
1600 if (ipc_kmsg_queue_empty(&port
->ip_messages
.imq_messages
))
1602 kmsg
= ipc_kmsg_queue_first(&port
->ip_messages
.imq_messages
);
1603 return db_kmsg_queue_print(kmsg
);
1608 #include <ddb/db_sym.h>
1609 #include <ddb/db_access.h>
1611 #define FUNC_NULL ((void (*)) 0)
1612 #define MAX_REFS 5 /* bins for tracking ref counts */
1615 * Translate port's cache of call stack pointers
1616 * into symbolic names.
1619 db_port_stack_trace(
1624 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1625 iprintf("[%d] 0x%x\t", i
, port
->ip_callstack
[i
]);
1626 if (port
->ip_callstack
[i
] != 0 &&
1627 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1628 db_printsym(port
->ip_callstack
[i
], DB_STGY_PROC
);
1634 typedef struct port_item
{
1636 unsigned long count
;
1640 #define ITEM_MAX 400
1641 typedef struct port_track
{
1644 unsigned long warning
;
1645 port_item items
[ITEM_MAX
];
1648 port_track port_callers
; /* match against calling addresses */
1649 port_track port_threads
; /* match against allocating threads */
1650 port_track port_spaces
; /* match against ipc spaces */
1652 void port_track_init(
1657 unsigned long item
);
1658 void port_track_sort(
1659 port_track
*trackp
);
1660 void port_track_print(
1662 void (*func
)(port_item
*));
1663 void port_callers_print(
1673 trackp
->max
= trackp
->warning
= 0;
1674 trackp
->name
= name
;
1675 for (i
= trackp
->items
; i
< trackp
->items
+ ITEM_MAX
; ++i
)
1676 i
->item
= i
->count
= 0;
1685 port_item
*limit
, *i
;
1687 limit
= trackp
->items
+ trackp
->max
;
1688 for (i
= trackp
->items
; i
< limit
; ++i
)
1689 if (i
->item
== item
) {
1693 if (trackp
->max
>= ITEM_MAX
) {
1694 if (trackp
->warning
++ == 0)
1695 iprintf("%s: no room\n", trackp
->name
);
1705 * Simple (and slow) bubble sort.
1711 port_item
*limit
, *p
;
1715 limit
= trackp
->items
+ trackp
->max
- 1;
1718 for (p
= trackp
->items
; p
< limit
- 1; ++p
) {
1719 if (p
->count
< (p
+1)->count
) {
1726 } while (unsorted
== TRUE
);
1733 void (*func
)(port_item
*))
1735 port_item
*limit
, *p
;
1737 limit
= trackp
->items
+ trackp
->max
;
1738 iprintf("%s:\n", trackp
->name
);
1739 for (p
= trackp
->items
; p
< limit
; ++p
) {
1740 if (func
!= FUNC_NULL
)
1743 iprintf("0x%x\t%8d\n", p
->item
, p
->count
);
1752 iprintf("0x%x\t%8d\t", p
->item
, p
->count
);
1753 db_printsym(p
->item
, DB_STGY_PROC
);
1759 * Show all ports with a given reference count.
1765 db_port_walk(1, 1, 1, refs
);
1770 * Examine all currently allocated ports.
1772 * verbose display suspicious ports
1773 * display print out each port encountered
1774 * ref_search restrict examination to ports with
1775 * a specified reference count
1776 * ref_target reference count for ref_search
1780 unsigned int verbose
,
1781 unsigned int display
,
1782 unsigned int ref_search
,
1783 unsigned int ref_target
)
1786 unsigned int ref_overflow
, refs
, i
, ref_inactive_overflow
;
1787 unsigned int no_receiver
, no_match
;
1788 unsigned int ref_counts
[MAX_REFS
];
1789 unsigned int inactive
[MAX_REFS
];
1790 unsigned int ipc_ports
= 0;
1792 iprintf("Allocated port count is %d\n", port_count
);
1793 no_receiver
= no_match
= ref_overflow
= 0;
1794 ref_inactive_overflow
= 0;
1795 for (i
= 0; i
< MAX_REFS
; ++i
) {
1799 port_track_init(&port_callers
, "port callers");
1800 port_track_init(&port_threads
, "port threads");
1801 port_track_init(&port_spaces
, "port spaces");
1803 iprintf("Walking ports of ref_count=%d.\n", ref_target
);
1805 iprintf("Walking all ports.\n");
1807 queue_iterate(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
) {
1808 const char *port_type
;
1810 port_type
= " IPC port";
1811 if (ip_active(port
))
1814 refs
= port
->ip_references
;
1815 if (ref_search
&& refs
!= ref_target
)
1818 if (refs
>= MAX_REFS
) {
1819 if (ip_active(port
))
1822 ++ref_inactive_overflow
;
1824 if (refs
== 0 && verbose
)
1825 iprintf("%s 0x%x has ref count of zero!\n",
1827 if (ip_active(port
))
1832 port_item_add(&port_threads
, (unsigned long) port
->ip_thread
);
1833 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1834 if (port
->ip_callstack
[i
] != 0 &&
1835 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1836 port_item_add(&port_callers
,
1837 port
->ip_callstack
[i
]);
1839 if (!ip_active(port
)) {
1841 iprintf("%s 0x%x, inactive, refcnt %d\n",
1842 port_type
, port
, refs
);
1846 if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1847 iprintf("%s 0x%x, no receiver, refcnt %d\n",
1852 if (port
->ip_receiver
== ipc_space_kernel
||
1853 port
->ip_receiver
== ipc_space_reply
||
1854 ipc_entry_lookup(port
->ip_receiver
,
1855 port
->ip_receiver_name
)
1857 port_item_add(&port_spaces
,
1858 (unsigned long)port
->ip_receiver
);
1860 iprintf( "%s 0x%x time 0x%x ref_cnt %d\n",
1862 port
->ip_timetrack
, refs
);
1866 iprintf("%s 0x%x, rcvr 0x%x, name 0x%x, ref %d, no match\n",
1867 port_type
, port
, port
->ip_receiver
,
1868 port
->ip_receiver_name
, refs
);
1871 iprintf("Active port type summary:\n");
1872 iprintf("\tlocal IPC %6d\n", ipc_ports
);
1873 iprintf("summary:\tcallers %d threads %d spaces %d\n",
1874 port_callers
.max
, port_threads
.max
, port_spaces
.max
);
1876 iprintf("\tref_counts:\n");
1877 for (i
= 0; i
< MAX_REFS
; ++i
)
1878 iprintf("\t ref_counts[%d] = %d\n", i
, ref_counts
[i
]);
1880 iprintf("\t%d ports w/o receivers, %d w/o matches\n",
1881 no_receiver
, no_match
);
1883 iprintf("\tinactives:");
1884 if ( ref_inactive_overflow
|| inactive
[0] || inactive
[1] ||
1885 inactive
[2] || inactive
[3] || inactive
[4] )
1886 printf(" [0]=%d [1]=%d [2]=%d [3]=%d [4]=%d [5+]=%d\n",
1887 inactive
[0], inactive
[1], inactive
[2],
1888 inactive
[3], inactive
[4], ref_inactive_overflow
);
1890 printf(" No inactive ports.\n");
1892 port_track_sort(&port_spaces
);
1893 port_track_print(&port_spaces
, FUNC_NULL
);
1894 port_track_sort(&port_threads
);
1895 port_track_print(&port_threads
, FUNC_NULL
);
1896 port_track_sort(&port_callers
);
1897 port_track_print(&port_callers
, port_callers_print
);
1902 #endif /* MACH_ASSERT */
1904 #endif /* MACH_KDB */