1 /* 2 * tracebuf.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * Benchmark tracing utility 36 */ 37 38 #include "osApi.h" 39 #include "tracebuf.h" 40 #include "tracebuf_api.h" 41 #include "report.h" 42 43 typedef struct { 44 unsigned long loc;/* trace entry identification */ 45 unsigned long ts;/* Timestamp */ 46 unsigned long p1; /* Parameter 1 */ 47 unsigned long p2; /* Parameter 2 */ 48 char msg[MAX_TB_MSG]; 49 } tb_entry_t; 50 51 typedef struct { 52 int pos; 53 int count; 54 int print_pos; 55 int nusers; 56 unsigned long self_delay; 57 unsigned long options; 58 tb_entry_t entry[1]; /* Array of entries */ 59 } tb_control_t; 60 61 static tb_control_t *tb_control; 62 63 static int tb_control_size(void) 64 { 65 return TI_FIELD_OFFSET(tb_control_t, entry) + sizeof(tb_entry_t)*TB_NUM_ENTRIES; 66 } 67 68 69 /* Initialization */ 70 int tb_init(unsigned long options) 71 { 72 if (tb_control) 73 { 74 ++tb_control->nusers; 75 return 0; 76 } 77 tb_control = (tb_control_t *)TB_MALLOC(tb_control_size()); 78 if (!tb_control) 79 return -1; 80 memset(tb_control, 0, tb_control_size()); 81 tb_control->nusers = 1; 82 83 /* Measure self-delay */ 84 tb_trace(0, 0, 0); 85 tb_trace(0, 0, 0); 86 tb_control->self_delay = tb_control->entry[1].ts - tb_control->entry[0].ts; 87 tb_control->pos = tb_control->count = 0; 88 tb_control->options = options; 89 return 0; 90 } 91 92 /* De-initialization */ 93 void tb_destroy(void) 94 { 95 if (--tb_control->nusers) 96 return; 97 TB_FREE(tb_control ); 98 } 99 100 static int tb_next(void) 101 { 102 int pos; 103 if (!tb_control || tb_control->print_pos) 104 return -1; 105 pos = tb_control->pos; 106 tb_control->pos = (pos+1) % TB_NUM_ENTRIES; 107 ++tb_control->count; 108 109 tb_control->entry[tb_control->pos].ts = 110 tb_control->entry[tb_control->pos].loc= 111 tb_control->entry[tb_control->pos].p1 = 112 tb_control->entry[tb_control->pos].p2 = 0xffffffff; 113 114 return pos; 115 } 116 static void tb_autoprint(void) 117 { 118 if ((tb_control->pos == 0) && (tb_control->count)) 119 { 120 if (tb_control->options & TB_OPTION_PRINTONCE) 121 { 122 tb_printf(); 123 tb_reset_option(TB_OPTION_PRINTONCE); 124 } 125 else if (tb_control->options & TB_OPTION_AUTOPRINT) 126 { 127 tb_printf(); 128 } 129 } 130 } 131 132 /* Add trace entry. not safe, but will do */ 133 int tb_trace(int loc, unsigned long p1, unsigned long p2) 134 { 135 int pos; 136 137 if ((tb_control->options & TB_OPTION_STOP) || ((pos = tb_next()) < 0)) 138 { 139 return -1; 140 } 141 tb_control->entry[pos].ts = os_timeStampUs(NULL); 142 tb_control->entry[pos].loc= loc; 143 tb_control->entry[pos].p1 = p1; 144 tb_control->entry[pos].p2 = p2; 145 146 return pos; 147 } 148 void tb_dump(void) 149 { 150 int j, pos; 151 152 WLAN_OS_REPORT(("Trace Dump:\n")); 153 WLAN_OS_REPORT(("===========\n\n")); 154 if (tb_control->count < TB_NUM_ENTRIES) 155 { 156 pos = 0; 157 } 158 else 159 { 160 pos = (tb_control->pos + 1) % TB_NUM_ENTRIES; 161 } 162 for (j=0; (unsigned int)j < tb_min((unsigned int)TB_NUM_ENTRIES,(unsigned int)tb_control->count); j++) 163 { 164 WLAN_OS_REPORT(("%4i %08x %08x %08x %08x\n", j, 165 (int)tb_control->entry[pos].ts, 166 (int)tb_control->entry[pos].loc, 167 (int)tb_control->entry[pos].p1, 168 (int)tb_control->entry[pos].p2)); 169 pos = (pos+1) % TB_NUM_ENTRIES; 170 } 171 172 } 173 174 int tb_sprintf(const char *format ,...) 175 { 176 177 va_list ap; 178 int pos; 179 180 if ((tb_control->options & TB_OPTION_STOP) || ((pos = tb_next()) < 0)) 181 { 182 return -1; 183 } 184 tb_control->entry[pos].loc = TB_ID; 185 va_start(ap,format); 186 vsprintf(&tb_control->entry[pos].msg[0], format, ap); 187 tb_autoprint(); 188 return pos; 189 } 190 191 void tb_printf(void) 192 { 193 int j, pos; 194 unsigned long saved_options=tb_control->options; 195 196 tb_set_option(TB_OPTION_STOP); 197 WLAN_OS_REPORT(("Trace Dump:\n")); 198 WLAN_OS_REPORT(("===========\n\n")); 199 if (tb_control->count < TB_NUM_ENTRIES) 200 { 201 pos = 0; 202 } 203 else 204 { 205 pos = (tb_control->pos + 1) % TB_NUM_ENTRIES; 206 } 207 for (j=0; (unsigned int)j < tb_min((unsigned int)TB_NUM_ENTRIES,(unsigned int)tb_control->count); j++) 208 { 209 WLAN_OS_REPORT(("%4i id=0x%8x %s \n", j, 210 tb_control->entry[pos].loc, tb_control->entry[pos].msg)); 211 pos = (pos+1) % TB_NUM_ENTRIES; 212 } 213 tb_control->options = saved_options; 214 } 215 void tb_set_option(unsigned long option) 216 { 217 tb_control->options |= option; 218 } 219 220 void tb_reset_option(unsigned long option) 221 { 222 tb_control->options &= ~option; 223 } 224 225 void tb_scan(void) 226 { 227 228 int j,k, Size, nAllocs=0, nFrees=0; 229 unsigned long address, Allocs=0, Frees=0; 230 231 for (j=0; j < TB_NUM_ENTRIES; j++) 232 { 233 Size = (int)tb_control->entry[j].p2; 234 if (Size > 0) /* Alloc */ 235 { 236 nAllocs += 1; 237 Allocs += Size; 238 address = tb_control->entry[j].p1; 239 for (k=j+1; k < TB_NUM_ENTRIES; k++) 240 { 241 if (address == tb_control->entry[k].p1) 242 { 243 if (tb_control->entry[k].p2 != -Size) 244 { 245 TB_PRINTF("Bad free size at 0x%lx address = 0x%lx Size = %ld Allocated = %d\n", 246 tb_control->entry[k].loc, tb_control->entry[k].p1, (long)tb_control->entry[k].p2, Size); 247 } 248 Frees += tb_control->entry[k].p2; 249 nFrees += 1; 250 break; 251 } 252 } 253 if (k == TB_NUM_ENTRIES) 254 { 255 TB_PRINTF("Memory leak at 0x%lx address = 0x%lx Size = %d\n", 256 tb_control->entry[j].loc, address, Size); 257 } 258 } 259 } 260 TB_PRINTF("tb_scan() Allocs = %ld nAllocs = %d Frees = %ld nFrees = %d\n", Allocs, nAllocs, Frees, nFrees); 261 } 262 263