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
tb_control_size(void)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 */
tb_init(unsigned long options)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 */
tb_destroy(void)93 void tb_destroy(void)
94 {
95 if (--tb_control->nusers)
96 return;
97 TB_FREE(tb_control );
98 }
99
tb_next(void)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 }
tb_autoprint(void)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 */
tb_trace(int loc,unsigned long p1,unsigned long p2)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 }
tb_dump(void)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
tb_sprintf(const char * format,...)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
tb_printf(void)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 }
tb_set_option(unsigned long option)215 void tb_set_option(unsigned long option)
216 {
217 tb_control->options |= option;
218 }
219
tb_reset_option(unsigned long option)220 void tb_reset_option(unsigned long option)
221 {
222 tb_control->options &= ~option;
223 }
224
tb_scan(void)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