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