2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
31 * Really a C file, but I'd like to have this code available in both
32 * the kernel and the application, so I'll put it in a .h file. This
33 * file needs to be included only once in the AIL or ME, into a .c file
34 * where it will be compiled.
38 * Since these are debug functions, it doesn't matter which processor macro
39 * version I use; I don't mind spoiling cache while I'm debugging.
42 #include <mach/flipc_cb.h>
44 * Print (using printf) all buffers in the communications buffer that
45 * are not on any endpoint or on the buffer freelist. Only active
46 * endpoints are checked.
48 * Note that no locking is done; this function implicitly assumes the
49 * communications buffer is in a quiescent state. It is expected that
50 * this function will normally be called from a debugger.
52 * As long as it is at it, this function prints buffers that are
53 * doubly owned (valid pointers to them from two places).
57 * Given that these functions will normally be called from the debugger,
58 * there isn't any need to globally visible prototypes for them. To
59 * eliminate compilation warnings, we include prototypes for the functions
62 static void flipcdbg_update_bufferset_bitvec(flipc_comm_buffer_ctl_t
,
64 void flipcdbg_print_unowned_buffers(void);
65 void flipcdbg_buffer_find_refs(flipc_cb_ptr buffer_cbptr
);
71 flipcdbg_update_bufferset_bitvec(flipc_comm_buffer_ctl_t cb_ctl
,
72 flipc_data_buffer_t buffer
)
74 unsigned char *buffer_base
= flipc_cb_base
+ cb_ctl
->data_buffer
.start
;
75 int bitpos
= ((((unsigned char *) buffer
) - buffer_base
)
76 / cb_ctl
->data_buffer_size
);
77 int element
= bitpos
/ (sizeof(unsigned long) * 8);
78 int subbitpos
= bitpos
- element
* sizeof(unsigned long) * 8;
80 /* Is that position set already? */
81 if (flipc_debug_buffer_bitvec
[element
] & (1 << subbitpos
))
82 printf("Buffer 0x%x (idx: %d, cbptr: 0x%x) is multiply referenced.\n",
83 buffer
, bitpos
, FLIPC_CBPTR(buffer
));
86 flipc_debug_buffer_bitvec
[element
] |= (1 << subbitpos
);
90 flipcdbg_print_unowned_buffers(void)
92 flipc_comm_buffer_ctl_t cb_ctl
=
93 (flipc_comm_buffer_ctl_t
) flipc_cb_base
;
95 unsigned long bitvec_length
= ((cb_ctl
->data_buffer
.number
+ sizeof(unsigned long) * 8)
96 / (sizeof(unsigned int) * 8));
97 flipc_data_buffer_t current_buffer
;
98 flipc_endpoint_t current_endpoint
;
99 flipc_cb_ptr current_cbptr
;
100 int header_printed
= 0;
102 /* Clean out the bitvec. */
103 for (i
= 0; i
< bitvec_length
; i
++)
104 flipc_debug_buffer_bitvec
[i
] = 0;
106 /* Go through the freelist, setting bits for each buffer. */
107 for (current_cbptr
= cb_ctl
->data_buffer
.free
;
108 current_cbptr
!= FLIPC_CBPTR_NULL
;
109 current_cbptr
= current_buffer
->u
.free
) {
111 int element
, subbitpos
;
113 current_buffer
= FLIPC_DATA_BUFFER_PTR(current_cbptr
);
114 flipcdbg_update_bufferset_bitvec(cb_ctl
, current_buffer
);
117 /* Go through all the endpoints, again setting bits for each buffer. */
118 for (current_endpoint
= FLIPC_ENDPOINT_PTR(cb_ctl
->endpoint
.start
);
120 < (FLIPC_ENDPOINT_PTR(cb_ctl
->endpoint
.start
)
121 + cb_ctl
->endpoint
.number
));
122 current_endpoint
++) {
123 if (EXTRACT_ENABLED(current_endpoint
->saildm_dpb_or_enabled
)) {
124 flipc_cb_ptr current_ptr
=
125 (EXTRACT_DPB(current_endpoint
->saildm_dpb_or_enabled
)
126 ? current_endpoint
->sme_process_ptr
127 : current_endpoint
->shrd_acquire_ptr
);
128 flipc_cb_ptr limit_ptr
= current_endpoint
->sail_release_ptr
;
130 while (current_ptr
!= limit_ptr
) {
131 flipc_cb_ptr current_buffer_cbptr
=
132 *FLIPC_BUFFERLIST_PTR(current_ptr
);
133 flipc_data_buffer_t current_buffer
=
134 FLIPC_DATA_BUFFER_PTR(current_buffer_cbptr
);
136 /* Mark this as set. */
137 flipcdbg_update_bufferset_bitvec(cb_ctl
, current_buffer
);
139 /* Increment the current pointer. */
140 current_ptr
= NEXT_BUFFERLIST_PTR_ME(current_ptr
,
146 /* Ok, we should have marked every buffer that has a reference.
147 Print out all the ones that done have references. */
148 for (i
= 0; i
< bitvec_length
; i
++) {
150 ((i
== bitvec_length
- 1)
151 ? cb_ctl
->data_buffer
.number
% (sizeof(unsigned long)*8)
152 : sizeof(unsigned long)*8);
153 if (flipc_debug_buffer_bitvec
[i
] != (unsigned long) -1) {
155 for (j
= 0; j
< this_limit
; j
++) {
156 if (!(flipc_debug_buffer_bitvec
[i
] & (1 << j
))) {
157 int buffer_bitpos
= i
* sizeof(unsigned long) * 8 + j
;
158 flipc_cb_ptr buffer_cbptr
=
159 (buffer_bitpos
* cb_ctl
->data_buffer_size
160 + cb_ctl
->data_buffer
.start
);
161 flipc_data_buffer_t buffer_ptr
=
162 FLIPC_DATA_BUFFER_PTR(buffer_cbptr
);
164 /* Print header if necessary. */
165 if (!header_printed
) {
167 printf("Unreferenced buffers (ptr,idx,cbptr):");
171 printf(" (0x%x,%d,0x%x)", buffer_ptr
, buffer_bitpos
,
182 flipcdbg_buffer_find_refs(flipc_cb_ptr buffer_cbptr
)
184 flipc_comm_buffer_ctl_t cb_ctl
=
185 (flipc_comm_buffer_ctl_t
) flipc_cb_base
;
186 int found_on_freelist
= 0;
187 int found_on_endpoints
= 0;
189 flipc_endpoint_t current_endpoint
;
191 flipc_cb_ptr current_cbptr
;
192 flipc_data_buffer_t current_buffer
;
194 /* Go through the freelist, looking for buffer. */
195 for (i
= 0, current_cbptr
= cb_ctl
->data_buffer
.free
;
196 current_cbptr
!= FLIPC_CBPTR_NULL
;
197 i
++, current_cbptr
= current_buffer
->u
.free
) {
198 if (current_cbptr
== buffer_cbptr
) {
199 printf("Buffer found on freelist in position %d\n", i
);
200 found_on_freelist
= 1;
202 current_buffer
= FLIPC_DATA_BUFFER_PTR(current_cbptr
);
203 if (i
> cb_ctl
->data_buffer
.number
) {
204 printf ("**Some form of corruption following freelist.**");
208 if (found_on_freelist
)
209 printf("(Total buffers on freelist: %d/%d)\n", i
,
210 cb_ctl
->data_buffer
.number
);
212 /* Go through all the endpoints, again looking for the buffer. */
213 for (current_endpoint
= FLIPC_ENDPOINT_PTR(cb_ctl
->endpoint
.start
);
215 < (FLIPC_ENDPOINT_PTR(cb_ctl
->endpoint
.start
)
216 + cb_ctl
->endpoint
.number
));
217 current_endpoint
++) {
218 if (EXTRACT_ENABLED(current_endpoint
->saildm_dpb_or_enabled
)) {
219 flipc_cb_ptr current_ptr
=
220 (EXTRACT_DPB(current_endpoint
->saildm_dpb_or_enabled
)
221 ? current_endpoint
->sme_process_ptr
222 : current_endpoint
->shrd_acquire_ptr
);
223 flipc_cb_ptr limit_ptr
= current_endpoint
->sail_release_ptr
;
225 while (current_ptr
!= limit_ptr
) {
226 current_cbptr
= *FLIPC_BUFFERLIST_PTR(current_ptr
);
228 if (current_cbptr
== buffer_cbptr
) {
229 printf("Buffer found on endpoint 0x%x (idx: %d)\n",
232 - FLIPC_ENDPOINT_PTR(cb_ctl
->endpoint
.start
)));
233 found_on_endpoints
= 1;
236 /* Increment the current pointer. */
237 current_ptr
= NEXT_BUFFERLIST_PTR_ME(current_ptr
,