Shared memory cache management
[ipc/ipcdev.git] / packages / ti / trace / SysMin.c
1 /*
2  * Copyright (c) 2011-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== SysMin.c ========
34  */
36 #include <xdc/runtime/Startup.h>
37 #include <xdc/runtime/Gate.h>
39 #ifdef SMP
40 #include <ti/sysbios/BIOS.h>
41 #include <ti/sysbios/hal/Core.h>
42 #include <ti/sysbios/hal/Hwi.h>
43 #endif
44 #include <ti/sysbios/knl/Clock.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <stdio.h>
50 #include "package/internal/SysMin.xdc.h"
52 /*
53  *  ======== SysMin_Module_startup ========
54  */
55 Int SysMin_Module_startup(Int phase)
56 {
57     if (SysMin_bufSize != 0) {
58         memset(module->outbuf, 0, SysMin_bufSize);
59     }
61 #ifndef SMP
62     /* Initialize to TRUE so the first line get the timestamp */
63     module->getTime = TRUE;
64 #endif
66     return (Startup_DONE);
67 }
69 /*
70  *  ======== SysMin_abort ========
71  */
72 Void SysMin_abort(CString str)
73 {
74     Char ch;
76     if (SysMin_bufSize != 0) {
77         if (str != NULL) {
78             while ((ch = *str++) != '\0') {
79                 SysMin_putch(ch);
80             }
81         }
83         /* Only flush if configured to do so */
84         if (SysMin_flushAtExit) {
85             SysMin_flush();
86         }
87     }
88 }
90 /*
91  *  ======== SysMin_exit ========
92  */
93 Void SysMin_exit(Int stat)
94 {
95     if ((SysMin_flushAtExit) && (SysMin_bufSize != 0)) {
96         SysMin_flush();
97     }
98 }
100 /*
101  *  ======== SysMin_output ========
102  *  Common output function to write a character
103  *  into the circular buffer
104  */
105 static inline Void SysMin_output(Char ch)
107     module->outbuf[module->outidx++] = ch;
108     /* Last 8 bytes are used for writeIdx/readIdx fields */
109     if (module->outidx == SysMin_bufSize - 8) {
110         module->outidx = 0;
111     }
114 /*
115  *  ======== SysMin_putch ========
116  *  Custom implementation for using circular
117  *  buffer without using flush
118  */
119 Void SysMin_putch(Char ch)
121     IArg        key;
122     UInt        i;
123 #ifndef SMP
124     static UInt coreId = 0;
125 #else
126     UInt        coreId;
127 #endif
128     UInt        lineIdx;
129     Char        *lineBuf;
130     Int         index;
131     UInt64      uSec;
132     static Bool configure = FALSE;
133     static UInt startIdx;
134     static UInt endIdx;
135     static UInt timeStampSecCharLen;
136     const  UInt minSecCharLen   = 4;  /* for 1 us tick period */
137     const  UInt maxuSecCharLen  = 6; /* for 1 us tick period */
138     /* Max characters for seconds would be 10 assuming 1 sec tick period,
139      * so decimal point index will be 11, and maximum time stamp buffer
140      * length would be 18 accounting maxuSecCharLen and a trailing NULL */
141     const  UInt decPtIdx        = 11;
142     const  UInt timeStampBufLen = 18;
143     const  UInt leftSpaceIdx    = 10;
144     Char        timeStamp[18]   = {"                 \0"};
146     /* Configure the trace timestamp format */
147     if (!configure) {
148         Int i = 0, mod = 10;
150         /* Find number of characters needes for seconds and sub-seconds,
151          * tick periods are specified in microseconds */
152         for (; i < maxuSecCharLen; i++) {
153             if (Clock_tickPeriod % mod) {
154                 break;
155             }
156             mod = mod * 10;
157         }
158         timeStampSecCharLen = minSecCharLen + i;
159         startIdx = decPtIdx - timeStampSecCharLen;
160         endIdx = timeStampBufLen - (i + 1); /* Account for null character too */
161         configure = TRUE;
162     }
164     if (SysMin_bufSize != 0) {
166 #ifndef SMP
167         key = Gate_enterSystem();
168 #else
169         /* Disable only local interrupts to place chars in local line buffer */
170         key = (IArg)Core_hwiDisable();
171         coreId = Core_getId();
172 #endif
174         lineIdx = module->lineBuffers[coreId].lineidx;
175         lineBuf = module->lineBuffers[coreId].linebuf;
176         lineBuf[lineIdx++] = ch;
177         module->lineBuffers[coreId].lineidx = lineIdx;
179 #ifdef SMP
180         /* Copy line buffer to shared output buffer at EOL or when filled up */
181         if ((ch == '\n') || (lineIdx >= SysMin_LINEBUFSIZE)) {
182             Gate_enterSystem();
184             /* Tag core number */
185             SysMin_output('[');
186             SysMin_output(0x30 + coreId);
187             SysMin_output(']');
188 #else
189         if (module->getTime == TRUE) {
190 #endif
191             uSec  = Clock_getTicks() * (UInt64)Clock_tickPeriod;
192             SysMin_output('[');
193             if (uSec) {
194                 sprintf(timeStamp, "%17llu\0", uSec);
195             }
196             for (index = startIdx; index < endIdx; index++) {
197                 if (index == decPtIdx) {
198                     SysMin_output('.');
199                 }
200                 if (timeStamp[index] == ' ' && index >= leftSpaceIdx) {
201                     SysMin_output('0');
202                 }
203                 else {
204                     SysMin_output(timeStamp[index]);
205                 }
206             }
207             SysMin_output(']');
208             SysMin_output(' ');
209 #ifdef SMP
210             for (i = 0; i < lineIdx; i++) {
211                 SysMin_output(lineBuf[i]);
212             }
213             module->writeidx[0] =  module->outidx;
214             module->lineBuffers[coreId].lineidx = 0;
216             Gate_leaveSystem(key);
217         }
218         else {
219             /* restore local interrupts */
220             Core_hwiRestore((UInt)key);
221         }
222 #else
223             module->getTime = FALSE;
224         }
226         /* Copy line buffer to shared output buffer at EOL or when filled up */
227         if ((ch == '\n') || (lineIdx >= SysMin_LINEBUFSIZE)) {
228             for (i = 0; i < lineIdx; i++) {
229                 SysMin_output(lineBuf[i]);
230             }
231             module->lineBuffers[coreId].lineidx = 0;
232             module->getTime = TRUE;
233             module->writeidx[0] = module->outidx;
234         }
236         Gate_leaveSystem(key);
237 #endif
239     }
242 /*
243  *  ======== SysMin_ready ========
244  */
245 Bool SysMin_ready()
247     return (SysMin_bufSize != 0);
250 /*
251  *  ======== SysMin_flush ========
252  *  Called during SysMin_exit, System_exit or System_flush.
253  */
254 Void SysMin_flush()
256 /* Using custom circular buffer implementation without resetting write ptr */
257 #if 0
258     IArg key;
260     key = Gate_enterSystem();
262     /*
263      *  If a wrap occured, we need to flush the "end" of the internal buffer
264      *  first to maintain fifo character output order.
265      */
266     if (module->wrapped == TRUE) {
267         SysMin_outputFunc(module->outbuf + module->outidx,
268                           SysMin_bufSize - module->outidx);
269     }
271     SysMin_outputFunc(module->outbuf, module->outidx);
272     module->outidx = 0;
273     module->wrapped = FALSE;
275     Gate_leaveSystem(key);
276 #endif