1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 *
31 */
32
33/*
34 * Really a C file, but I'd like to have this code available in both
35 * the kernel and the application, so I'll put it in a .h file.  This
36 * file needs to be included only once in the AIL or ME, into a .c file
37 * where it will be compiled.
38 */
39
40/*
41 * Since these are debug functions, it doesn't matter which processor macro
42 * version I use; I don't mind spoiling cache while I'm debugging.
43 */
44
45#include <mach/flipc_cb.h>
46/*
47 * Print (using printf) all buffers in the communications buffer that
48 * are not on any endpoint or on the buffer freelist.  Only active
49 * endpoints are checked.
50 *
51 * Note that no locking is done; this function implicitly assumes the
52 * communications buffer is in a quiescent state.  It is expected that
53 * this function will normally be called from a debugger.
54 *
55 * As long as it is at it, this function prints buffers that are
56 * doubly owned (valid pointers to them from two places).
57 */
58
59/*
60 * Given that these functions will normally be called from the debugger,
61 * there isn't any need to globally visible prototypes for them.  To
62 * eliminate compilation warnings, we include prototypes for the functions
63 * here in the file.
64 */
65static void flipcdbg_update_bufferset_bitvec(flipc_comm_buffer_ctl_t,
66					     flipc_data_buffer_t);
67void flipcdbg_print_unowned_buffers(void);
68void flipcdbg_buffer_find_refs(flipc_cb_ptr buffer_cbptr);
69
70#ifdef __GNUC__
71__inline__
72#endif
73static void
74flipcdbg_update_bufferset_bitvec(flipc_comm_buffer_ctl_t cb_ctl,
75				 flipc_data_buffer_t buffer)
76{
77    unsigned char *buffer_base = flipc_cb_base + cb_ctl->data_buffer.start;
78    int bitpos = ((((unsigned char *) buffer) - buffer_base)
79		  / cb_ctl->data_buffer_size);
80    int element = bitpos / (sizeof(unsigned long) * 8);
81    int subbitpos = bitpos - element * sizeof(unsigned long) * 8;
82
83    /* Is that position set already?  */
84    if (flipc_debug_buffer_bitvec[element] & (1 << subbitpos))
85	printf("Buffer 0x%x (idx: %d, cbptr: 0x%x) is multiply referenced.\n",
86	       buffer, bitpos, FLIPC_CBPTR(buffer));
87
88    /* Set it.  */
89    flipc_debug_buffer_bitvec[element] |= (1 << subbitpos);
90}
91
92void
93flipcdbg_print_unowned_buffers(void)
94{
95    flipc_comm_buffer_ctl_t cb_ctl =
96	(flipc_comm_buffer_ctl_t) flipc_cb_base;
97    int i;
98    unsigned long bitvec_length = ((cb_ctl->data_buffer.number + sizeof(unsigned long) * 8)
99			    / (sizeof(unsigned int) * 8));
100    flipc_data_buffer_t current_buffer;
101    flipc_endpoint_t current_endpoint;
102    flipc_cb_ptr current_cbptr;
103    int header_printed = 0;
104
105    /* Clean out the bitvec.  */
106    for (i = 0; i < bitvec_length; i++)
107	flipc_debug_buffer_bitvec[i] = 0;
108
109    /* Go through the freelist, setting bits for each buffer.  */
110    for (current_cbptr = cb_ctl->data_buffer.free;
111	 current_cbptr != FLIPC_CBPTR_NULL;
112	 current_cbptr = current_buffer->u.free) {
113	int bitpos;
114	int element, subbitpos;
115
116	current_buffer = FLIPC_DATA_BUFFER_PTR(current_cbptr);
117	flipcdbg_update_bufferset_bitvec(cb_ctl, current_buffer);
118    }
119
120    /* Go through all the endpoints, again setting bits for each buffer.  */
121    for (current_endpoint = FLIPC_ENDPOINT_PTR(cb_ctl->endpoint.start);
122	 (current_endpoint
123	  < (FLIPC_ENDPOINT_PTR(cb_ctl->endpoint.start)
124	     + cb_ctl->endpoint.number));
125	 current_endpoint++) {
126	if (EXTRACT_ENABLED(current_endpoint->saildm_dpb_or_enabled)) {
127	    flipc_cb_ptr current_ptr =
128		(EXTRACT_DPB(current_endpoint->saildm_dpb_or_enabled)
129		 ? current_endpoint->sme_process_ptr
130		 : current_endpoint->shrd_acquire_ptr);
131	    flipc_cb_ptr limit_ptr = current_endpoint->sail_release_ptr;
132
133	    while (current_ptr != limit_ptr) {
134		flipc_cb_ptr current_buffer_cbptr =
135		    *FLIPC_BUFFERLIST_PTR(current_ptr);
136		flipc_data_buffer_t current_buffer =
137		    FLIPC_DATA_BUFFER_PTR(current_buffer_cbptr);
138
139		/* Mark this as set.  */
140		flipcdbg_update_bufferset_bitvec(cb_ctl, current_buffer);
141
142		/* Increment the current pointer.  */
143		current_ptr = NEXT_BUFFERLIST_PTR_ME(current_ptr,
144						     current_endpoint);
145	    }
146	}
147    }
148
149    /* Ok, we should have marked every buffer that has a reference.
150       Print out all the ones that done have references.  */
151    for (i = 0; i < bitvec_length; i++) {
152	int this_limit =
153	    ((i == bitvec_length - 1)
154	     ? cb_ctl->data_buffer.number % (sizeof(unsigned long)*8)
155	     : sizeof(unsigned long)*8);
156	if (flipc_debug_buffer_bitvec[i] != (unsigned long) -1) {
157	    int j;
158	    for (j = 0; j < this_limit; j++) {
159		if (!(flipc_debug_buffer_bitvec[i] & (1 << j))) {
160		    int buffer_bitpos = i * sizeof(unsigned long) * 8 + j;
161		    flipc_cb_ptr buffer_cbptr =
162			(buffer_bitpos * cb_ctl->data_buffer_size
163			 + cb_ctl->data_buffer.start);
164		    flipc_data_buffer_t buffer_ptr =
165			FLIPC_DATA_BUFFER_PTR(buffer_cbptr);
166
167		    /* Print header if necessary.  */
168		    if (!header_printed) {
169			header_printed = 1;
170			printf("Unreferenced buffers (ptr,idx,cbptr):");
171		    }
172
173		    /* Print buffer.  */
174		    printf(" (0x%x,%d,0x%x)", buffer_ptr, buffer_bitpos,
175			   buffer_cbptr);
176		}
177	    }
178	}
179    }
180    if (header_printed)
181	printf("\n");
182}
183
184void
185flipcdbg_buffer_find_refs(flipc_cb_ptr buffer_cbptr)
186{
187    flipc_comm_buffer_ctl_t cb_ctl =
188	(flipc_comm_buffer_ctl_t) flipc_cb_base;
189    int found_on_freelist = 0;
190    int found_on_endpoints = 0;
191    int i;
192    flipc_endpoint_t current_endpoint;
193
194    flipc_cb_ptr current_cbptr;
195    flipc_data_buffer_t current_buffer;
196
197    /* Go through the freelist, looking for buffer.  */
198    for (i = 0, current_cbptr = cb_ctl->data_buffer.free;
199	 current_cbptr != FLIPC_CBPTR_NULL;
200	 i++, current_cbptr = current_buffer->u.free) {
201	if (current_cbptr == buffer_cbptr) {
202	    printf("Buffer found on freelist in position %d\n", i);
203	    found_on_freelist = 1;
204	}
205	current_buffer = FLIPC_DATA_BUFFER_PTR(current_cbptr);
206	if (i > cb_ctl->data_buffer.number) {
207	    printf ("**Some form of corruption following freelist.**");
208	    return;
209	}
210    }
211    if (found_on_freelist)
212	printf("(Total buffers on freelist: %d/%d)\n", i,
213	       cb_ctl->data_buffer.number);
214
215    /* Go through all the endpoints, again looking for the buffer.  */
216    for (current_endpoint = FLIPC_ENDPOINT_PTR(cb_ctl->endpoint.start);
217	 (current_endpoint
218	  < (FLIPC_ENDPOINT_PTR(cb_ctl->endpoint.start)
219	     + cb_ctl->endpoint.number));
220	 current_endpoint++) {
221	if (EXTRACT_ENABLED(current_endpoint->saildm_dpb_or_enabled)) {
222	    flipc_cb_ptr current_ptr =
223		(EXTRACT_DPB(current_endpoint->saildm_dpb_or_enabled)
224		 ? current_endpoint->sme_process_ptr
225		 : current_endpoint->shrd_acquire_ptr);
226	    flipc_cb_ptr limit_ptr = current_endpoint->sail_release_ptr;
227
228	    while (current_ptr != limit_ptr) {
229		current_cbptr = *FLIPC_BUFFERLIST_PTR(current_ptr);
230
231		if (current_cbptr == buffer_cbptr) {
232		    printf("Buffer found on endpoint 0x%x (idx: %d)\n",
233			   current_endpoint,
234			   (current_endpoint
235			    - FLIPC_ENDPOINT_PTR(cb_ctl->endpoint.start)));
236		    found_on_endpoints = 1;
237		}
238
239		/* Increment the current pointer.  */
240		current_ptr = NEXT_BUFFERLIST_PTR_ME(current_ptr,
241						     current_endpoint);
242	    }
243	}
244    }
245}
246
247
248
249