Home | History | Annotate | Download | only in src
      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