2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * @OSF_FREE_COPYRIGHT@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 * File: ipc/ipc_port.c
57 * Functions to manipulate IPC ports.
62 #include <zone_debug.h>
63 #include <mach_assert.h>
65 #include <mach/port.h>
66 #include <mach/kern_return.h>
67 #include <kern/lock.h>
68 #include <kern/ipc_kobject.h>
69 #include <kern/ipc_subsystem.h>
70 #include <kern/thread.h>
71 #include <kern/thread_pool.h>
72 #include <kern/misc_protos.h>
73 #include <kern/wait_queue.h>
74 #include <ipc/ipc_entry.h>
75 #include <ipc/ipc_space.h>
76 #include <ipc/ipc_object.h>
77 #include <ipc/ipc_port.h>
78 #include <ipc/ipc_pset.h>
79 #include <ipc/ipc_kmsg.h>
80 #include <ipc/ipc_mqueue.h>
81 #include <ipc/ipc_notify.h>
82 #include <ipc/ipc_print.h>
83 #include <ipc/ipc_table.h>
86 #include <machine/db_machdep.h>
87 #include <ddb/db_command.h>
88 #include <ddb/db_expr.h>
93 decl_mutex_data(, ipc_port_multiple_lock_data
)
94 decl_mutex_data(, ipc_port_timestamp_lock_data
)
95 ipc_port_timestamp_t ipc_port_timestamp_data
;
98 void ipc_port_init_debug(
100 #endif /* MACH_ASSERT */
102 #if MACH_KDB && ZONE_DEBUG
104 void print_type_ports(unsigned, unsigned);
105 void print_ports(void);
106 #endif /* MACH_KDB && ZONE_DEBUG */
109 * Routine: ipc_port_timestamp
111 * Retrieve a timestamp value.
115 ipc_port_timestamp(void)
117 ipc_port_timestamp_t timestamp
;
119 ipc_port_timestamp_lock();
120 timestamp
= ipc_port_timestamp_data
++;
121 ipc_port_timestamp_unlock();
127 * Routine: ipc_port_dnrequest
129 * Try to allocate a dead-name request slot.
130 * If successful, returns the request index.
131 * Otherwise returns zero.
133 * The port is locked and active.
135 * KERN_SUCCESS A request index was found.
136 * KERN_NO_SPACE No index allocated.
142 mach_port_name_t name
,
144 ipc_port_request_index_t
*indexp
)
146 ipc_port_request_t ipr
, table
;
147 ipc_port_request_index_t index
;
149 assert(ip_active(port
));
150 assert(name
!= MACH_PORT_NULL
);
151 assert(soright
!= IP_NULL
);
153 table
= port
->ip_dnrequests
;
154 if (table
== IPR_NULL
)
155 return KERN_NO_SPACE
;
157 index
= table
->ipr_next
;
159 return KERN_NO_SPACE
;
162 assert(ipr
->ipr_name
== MACH_PORT_NULL
);
164 table
->ipr_next
= ipr
->ipr_next
;
165 ipr
->ipr_name
= name
;
166 ipr
->ipr_soright
= soright
;
173 * Routine: ipc_port_dngrow
175 * Grow a port's table of dead-name requests.
177 * The port must be locked and active.
178 * Nothing else locked; will allocate memory.
179 * Upon return the port is unlocked.
181 * KERN_SUCCESS Grew the table.
182 * KERN_SUCCESS Somebody else grew the table.
183 * KERN_SUCCESS The port died.
184 * KERN_RESOURCE_SHORTAGE Couldn't allocate new table.
185 * KERN_NO_SPACE Couldn't grow to desired size
193 ipc_table_size_t its
;
194 ipc_port_request_t otable
, ntable
;
196 assert(ip_active(port
));
198 otable
= port
->ip_dnrequests
;
199 if (otable
== IPR_NULL
)
200 its
= &ipc_table_dnrequests
[0];
202 its
= otable
->ipr_size
+ 1;
204 if (target_size
!= ITS_SIZE_NONE
) {
205 if ((otable
!= IPR_NULL
) &&
206 (target_size
<= otable
->ipr_size
->its_size
)) {
210 while ((its
->its_size
) && (its
->its_size
< target_size
)) {
213 if (its
->its_size
== 0) {
215 return KERN_NO_SPACE
;
222 if ((its
->its_size
== 0) ||
223 ((ntable
= it_dnrequests_alloc(its
)) == IPR_NULL
)) {
224 ipc_port_release(port
);
225 return KERN_RESOURCE_SHORTAGE
;
232 * Check that port is still active and that nobody else
233 * has slipped in and grown the table on us. Note that
234 * just checking port->ip_dnrequests == otable isn't
235 * sufficient; must check ipr_size.
238 if (ip_active(port
) &&
239 (port
->ip_dnrequests
== otable
) &&
240 ((otable
== IPR_NULL
) || (otable
->ipr_size
+1 == its
))) {
241 ipc_table_size_t oits
;
242 ipc_table_elems_t osize
, nsize
;
243 ipc_port_request_index_t free
, i
;
245 /* copy old table to new table */
247 if (otable
!= IPR_NULL
) {
248 oits
= otable
->ipr_size
;
249 osize
= oits
->its_size
;
250 free
= otable
->ipr_next
;
252 (void) memcpy((void *)(ntable
+ 1),
253 (const void *)(otable
+ 1),
254 (osize
- 1) * sizeof(struct ipc_port_request
));
260 nsize
= its
->its_size
;
261 assert(nsize
> osize
);
263 /* add new elements to the new table's free list */
265 for (i
= osize
; i
< nsize
; i
++) {
266 ipc_port_request_t ipr
= &ntable
[i
];
268 ipr
->ipr_name
= MACH_PORT_NULL
;
269 ipr
->ipr_next
= free
;
273 ntable
->ipr_next
= free
;
274 ntable
->ipr_size
= its
;
275 port
->ip_dnrequests
= ntable
;
278 if (otable
!= IPR_NULL
) {
279 it_dnrequests_free(oits
, otable
);
282 ip_check_unlock(port
);
283 it_dnrequests_free(its
, ntable
);
290 * Routine: ipc_port_dncancel
292 * Cancel a dead-name request and return the send-once right.
294 * The port must locked and active.
300 mach_port_name_t name
,
301 ipc_port_request_index_t index
)
303 ipc_port_request_t ipr
, table
;
304 ipc_port_t dnrequest
;
306 assert(ip_active(port
));
307 assert(name
!= MACH_PORT_NULL
);
310 table
= port
->ip_dnrequests
;
311 assert(table
!= IPR_NULL
);
314 dnrequest
= ipr
->ipr_soright
;
315 assert(ipr
->ipr_name
== name
);
317 /* return ipr to the free list inside the table */
319 ipr
->ipr_name
= MACH_PORT_NULL
;
320 ipr
->ipr_next
= table
->ipr_next
;
321 table
->ipr_next
= index
;
327 * Routine: ipc_port_pdrequest
329 * Make a port-deleted request, returning the
330 * previously registered send-once right.
331 * Just cancels the previous request if notify is IP_NULL.
333 * The port is locked and active. It is unlocked.
334 * Consumes a ref for notify (if non-null), and
335 * returns previous with a ref (if non-null).
342 ipc_port_t
*previousp
)
346 assert(ip_active(port
));
348 previous
= port
->ip_pdrequest
;
349 port
->ip_pdrequest
= notify
;
352 *previousp
= previous
;
356 * Routine: ipc_port_nsrequest
358 * Make a no-senders request, returning the
359 * previously registered send-once right.
360 * Just cancels the previous request if notify is IP_NULL.
362 * The port is locked and active. It is unlocked.
363 * Consumes a ref for notify (if non-null), and
364 * returns previous with a ref (if non-null).
370 mach_port_mscount_t sync
,
372 ipc_port_t
*previousp
)
375 mach_port_mscount_t mscount
;
377 assert(ip_active(port
));
379 previous
= port
->ip_nsrequest
;
380 mscount
= port
->ip_mscount
;
382 if ((port
->ip_srights
== 0) && (sync
<= mscount
) &&
383 (notify
!= IP_NULL
)) {
384 port
->ip_nsrequest
= IP_NULL
;
386 ipc_notify_no_senders(notify
, mscount
);
388 port
->ip_nsrequest
= notify
;
392 *previousp
= previous
;
397 * Routine: ipc_port_clear_receiver
399 * Prepares a receive right for transmission/destruction.
401 * The port is locked and active.
405 ipc_port_clear_receiver(
410 assert(ip_active(port
));
413 * pull ourselves from any sets.
415 if (port
->ip_pset_count
!= 0) {
416 ipc_pset_remove_all(port
);
417 port
->ip_pset_count
= 0;
421 * Send anyone waiting on the port's queue directly away.
422 * Also clear the mscount and seqno.
425 imq_lock(&port
->ip_messages
);
426 ipc_mqueue_changed(&port
->ip_messages
);
427 ipc_port_set_mscount(port
, 0);
428 port
->ip_messages
.imq_seqno
= 0;
429 imq_unlock(&port
->ip_messages
);
434 * Routine: ipc_port_init
436 * Initializes a newly-allocated port.
437 * Doesn't touch the ip_object fields.
444 mach_port_name_t name
)
446 /* port->ip_kobject doesn't have to be initialized */
448 port
->ip_receiver
= space
;
449 port
->ip_receiver_name
= name
;
451 port
->ip_mscount
= 0;
452 port
->ip_srights
= 0;
453 port
->ip_sorights
= 0;
455 port
->ip_nsrequest
= IP_NULL
;
456 port
->ip_pdrequest
= IP_NULL
;
457 port
->ip_dnrequests
= IPR_NULL
;
459 port
->ip_pset_count
= 0;
460 port
->ip_premsg
= IKM_NULL
;
462 thread_pool_init(&port
->ip_thread_pool
);
464 port
->ip_subsystem
= RPC_SUBSYSTEM_NULL
;
467 ipc_port_init_debug(port
);
468 #endif /* MACH_ASSERT */
470 ipc_mqueue_init(&port
->ip_messages
, FALSE
/* set */);
474 * Routine: ipc_port_alloc
478 * Nothing locked. If successful, the port is returned
479 * locked. (The caller doesn't have a reference.)
481 * KERN_SUCCESS The port is allocated.
482 * KERN_INVALID_TASK The space is dead.
483 * KERN_NO_SPACE No room for an entry in the space.
484 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
490 mach_port_name_t
*namep
,
494 mach_port_name_t name
;
497 kr
= ipc_object_alloc(space
, IOT_PORT
,
498 MACH_PORT_TYPE_RECEIVE
, 0,
499 &name
, (ipc_object_t
*) &port
);
500 if (kr
!= KERN_SUCCESS
)
505 ipc_port_init(port
, space
, name
);
514 * Routine: ipc_port_alloc_name
516 * Allocate a port, with a specific name.
518 * Nothing locked. If successful, the port is returned
519 * locked. (The caller doesn't have a reference.)
521 * KERN_SUCCESS The port is allocated.
522 * KERN_INVALID_TASK The space is dead.
523 * KERN_NAME_EXISTS The name already denotes a right.
524 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
530 mach_port_name_t name
,
536 kr
= ipc_object_alloc_name(space
, IOT_PORT
,
537 MACH_PORT_TYPE_RECEIVE
, 0,
538 name
, (ipc_object_t
*) &port
);
539 if (kr
!= KERN_SUCCESS
)
544 ipc_port_init(port
, space
, name
);
552 * Generate dead name notifications. Called from ipc_port_destroy.
553 * Port is unlocked but still has reference(s);
554 * dnrequests was taken from port while the port
555 * was locked but the port now has port->ip_dnrequests set to IPR_NULL.
560 ipc_port_request_t dnrequests
)
562 ipc_table_size_t its
= dnrequests
->ipr_size
;
563 ipc_table_elems_t size
= its
->its_size
;
564 ipc_port_request_index_t index
;
566 for (index
= 1; index
< size
; index
++) {
567 ipc_port_request_t ipr
= &dnrequests
[index
];
568 mach_port_name_t name
= ipr
->ipr_name
;
571 if (name
== MACH_PORT_NULL
)
574 soright
= ipr
->ipr_soright
;
575 assert(soright
!= IP_NULL
);
577 ipc_notify_dead_name(soright
, name
);
580 it_dnrequests_free(its
, dnrequests
);
584 * Routine: ipc_port_destroy
586 * Destroys a port. Cleans up queued messages.
588 * If the port has a backup, it doesn't get destroyed,
589 * but is sent in a port-destroyed notification to the backup.
591 * The port is locked and alive; nothing else locked.
592 * The caller has a reference, which is consumed.
593 * Afterwards, the port is unlocked and dead.
600 ipc_port_t pdrequest
, nsrequest
;
602 ipc_kmsg_queue_t kmqueue
;
604 ipc_port_request_t dnrequests
;
605 thread_pool_t thread_pool
;
607 assert(ip_active(port
));
608 /* port->ip_receiver_name is garbage */
609 /* port->ip_receiver/port->ip_destination is garbage */
610 assert(port
->ip_pset_count
== 0);
611 assert(port
->ip_mscount
== 0);
613 /* first check for a backup port */
615 pdrequest
= port
->ip_pdrequest
;
616 if (pdrequest
!= IP_NULL
) {
617 /* we assume the ref for pdrequest */
618 port
->ip_pdrequest
= IP_NULL
;
620 /* make port be in limbo */
621 port
->ip_receiver_name
= MACH_PORT_NULL
;
622 port
->ip_destination
= IP_NULL
;
625 if (!ipc_port_check_circularity(port
, pdrequest
)) {
626 /* consumes our refs for port and pdrequest */
627 ipc_notify_port_destroyed(pdrequest
, port
);
630 /* consume pdrequest and destroy port */
631 ipc_port_release_sonce(pdrequest
);
635 assert(ip_active(port
));
636 assert(port
->ip_pset_count
== 0);
637 assert(port
->ip_mscount
== 0);
638 assert(port
->ip_pdrequest
== IP_NULL
);
639 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
640 assert(port
->ip_destination
== IP_NULL
);
642 /* fall through and destroy the port */
645 /* once port is dead, we don't need to keep it locked */
647 port
->ip_object
.io_bits
&= ~IO_BITS_ACTIVE
;
648 port
->ip_timestamp
= ipc_port_timestamp();
651 dnrequests
= port
->ip_dnrequests
;
652 port
->ip_dnrequests
= IPR_NULL
;
655 * If the port has a preallocated message buffer and that buffer
656 * is not inuse, free it. If it has and inuse one, then the kmsg
657 * free will detect that we freed the association and it can free it
658 * like a normal buffer.
660 if (IP_PREALLOC(port
)) {
661 kmsg
= port
->ip_premsg
;
662 assert(kmsg
!= IKM_NULL
);
663 if (!ikm_prealloc_inuse(kmsg
)) {
664 ikm_prealloc_clear_inuse(kmsg
, port
);
665 IP_CLEAR_PREALLOC(port
, kmsg
);
668 assert(ikm_prealloc_inuse_port(kmsg
) == port
);
669 ikm_prealloc_clear_inuse(kmsg
, port
);
670 IP_CLEAR_PREALLOC(port
, kmsg
);
676 /* wakeup any threads waiting on this pool port for an activation */
677 if ((thread_pool
= &port
->ip_thread_pool
) != THREAD_POOL_NULL
)
678 thread_pool_wakeup(thread_pool
);
680 /* throw away no-senders request */
682 nsrequest
= port
->ip_nsrequest
;
683 if (nsrequest
!= IP_NULL
)
684 ipc_notify_send_once(nsrequest
); /* consumes ref */
686 /* destroy any queued messages */
687 mqueue
= &port
->ip_messages
;
688 ipc_mqueue_destroy(mqueue
);
690 /* generate dead-name notifications */
691 if (dnrequests
!= IPR_NULL
) {
692 ipc_port_dnnotify(port
, dnrequests
);
695 ipc_kobject_destroy(port
);
697 if (port
->ip_subsystem
!= RPC_SUBSYSTEM_NULL
) {
698 subsystem_deallocate((subsystem_t
) port
->ip_kobject
);
701 /* XXXX Perhaps should verify that ip_thread_pool is empty! */
703 ipc_port_release(port
); /* consume caller's ref */
707 * Routine: ipc_port_check_circularity
709 * Check if queueing "port" in a message for "dest"
710 * would create a circular group of ports and messages.
712 * If no circularity (FALSE returned), then "port"
713 * is changed from "in limbo" to "in transit".
715 * That is, we want to set port->ip_destination == dest,
716 * but guaranteeing that this doesn't create a circle
717 * port->ip_destination->ip_destination->... == port
719 * No ports locked. References held for "port" and "dest".
723 ipc_port_check_circularity(
729 assert(port
!= IP_NULL
);
730 assert(dest
!= IP_NULL
);
737 * First try a quick check that can run in parallel.
738 * No circularity if dest is not in transit.
742 if (ip_lock_try(dest
)) {
743 if (!ip_active(dest
) ||
744 (dest
->ip_receiver_name
!= MACH_PORT_NULL
) ||
745 (dest
->ip_destination
== IP_NULL
))
748 /* dest is in transit; further checking necessary */
754 ipc_port_multiple_lock(); /* massive serialization */
757 * Search for the end of the chain (a port not in transit),
758 * acquiring locks along the way.
764 if (!ip_active(base
) ||
765 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
766 (base
->ip_destination
== IP_NULL
))
769 base
= base
->ip_destination
;
772 /* all ports in chain from dest to base, inclusive, are locked */
775 /* circularity detected! */
777 ipc_port_multiple_unlock();
779 /* port (== base) is in limbo */
781 assert(ip_active(port
));
782 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
783 assert(port
->ip_destination
== IP_NULL
);
785 while (dest
!= IP_NULL
) {
788 /* dest is in transit or in limbo */
790 assert(ip_active(dest
));
791 assert(dest
->ip_receiver_name
== MACH_PORT_NULL
);
793 next
= dest
->ip_destination
;
802 * The guarantee: lock port while the entire chain is locked.
803 * Once port is locked, we can take a reference to dest,
804 * add port to the chain, and unlock everything.
808 ipc_port_multiple_unlock();
812 /* port is in limbo */
814 assert(ip_active(port
));
815 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
816 assert(port
->ip_destination
== IP_NULL
);
819 port
->ip_destination
= dest
;
821 /* now unlock chain */
823 while (port
!= base
) {
826 /* port is in transit */
828 assert(ip_active(port
));
829 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
830 assert(port
->ip_destination
!= IP_NULL
);
832 next
= port
->ip_destination
;
837 /* base is not in transit */
839 assert(!ip_active(base
) ||
840 (base
->ip_receiver_name
!= MACH_PORT_NULL
) ||
841 (base
->ip_destination
== IP_NULL
));
848 * Routine: ipc_port_lookup_notify
850 * Make a send-once notify port from a receive right.
851 * Returns IP_NULL if name doesn't denote a receive right.
853 * The space must be locked (read or write) and active.
854 * Being the active space, we can rely on thread server_id
855 * context to give us the proper server level sub-order
860 ipc_port_lookup_notify(
862 mach_port_name_t name
)
867 assert(space
->is_active
);
869 entry
= ipc_entry_lookup(space
, name
);
870 if (entry
== IE_NULL
)
872 if ((entry
->ie_bits
& MACH_PORT_TYPE_RECEIVE
) == 0)
875 port
= (ipc_port_t
) entry
->ie_object
;
876 assert(port
!= IP_NULL
);
879 assert(ip_active(port
));
880 assert(port
->ip_receiver_name
== name
);
881 assert(port
->ip_receiver
== space
);
891 * Routine: ipc_port_make_send_locked
893 * Make a naked send right from a receive right.
896 * port locked and active.
899 ipc_port_make_send_locked(
902 assert(ip_active(port
));
911 * Routine: ipc_port_make_send
913 * Make a naked send right from a receive right.
925 if (ip_active(port
)) {
937 * Routine: ipc_port_copy_send
939 * Make a naked send right from another naked send right.
942 * dead port -> IP_DEAD
943 * live port -> port + ref
945 * Nothing locked except possibly a space.
958 if (ip_active(port
)) {
959 assert(port
->ip_srights
> 0);
972 * Routine: ipc_port_copyout_send
974 * Copyout a naked send right (possibly null/dead),
975 * or if that fails, destroy the right.
981 ipc_port_copyout_send(
985 mach_port_name_t name
;
987 if (IP_VALID(sright
)) {
990 kr
= ipc_object_copyout(space
, (ipc_object_t
) sright
,
991 MACH_MSG_TYPE_PORT_SEND
, TRUE
, &name
);
992 if (kr
!= KERN_SUCCESS
) {
993 ipc_port_release_send(sright
);
995 if (kr
== KERN_INVALID_CAPABILITY
)
996 name
= MACH_PORT_DEAD
;
998 name
= MACH_PORT_NULL
;
1001 name
= (mach_port_name_t
) sright
;
1007 * Routine: ipc_port_release_send
1009 * Release a (valid) naked send right.
1010 * Consumes a ref for the port.
1016 ipc_port_release_send(
1019 ipc_port_t nsrequest
= IP_NULL
;
1020 mach_port_mscount_t mscount
;
1022 assert(IP_VALID(port
));
1027 if (!ip_active(port
)) {
1028 ip_check_unlock(port
);
1032 assert(port
->ip_srights
> 0);
1034 if (--port
->ip_srights
== 0 &&
1035 port
->ip_nsrequest
!= IP_NULL
) {
1036 nsrequest
= port
->ip_nsrequest
;
1037 port
->ip_nsrequest
= IP_NULL
;
1038 mscount
= port
->ip_mscount
;
1040 ipc_notify_no_senders(nsrequest
, mscount
);
1042 * Check that there are no other locks taken, because
1043 * [norma_]ipc_notify_no_senders routines may block.
1045 check_simple_locks();
1051 * Routine: ipc_port_make_sonce
1053 * Make a naked send-once right from a receive right.
1055 * The port is not locked but it is active.
1059 ipc_port_make_sonce(
1062 assert(IP_VALID(port
));
1065 assert(ip_active(port
));
1066 port
->ip_sorights
++;
1074 * Routine: ipc_port_release_sonce
1076 * Release a naked send-once right.
1077 * Consumes a ref for the port.
1079 * In normal situations, this is never used.
1080 * Send-once rights are only consumed when
1081 * a message (possibly a send-once notification)
1084 * Nothing locked except possibly a space.
1088 ipc_port_release_sonce(
1091 assert(IP_VALID(port
));
1095 assert(port
->ip_sorights
> 0);
1097 port
->ip_sorights
--;
1101 if (!ip_active(port
)) {
1102 ip_check_unlock(port
);
1110 * Routine: ipc_port_release_receive
1112 * Release a naked (in limbo or in transit) receive right.
1113 * Consumes a ref for the port; destroys the port.
1119 ipc_port_release_receive(
1124 assert(IP_VALID(port
));
1127 assert(ip_active(port
));
1128 assert(port
->ip_receiver_name
== MACH_PORT_NULL
);
1129 dest
= port
->ip_destination
;
1131 ipc_port_destroy(port
); /* consumes ref, unlocks */
1133 if (dest
!= IP_NULL
)
1134 ipc_port_release(dest
);
1138 * Routine: ipc_port_alloc_special
1140 * Allocate a port in a special space.
1141 * The new port is returned with one ref.
1142 * If unsuccessful, IP_NULL is returned.
1148 ipc_port_alloc_special(
1153 port
= (ipc_port_t
) io_alloc(IOT_PORT
);
1154 if (port
== IP_NULL
)
1157 bzero((char *)port
, sizeof(*port
));
1158 io_lock_init(&port
->ip_object
);
1159 port
->ip_references
= 1;
1160 port
->ip_object
.io_bits
= io_makebits(TRUE
, IOT_PORT
, 0);
1162 ipc_port_init(port
, space
, 1);
1168 * Routine: ipc_port_dealloc_special
1170 * Deallocate a port in a special space.
1171 * Consumes one ref for the port.
1177 ipc_port_dealloc_special(
1182 assert(ip_active(port
));
1183 assert(port
->ip_receiver_name
!= MACH_PORT_NULL
);
1184 assert(port
->ip_receiver
== space
);
1187 * We clear ip_receiver_name and ip_receiver to simplify
1188 * the ipc_space_kernel check in ipc_mqueue_send.
1191 port
->ip_receiver_name
= MACH_PORT_NULL
;
1192 port
->ip_receiver
= IS_NULL
;
1194 /* relevant part of ipc_port_clear_receiver */
1195 ipc_port_set_mscount(port
, 0);
1196 port
->ip_messages
.imq_seqno
= 0;
1198 ipc_port_destroy(port
);
1204 * Keep a list of all allocated ports.
1205 * Allocation is intercepted via ipc_port_init;
1206 * deallocation is intercepted via io_free.
1208 queue_head_t port_alloc_queue
;
1209 decl_mutex_data(,port_alloc_queue_lock
)
1211 unsigned long port_count
= 0;
1212 unsigned long port_count_warning
= 20000;
1213 unsigned long port_timestamp
= 0;
1215 void db_port_stack_trace(
1220 unsigned int verbose
,
1221 unsigned int display
,
1222 unsigned int ref_search
,
1223 unsigned int ref_target
);
1226 * Initialize global state needed for run-time
1230 ipc_port_debug_init(void)
1232 queue_init(&port_alloc_queue
);
1233 mutex_init(&port_alloc_queue_lock
, ETAP_IPC_PORT_ALLOCQ
);
1238 * Initialize all of the debugging state in a port.
1239 * Insert the port into a global list of all allocated ports.
1242 ipc_port_init_debug(
1247 port
->ip_thread
= (unsigned long) current_thread();
1248 port
->ip_timetrack
= port_timestamp
++;
1249 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
)
1250 port
->ip_callstack
[i
] = 0;
1251 for (i
= 0; i
< IP_NSPARES
; ++i
)
1252 port
->ip_spares
[i
] = 0;
1255 * Machine-dependent routine to fill in an
1256 * array with up to IP_CALLSTACK_MAX levels
1257 * of return pc information.
1259 machine_callstack(&port
->ip_callstack
[0], IP_CALLSTACK_MAX
);
1262 mutex_lock(&port_alloc_queue_lock
);
1264 if (port_count_warning
> 0 && port_count
>= port_count_warning
)
1265 assert(port_count
< port_count_warning
);
1266 queue_enter(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1267 mutex_unlock(&port_alloc_queue_lock
);
1273 * Remove a port from the queue of allocated ports.
1274 * This routine should be invoked JUST prior to
1275 * deallocating the actual memory occupied by the port.
1278 ipc_port_track_dealloc(
1282 mutex_lock(&port_alloc_queue_lock
);
1283 assert(port_count
> 0);
1285 queue_remove(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
);
1286 mutex_unlock(&port_alloc_queue_lock
);
1290 #endif /* MACH_ASSERT */
1295 #include <ddb/db_output.h>
1296 #include <ddb/db_print.h>
1298 #define printf kdbprintf
1299 extern int db_indent
;
1302 db_port_queue_print(
1306 * ipc_entry_print - pretty-print an ipc_entry
1308 static void ipc_entry_print(struct ipc_entry
*, char *); /* forward */
1310 static void ipc_entry_print(struct ipc_entry
*iep
, char *tag
)
1312 ipc_entry_bits_t bits
= iep
->ie_bits
;
1314 iprintf("%s @", tag
);
1315 printf(" 0x%x, bits=%x object=%x\n", iep
, bits
, iep
->ie_object
);
1317 iprintf("urefs=%x ", IE_BITS_UREFS(bits
));
1318 printf("type=%x gen=%x\n", IE_BITS_TYPE(bits
), IE_BITS_GEN(bits
));
1323 * Routine: ipc_port_print
1325 * Pretty-print a port for kdb.
1327 int ipc_port_print_long
= 0; /* set for more detail */
1332 boolean_t have_addr
,
1336 extern int db_indent
;
1342 int i
, needs_db_indent
, items_printed
;
1343 #endif /* MACH_ASSERT */
1345 if (db_option(modif
, 'l') || db_option(modif
, 'v'))
1348 printf("port 0x%x\n", port
);
1352 ipc_object_print(&port
->ip_object
);
1354 if (ipc_port_print_long
) {
1355 iprintf("pool=0x%x", port
->ip_thread_pool
);
1359 if (!ip_active(port
)) {
1360 iprintf("timestamp=0x%x", port
->ip_timestamp
);
1361 } else if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1362 iprintf("destination=0x%x (", port
->ip_destination
);
1363 if (port
->ip_destination
!= MACH_PORT_NULL
&&
1364 (task
= db_task_from_space(port
->ip_destination
->
1365 ip_receiver
, &task_id
)))
1366 printf("task%d at 0x%x", task_id
, task
);
1371 iprintf("receiver=0x%x (", port
->ip_receiver
);
1372 if (port
->ip_receiver
== ipc_space_kernel
)
1374 else if (port
->ip_receiver
== ipc_space_reply
)
1376 else if (port
->ip_receiver
== default_pager_space
)
1377 printf("default_pager");
1378 else if (task
= db_task_from_space(port
->ip_receiver
, &task_id
))
1379 printf("task%d at 0x%x", task_id
, task
);
1384 printf(", receiver_name=0x%x\n", port
->ip_receiver_name
);
1386 iprintf("mscount=%d", port
->ip_mscount
);
1387 printf(", srights=%d", port
->ip_srights
);
1388 printf(", sorights=%d\n", port
->ip_sorights
);
1390 iprintf("nsrequest=0x%x", port
->ip_nsrequest
);
1391 printf(", pdrequest=0x%x", port
->ip_pdrequest
);
1392 printf(", dnrequests=0x%x\n", port
->ip_dnrequests
);
1394 iprintf("pset_count=0x%x", port
->ip_pset_count
);
1395 printf(", seqno=%d", port
->ip_messages
.imq_seqno
);
1396 printf(", msgcount=%d", port
->ip_messages
.imq_msgcount
);
1397 printf(", qlimit=%d\n", port
->ip_messages
.imq_qlimit
);
1399 iprintf("kmsgs=0x%x", port
->ip_messages
.imq_messages
.ikmq_base
);
1400 printf(", rcvrs queue=0x%x", port
->ip_messages
.imq_wait_queue
);
1401 printf(", kobj=0x%x\n", port
->ip_kobject
);
1403 iprintf("premsg=0x%x", port
->ip_premsg
);
1406 /* don't bother printing callstack or queue links */
1407 iprintf("ip_thread=0x%x, ip_timetrack=0x%x\n",
1408 port
->ip_thread
, port
->ip_timetrack
);
1410 needs_db_indent
= 1;
1411 for (i
= 0; i
< IP_NSPARES
; ++i
) {
1412 if (port
->ip_spares
[i
] != 0) {
1413 if (needs_db_indent
) {
1415 needs_db_indent
= 0;
1417 printf("%sip_spares[%d] = %d",
1418 items_printed
? ", " : "", i
,
1419 port
->ip_spares
[i
]);
1420 if (++items_printed
>= 4) {
1421 needs_db_indent
= 1;
1427 #endif /* MACH_ASSERT */
1430 iprintf("kmsg queue contents:\n");
1432 nmsgs
= db_port_queue_print(port
);
1434 iprintf("...total kmsgs: %d\n", nmsgs
);
1443 mach_port_name_t name
)
1448 if (task
== TASK_NULL
) {
1449 db_printf("port_name_to_data: task is null\n");
1452 if ((space
= task
->itk_space
) == 0) {
1453 db_printf("port_name_to_data: task->itk_space is null\n");
1456 if (!space
->is_active
) {
1457 db_printf("port_name_to_data: task->itk_space not active\n");
1460 if ((entry
= ipc_entry_lookup(space
, name
)) == 0) {
1461 db_printf("port_name_to_data: lookup yields zero\n");
1464 return ((ipc_port_t
)entry
->ie_object
);
1469 print_type_ports(type
, dead
)
1477 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1479 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1481 if (ip_kotype(port
) == type
&&
1482 (!dead
|| !ip_active(port
))) {
1484 printf("0x%x\t", port
);
1486 printf("0x%x\n", port
);
1496 int total_port_count
;
1497 int space_null_count
;
1498 int space_kernel_count
;
1499 int space_reply_count
;
1500 int space_pager_count
;
1501 int space_other_count
;
1506 } port_types
[IKOT_MAX_TYPE
];
1508 total_port_count
= 0;
1510 bzero((char *)&port_types
[0], sizeof(port_types
));
1511 space_null_count
= 0;
1512 space_kernel_count
= 0;
1513 space_reply_count
= 0;
1514 space_pager_count
= 0;
1515 space_other_count
= 0;
1517 for (port
= (ipc_port_t
)first_element(ipc_object_zones
[IOT_PORT
]);
1519 port
= (ipc_port_t
)next_element(ipc_object_zones
[IOT_PORT
],
1520 (vm_offset_t
)port
)) {
1522 if (ip_kotype(port
) >= IKOT_MAX_TYPE
) {
1523 port_types
[IKOT_UNKNOWN
].total_count
++;
1524 if (!io_active(&port
->ip_object
))
1525 port_types
[IKOT_UNKNOWN
].dead_count
++;
1527 port_types
[ip_kotype(port
)].total_count
++;
1528 if (!io_active(&port
->ip_object
))
1529 port_types
[ip_kotype(port
)].dead_count
++;
1532 if (!port
->ip_receiver
)
1534 else if (port
->ip_receiver
== ipc_space_kernel
)
1535 space_kernel_count
++;
1536 else if (port
->ip_receiver
== ipc_space_reply
)
1537 space_reply_count
++;
1538 else if (port
->ip_receiver
== default_pager_space
)
1539 space_pager_count
++;
1541 space_other_count
++;
1543 printf("\n%7d total ports\n\n", total_port_count
);
1545 #define PRINT_ONE_PORT_TYPE(name) \
1546 printf("%7d %s", port_types[IKOT_##name].total_count, # name); \
1547 if (port_types[IKOT_##name].dead_count) \
1548 printf(" (%d dead ports)", port_types[IKOT_##name].dead_count);\
1551 PRINT_ONE_PORT_TYPE(NONE
);
1552 PRINT_ONE_PORT_TYPE(THREAD
);
1553 PRINT_ONE_PORT_TYPE(TASK
);
1554 PRINT_ONE_PORT_TYPE(HOST
);
1555 PRINT_ONE_PORT_TYPE(HOST_PRIV
);
1556 PRINT_ONE_PORT_TYPE(PROCESSOR
);
1557 PRINT_ONE_PORT_TYPE(PSET
);
1558 PRINT_ONE_PORT_TYPE(PSET_NAME
);
1559 PRINT_ONE_PORT_TYPE(PAGING_REQUEST
);
1560 PRINT_ONE_PORT_TYPE(MEMORY_OBJECT
);
1561 PRINT_ONE_PORT_TYPE(MIG
);
1562 PRINT_ONE_PORT_TYPE(XMM_PAGER
);
1563 PRINT_ONE_PORT_TYPE(XMM_KERNEL
);
1564 PRINT_ONE_PORT_TYPE(XMM_REPLY
);
1565 PRINT_ONE_PORT_TYPE(CLOCK
);
1566 PRINT_ONE_PORT_TYPE(CLOCK_CTRL
);
1567 PRINT_ONE_PORT_TYPE(MASTER_DEVICE
);
1568 PRINT_ONE_PORT_TYPE(UNKNOWN
);
1569 printf("\nipc_space:\n\n");
1570 printf("NULL KERNEL REPLY PAGER OTHER\n");
1571 printf("%d %d %d %d %d\n",
1580 #endif /* ZONE_DEBUG */
1584 * Print out all the kmsgs in a queue. Aggregate kmsgs with
1585 * identical message ids into a single entry. Count up the
1586 * amount of inline and out-of-line data consumed by each
1591 #define KMSG_MATCH_FIELD(kmsg) ((unsigned int) kmsg->ikm_header.msgh_id)
1592 #define DKQP_LONG(kmsg) FALSE
1593 char *dkqp_long_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1594 char *dkqp_format
= "(%3d) <%10d> 0x%x %10d %10d\n";
1597 db_kmsg_queue_print(
1600 db_kmsg_queue_print(
1603 ipc_kmsg_t ikmsg
, first_kmsg
;
1604 register int icount
;
1605 mach_msg_id_t cur_id
;
1606 unsigned int inline_total
, ool_total
;
1609 iprintf("Count msgh_id kmsg addr inline bytes ool bytes\n");
1610 inline_total
= ool_total
= (vm_size_t
) 0;
1611 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1612 for (icount
= 0, nmsgs
= 0, first_kmsg
= ikmsg
= kmsg
;
1613 kmsg
!= IKM_NULL
&& (kmsg
!= first_kmsg
|| nmsgs
== 0);
1614 kmsg
= kmsg
->ikm_next
) {
1616 if (!(KMSG_MATCH_FIELD(kmsg
) == cur_id
)) {
1617 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
:dkqp_format
,
1618 icount
, cur_id
, ikmsg
, inline_total
,ool_total
);
1619 cur_id
= KMSG_MATCH_FIELD(kmsg
);
1622 inline_total
= ool_total
= 0;
1626 if (DKQP_LONG(kmsg
))
1627 inline_total
+= kmsg
->ikm_size
;
1629 inline_total
+= kmsg
->ikm_header
.msgh_size
;
1631 iprintf(DKQP_LONG(kmsg
) ? dkqp_long_format
: dkqp_format
,
1632 icount
, cur_id
, ikmsg
, inline_total
, ool_total
);
1638 * Process all of the messages on a port - prints out the
1639 * number of occurences of each message type, and the first
1640 * kmsg with a particular msgh_id.
1643 db_port_queue_print(
1648 if (ipc_kmsg_queue_empty(&port
->ip_messages
.imq_messages
))
1650 kmsg
= ipc_kmsg_queue_first(&port
->ip_messages
.imq_messages
);
1651 return db_kmsg_queue_print(kmsg
);
1656 #include <ddb/db_sym.h>
1657 #include <ddb/db_access.h>
1659 #define FUNC_NULL ((void (*)) 0)
1660 #define MAX_REFS 5 /* bins for tracking ref counts */
1663 * Translate port's cache of call stack pointers
1664 * into symbolic names.
1667 db_port_stack_trace(
1672 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1673 iprintf("[%d] 0x%x\t", i
, port
->ip_callstack
[i
]);
1674 if (port
->ip_callstack
[i
] != 0 &&
1675 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1676 db_printsym(port
->ip_callstack
[i
], DB_STGY_PROC
);
1682 typedef struct port_item
{
1684 unsigned long count
;
1688 #define ITEM_MAX 400
1689 typedef struct port_track
{
1692 unsigned long warning
;
1693 port_item items
[ITEM_MAX
];
1696 port_track port_callers
; /* match against calling addresses */
1697 port_track port_threads
; /* match against allocating threads */
1698 port_track port_spaces
; /* match against ipc spaces */
1700 void port_track_init(
1705 unsigned long item
);
1706 void port_track_sort(
1707 port_track
*trackp
);
1708 void port_track_print(
1710 void (*func
)(port_item
*));
1711 void port_callers_print(
1721 trackp
->max
= trackp
->warning
= 0;
1722 trackp
->name
= name
;
1723 for (i
= trackp
->items
; i
< trackp
->items
+ ITEM_MAX
; ++i
)
1724 i
->item
= i
->count
= 0;
1733 port_item
*limit
, *i
;
1735 limit
= trackp
->items
+ trackp
->max
;
1736 for (i
= trackp
->items
; i
< limit
; ++i
)
1737 if (i
->item
== item
) {
1741 if (trackp
->max
>= ITEM_MAX
) {
1742 if (trackp
->warning
++ == 0)
1743 iprintf("%s: no room\n", trackp
->name
);
1753 * Simple (and slow) bubble sort.
1759 port_item
*limit
, *p
;
1763 limit
= trackp
->items
+ trackp
->max
- 1;
1766 for (p
= trackp
->items
; p
< limit
- 1; ++p
) {
1767 if (p
->count
< (p
+1)->count
) {
1774 } while (unsorted
== TRUE
);
1781 void (*func
)(port_item
*))
1783 port_item
*limit
, *p
;
1785 limit
= trackp
->items
+ trackp
->max
;
1786 iprintf("%s:\n", trackp
->name
);
1787 for (p
= trackp
->items
; p
< limit
; ++p
) {
1788 if (func
!= FUNC_NULL
)
1791 iprintf("0x%x\t%8d\n", p
->item
, p
->count
);
1800 iprintf("0x%x\t%8d\t", p
->item
, p
->count
);
1801 db_printsym(p
->item
, DB_STGY_PROC
);
1807 * Show all ports with a given reference count.
1813 db_port_walk(1, 1, 1, refs
);
1818 * Examine all currently allocated ports.
1820 * verbose display suspicious ports
1821 * display print out each port encountered
1822 * ref_search restrict examination to ports with
1823 * a specified reference count
1824 * ref_target reference count for ref_search
1828 unsigned int verbose
,
1829 unsigned int display
,
1830 unsigned int ref_search
,
1831 unsigned int ref_target
)
1834 unsigned int ref_overflow
, refs
, i
, ref_inactive_overflow
;
1835 unsigned int no_receiver
, no_match
;
1836 unsigned int ref_counts
[MAX_REFS
];
1837 unsigned int inactive
[MAX_REFS
];
1838 unsigned int ipc_ports
= 0;
1839 unsigned int proxies
= 0, principals
= 0;
1841 iprintf("Allocated port count is %d\n", port_count
);
1842 no_receiver
= no_match
= ref_overflow
= 0;
1843 ref_inactive_overflow
= 0;
1844 for (i
= 0; i
< MAX_REFS
; ++i
) {
1848 port_track_init(&port_callers
, "port callers");
1849 port_track_init(&port_threads
, "port threads");
1850 port_track_init(&port_spaces
, "port spaces");
1852 iprintf("Walking ports of ref_count=%d.\n", ref_target
);
1854 iprintf("Walking all ports.\n");
1856 queue_iterate(&port_alloc_queue
, port
, ipc_port_t
, ip_port_links
) {
1859 port_type
= " IPC port";
1860 if (ip_active(port
))
1863 refs
= port
->ip_references
;
1864 if (ref_search
&& refs
!= ref_target
)
1867 if (refs
>= MAX_REFS
) {
1868 if (ip_active(port
))
1871 ++ref_inactive_overflow
;
1873 if (refs
== 0 && verbose
)
1874 iprintf("%s 0x%x has ref count of zero!\n",
1876 if (ip_active(port
))
1881 port_item_add(&port_threads
, (unsigned long) port
->ip_thread
);
1882 for (i
= 0; i
< IP_CALLSTACK_MAX
; ++i
) {
1883 if (port
->ip_callstack
[i
] != 0 &&
1884 DB_VALID_KERN_ADDR(port
->ip_callstack
[i
]))
1885 port_item_add(&port_callers
,
1886 port
->ip_callstack
[i
]);
1888 if (!ip_active(port
)) {
1890 iprintf("%s 0x%x, inactive, refcnt %d\n",
1891 port_type
, port
, refs
);
1895 if (port
->ip_receiver_name
== MACH_PORT_NULL
) {
1896 iprintf("%s 0x%x, no receiver, refcnt %d\n",
1901 if (port
->ip_receiver
== ipc_space_kernel
||
1902 port
->ip_receiver
== ipc_space_reply
||
1903 ipc_entry_lookup(port
->ip_receiver
,
1904 port
->ip_receiver_name
)
1906 port_item_add(&port_spaces
,
1907 (unsigned long)port
->ip_receiver
);
1909 iprintf( "%s 0x%x time 0x%x ref_cnt %d\n",
1911 port
->ip_timetrack
, refs
);
1915 iprintf("%s 0x%x, rcvr 0x%x, name 0x%x, ref %d, no match\n",
1916 port_type
, port
, port
->ip_receiver
,
1917 port
->ip_receiver_name
, refs
);
1920 iprintf("Active port type summary:\n");
1921 iprintf("\tlocal IPC %6d\n", ipc_ports
);
1922 iprintf("summary:\tcallers %d threads %d spaces %d\n",
1923 port_callers
.max
, port_threads
.max
, port_spaces
.max
);
1925 iprintf("\tref_counts:\n");
1926 for (i
= 0; i
< MAX_REFS
; ++i
)
1927 iprintf("\t ref_counts[%d] = %d\n", i
, ref_counts
[i
]);
1929 iprintf("\t%d ports w/o receivers, %d w/o matches\n",
1930 no_receiver
, no_match
);
1932 iprintf("\tinactives:");
1933 if ( ref_inactive_overflow
|| inactive
[0] || inactive
[1] ||
1934 inactive
[2] || inactive
[3] || inactive
[4] )
1935 printf(" [0]=%d [1]=%d [2]=%d [3]=%d [4]=%d [5+]=%d\n",
1936 inactive
[0], inactive
[1], inactive
[2],
1937 inactive
[3], inactive
[4], ref_inactive_overflow
);
1939 printf(" No inactive ports.\n");
1941 port_track_sort(&port_spaces
);
1942 port_track_print(&port_spaces
, FUNC_NULL
);
1943 port_track_sort(&port_threads
);
1944 port_track_print(&port_threads
, FUNC_NULL
);
1945 port_track_sort(&port_callers
);
1946 port_track_print(&port_callers
, port_callers_print
);
1951 #endif /* MACH_ASSERT */
1953 #endif /* MACH_KDB */