1 
2 /*
3  * Copyright (C) Texas Instruments - http://www.ti.com/
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 #ifdef __PERF_CUSTOMIZABLE__
22 
23     #define __PERF_PRINT_C__
24 
25     #include "perf_config.h"
26     #include "perf.h"
27     #include "perf_print.h"
28 
29 /* ============================================================================
30    DEBUG PRINT METHODS
31 ============================================================================ */
32 
PERF_PRINT_done(PERF_Private * perf)33 void PERF_PRINT_done(PERF_Private *perf)
34 {
35     PERF_PRINT_Private *me = perf->cip.pDebug;
36 
37     /* close debug file unless stdout or stderr */
38     if (me->fDebug && me->fDebug != stdout &&
39         me->fDebug != stderr) fclose(me->fDebug);
40 
41     /* free allocated strings */
42     free(me->info);    me->info = NULL;
43 
44     /* free private structure */
45     free(me);
46     perf->cip.pDebug = NULL;
47 }
48 
49 char * const domains_normal[] = { "AD,", "VD,", "ID,", "AE,", "VE,", "IE,"};
50 char * const domains_csv[]    = { "+AD", "+VD", "+ID", "+AE", "+VE", "+IE"};
51 
52 static
print_header(FILE * fOut)53 void print_header(FILE *fOut)
54 {
55     fprintf(fOut, "time,PID,handle,name,domAD,domVD,domID,domAE,domVE,domIE,"
56             "type,operation\n");
57 }
58 
PERF_PRINT_setup(PERF_Private * perf,PERF_MODULETYPE eModule)59 int PERF_PRINT_setup(PERF_Private *perf, PERF_MODULETYPE eModule)
60 {
61     PERF_PRINT_Private *me = perf->cip.pDebug;
62     /* we concatenate the following fields for a unique and informative ID:
63        PID, address, domain, type */
64 
65     /* common variables that differ from CSV and text output */
66     char const * const * domains, *missing, *separator;
67 
68     /* data needed for info field */
69     unsigned long type = eModule & PERF_ModuleMask;
70 
71     /* set up common variables */
72     if (me->csv)
73     {
74         domains = (char const * const *) domains_normal;
75         missing = separator = ",";
76         me->prompt = "";
77         print_header(me->fDebug);
78     }
79     else
80     {
81         domains = (char const * const *) domains_csv;
82         missing = "";
83         separator = ", ";
84         me->prompt = "<";
85     }
86 
87     me->info = (char *) malloc(3+9+1+8+2+6+4+2+7+12+8+16+2 + 100);
88     if (me->info)
89     {
90 
91         sprintf(me->info,
92                 "%s"           /* info separator start */
93                 "%ld"          /* PID */
94                 "%s"           /* separator */
95                 "%08lx"        /* handle */
96                 "%s"           /* separator */
97                 "%s"           /* name tag */
98                 "%c%c%c%c"     /* name (fourcc) */
99                 "%s"           /* separator */
100                 "%s"           /* domain tag */
101                 "%s%s%s%s%s%s" /* domain */
102                 "%s"           /* module tag */
103                 "%s"           /* module */
104                 "%s"           /* info separator end */
105                 ,
106                 me->csv ? separator : "> {",
107                 perf->ulPID,
108                 me->csv ? separator : "-",
109                 (unsigned long) perf,
110                 separator,
111                 /* name tag */
112                 me->csv ? "" : "name: ",
113                 /* name (fourcc) */
114                 PERF_FOUR_CHARS(perf->ulID),
115                 separator,
116                 /* domain tag */
117                 me->csv ? "" : "domain: ",
118                 /* domain */
119                 (eModule & PERF_ModuleAudioDecode) ? domains[0] : missing,
120                 (eModule & PERF_ModuleVideoDecode) ? domains[1] : missing,
121                 (eModule & PERF_ModuleImageDecode) ? domains[2] : missing,
122                 (eModule & PERF_ModuleAudioEncode) ? domains[3] : missing,
123                 (eModule & PERF_ModuleVideoEncode) ? domains[4] : missing,
124                 (eModule & PERF_ModuleImageEncode) ? domains[5] : missing,
125                 /* module tag */
126                 me->csv ? "" : ", module: ",  /* note: separator added for CSV */
127                 /* module */
128                 (type < PERF_ModuleMax) ? PERF_ModuleTypes[type] : "INVALID",
129                 /* info separator end */
130                 me->csv ? separator : "} ");
131     }
132 
133     /* we succeed if we could allocate the info string */
134     return(me->info != NULL);
135 }
136 
137 #ifdef __PERF_LOG_LOCATION__
__print_Location(PERF_Private * perf,char const * szFile,unsigned long ulLine,char const * szFunc)138 void __print_Location(PERF_Private *perf,
139                       char const *szFile,
140                       unsigned long ulLine,
141                       char const *szFunc)
142 {
143     /* save location for printing */
144     PERF_PRINT_Private *me = perf->cip.pDebug;
145 
146     me->szFile = szFile;
147     me->szFunc = szFunc;
148     me->ulLine = ulLine;
149 }
150 
clear_print_location(PERF_Private * perf)151 void clear_print_location(PERF_Private *perf)
152 {
153     PERF_PRINT_Private *me = perf->cip.pDebug;
154 
155     /* clear location information */
156     me->szFile = me->szFunc = NULL;
157     me->ulLine = 0;
158 }
159 
print_print_location(PERF_Private * perf,FILE * fOut,int nValues)160 void print_print_location(PERF_Private *perf, FILE *fOut, int nValues)
161 {
162     PERF_PRINT_Private *me = perf->cip.pDebug;
163 
164     /* print location information if specified */
165     if (me->szFile && me->szFunc)
166     {
167         /* align filenames for CSV format */
168         if (me->csv)
169         {
170             while (nValues < 7)
171             {
172                 fprintf(fOut, ",");
173                 nValues++;
174             }
175         }
176         fprintf(fOut, "%s%s%s%lu%s%s%s\n",
177                 me->csv ? "," : " in ",
178                 me->szFile,
179                 me->csv ? "," : ":line ",
180                 me->ulLine,
181                 me->csv ? "," : ":",
182                 me->szFunc,
183                 me->csv ? "" : "()");
184 
185         /* clear print location */
186         clear_print_location(perf);
187     }
188     else
189     {   /* if no info is specified, we still need to print the new line */
190         fprintf(fOut, "\n");
191     }
192 }
193 
194 #define __LINE_END__ ""
195 #else
196 #define __LINE_END__ "\n"
197 #define print_print_location(perf, fOut, nValues)
198 #endif
199 
200 PERF_PRINT_Private *
PERF_PRINT_create(PERF_Private * perf,PERF_Config * config,PERF_MODULETYPE eModule)201 PERF_PRINT_create(PERF_Private *perf, PERF_Config *config,
202                   PERF_MODULETYPE eModule)
203 {
204     char *fOutFile = NULL;
205     FILE *fOut = NULL;
206     PERF_PRINT_Private *me =
207     perf->cip.pDebug = malloc(sizeof(PERF_PRINT_Private));
208 
209     if (me)
210     {
211         me->csv = config->csv;
212         me->fDebug = me->fPrint = NULL;
213         me->info = me->prompt = NULL;
214         perf->uMode |= PERF_Mode_Print;
215 
216 #ifdef __PERF_LOG_LOCATION__
217         /* no location information yet */
218         clear_print_location(perf);
219 #endif
220         /* set up fDebug and fPrint file pointers */
221         if (config->log_file)
222         {
223             /* open log file unless STDOUT or STDERR is specified */
224             if (!strcasecmp(config->log_file, "STDOUT")) fOut = stdout;
225             else if (!strcasecmp(config->log_file, "STDERR")) fOut = stderr;
226             else
227             {
228                 /* expand file name with PID and name */
229                 fOutFile = (char *) malloc (strlen(config->log_file) + 32);
230                 if (fOutFile)
231                 {
232                     sprintf(fOutFile, "%s-%05lu-%08lx-%c%c%c%c.log",
233                             config->log_file, perf->ulPID, (unsigned long) perf,
234                             PERF_FOUR_CHARS(perf->ulID));
235                     fOut = fopen(fOutFile, "at");
236 
237                     /* free new file name */
238                     free(fOutFile);
239                     fOutFile = NULL;
240                 }
241 
242                 /* if could not open output, set it to STDOUT */
243                 if (!fOut) fOut = stdout;
244             }
245             me->fDebug = me->fPrint = fOut;
246 
247         }
248         else if (config->detailed_debug)
249         {
250             /* detailed debug is through stderr */
251             me->fDebug = me->fPrint = stderr;
252         }
253         else if (config->debug)
254         {
255             /* normal debug is through stdout (buffers are not printed) */
256             me->fDebug = stdout;
257             me->fPrint = NULL;
258         }
259 
260         PERF_PRINT_setup(perf, eModule);
261 
262         if (me->fDebug) __print_Create(me->fDebug, perf);
263     }
264 
265     return(me);
266 }
267 
__print_Boundary(FILE * fOut,PERF_Private * perf,PERF_BOUNDARYTYPE eBoundary)268 void __print_Boundary(FILE *fOut,
269                       PERF_Private *perf, PERF_BOUNDARYTYPE eBoundary)
270 {
271     /* get debug private structure */
272     PERF_PRINT_Private *me = perf->cip.pDebug;
273 
274     unsigned long boundary = ((unsigned long) eBoundary) & PERF_BoundaryMask;
275 
276     fprintf(fOut, "%s%ld.%06ld%sBoundary%s0x%x%s%s%s%s" __LINE_END__,
277             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
278             me->info,
279             me->csv ? "," : "(",
280             eBoundary,
281             me->csv ? "," : " = ",
282             PERF_IsStarted(eBoundary) ? "started " : "completed ",
283             (boundary < PERF_BoundaryMax  ?
284              PERF_BoundaryTypes[boundary] : "INVALID"),
285             me->csv ? "" : ")");
286 
287     print_print_location(perf, fOut, 2);
288 }
289 
290 static const char *sendRecvTxt[] = {
291         "received", "sending", "requesting", "sent",
292     };
293 
__print_Buffer(FILE * fOut,PERF_Private * perf,unsigned long ulAddress1,unsigned long ulAddress2,unsigned long ulSize,PERF_MODULETYPE eModule)294 void __print_Buffer(FILE *fOut,
295                     PERF_Private *perf,
296                     unsigned long ulAddress1,
297                     unsigned long ulAddress2,
298                     unsigned long ulSize,
299                     PERF_MODULETYPE eModule)
300 {
301 
302     /* get debug private structure */
303     PERF_PRINT_Private *me = perf->cip.pDebug;
304 
305     unsigned long module1 = ((unsigned long) eModule) & PERF_ModuleMask;
306     unsigned long module2 = (((unsigned long) eModule) >> PERF_ModuleBits) & PERF_ModuleMask;
307     int xfering  = PERF_IsXfering ((unsigned long) eModule);
308     int sendIx   = (PERF_GetSendRecv ((unsigned long) eModule) >> 28) & 3;
309     int sending  = PERF_IsSending ((unsigned long) eModule);
310     int frame    = PERF_IsFrame   ((unsigned long) eModule);
311     int multiple = PERF_IsMultiple((unsigned long) eModule);
312 
313     if (!xfering && sending) module2 = module1;
314 
315     fprintf(fOut, "%s%ld.%06ld%sBuffer%s%s%s%s%s%s%s%s%s0x%lx%s0x%lx",
316             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
317             me->info,
318             me->csv ? "," : "(",
319             xfering ? "xfering" : sendRecvTxt[sendIx],
320             me->csv ? "," : " ",
321             frame ? "frame" : "buffer",
322             me->csv ? "," : (xfering || !sending) ? " from=" : "",
323             (xfering || !sending) ?
324             (module1 < PERF_ModuleMax ? PERF_ModuleTypes[module1] : "INVALID") :
325             "",
326             me->csv ? "," : (xfering || sending) ? " to=" : "",
327             (xfering || sending) ?
328             (module2 < PERF_ModuleMax ? PERF_ModuleTypes[module2] : "INVALID") :
329             "",
330             me->csv ? "," : " size=",
331             ulSize,
332             me->csv ? "," : " addr=",
333             ulAddress1);
334 
335     /* print second address if supplied */
336     if (multiple)
337     {
338         fprintf(fOut, "%s0x%lx",
339                 me->csv ? "," : " addr=",
340                 ulAddress2);
341     }
342 
343     fprintf(fOut, "%s" __LINE_END__,
344             me->csv ? "" : ")");
345 
346     print_print_location(perf, fOut, 6 + (multiple ? 1 : 0));
347 }
348 
__print_Command(FILE * fOut,PERF_Private * perf,unsigned long ulCommand,unsigned long ulArgument,PERF_MODULETYPE eModule)349 void __print_Command(FILE *fOut,
350                      PERF_Private *perf,
351                      unsigned long ulCommand,
352 					 unsigned long ulArgument,
353                      PERF_MODULETYPE eModule)
354 {
355     /* get debug private structure */
356     PERF_PRINT_Private *me = perf->cip.pDebug;
357 
358     unsigned long module = ((unsigned long) eModule) & PERF_ModuleMask;
359     int sendIx   = (PERF_GetSendRecv ((unsigned long) eModule) >> 28) & 3;
360     int sending  = PERF_IsSending(((unsigned long) eModule) & ~PERF_ModuleMask);
361 
362     fprintf(fOut, "%s%ld.%06ld%sCommand%s%s%s%s%s0x%lx%s0x%lx%s%s%s" __LINE_END__,
363             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
364             me->info,
365             me->csv ? "," : "(",
366             sendRecvTxt[sendIx],
367             me->csv ? "," : sending ? " to=" : " from=",
368             module < PERF_ModuleMax ? PERF_ModuleTypes[module] : "INVALID",
369             me->csv ? "," : " cmd=",
370             ulCommand,
371 			me->csv ? "," : "(",
372 			ulArgument,
373             me->csv ? "," : ") = ",
374             (ulCommand != PERF_CommandStatus  ?
375              "INVALID" : PERF_CommandTypes[ulCommand]),
376             me->csv ? "" : ")");
377 
378     print_print_location(perf, fOut, 5);
379 }
380 
__print_Create(FILE * fOut,PERF_Private * perf)381 void __print_Create(FILE *fOut,
382                     PERF_Private *perf)
383 {
384     /* get debug private structure */
385     PERF_PRINT_Private *me = perf->cip.pDebug;
386 
387     fprintf(fOut, "%s%ld.%06ld%sCreate" __LINE_END__,
388             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
389             me->info);
390 
391     print_print_location(perf, fOut, 0);
392 }
393 
__print_Done(FILE * fOut,PERF_Private * perf)394 void __print_Done(FILE *fOut,
395                   PERF_Private *perf)
396 {
397     /* get debug private structure */
398     PERF_PRINT_Private *me = perf->cip.pDebug;
399 
400     fprintf(fOut, "%s%ld.%06ld%sDone" __LINE_END__,
401             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
402             me->info);
403 
404     print_print_location(perf, fOut, 0);
405 }
406 
__print_Log(FILE * fOut,PERF_Private * perf,unsigned long ulData1,unsigned long ulData2,unsigned long ulData3)407 void __print_Log(FILE *fOut,
408                  PERF_Private *perf,
409                  unsigned long ulData1, unsigned long ulData2,
410                  unsigned long ulData3)
411 {
412     /* get debug private structure */
413     PERF_PRINT_Private *me = perf->cip.pDebug;
414 
415     fprintf(fOut, "%s%ld.%06ld%sLog%s0x%lx%s0x%lx%s0x%lx%s" __LINE_END__,
416             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
417             me->info,
418             me->csv ? "," : "(",
419             ulData1,
420             me->csv ? "," : ", ",
421             ulData2,
422             me->csv ? "," : ", ",
423             ulData3,
424             me->csv ? "" : ")");
425 
426     print_print_location(perf, fOut, 3);
427 }
428 
__print_SyncAV(FILE * fOut,PERF_Private * perf,float pfTimeAudio,float pfTimeVideo,PERF_SYNCOPTYPE eSyncOperation)429 void __print_SyncAV(FILE *fOut,
430                     PERF_Private *perf,
431                     float pfTimeAudio,
432                     float pfTimeVideo,
433                     PERF_SYNCOPTYPE eSyncOperation)
434 {
435     /* get debug private structure */
436     PERF_PRINT_Private *me = perf->cip.pDebug;
437 
438     unsigned long op = (unsigned long) eSyncOperation;
439 
440     fprintf(fOut, "%s%ld.%06ld%sSyncAV%s%g%s%g%s%s%s" __LINE_END__,
441             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
442             me->info,
443             me->csv ? "," : "(audioTS=",
444             pfTimeAudio,
445             me->csv ? "," : " videoTS=",
446             pfTimeVideo,
447             me->csv ? "," : " op=",
448             (op < PERF_SyncOpMax ? PERF_SyncOpTypes[op] : "INVALID"),
449             me->csv ? "" : ")");
450 
451     print_print_location(perf, fOut, 3);
452 }
453 
__print_ThreadCreated(FILE * fOut,PERF_Private * perf,unsigned long ulThreadID,unsigned long ulThreadName)454 void __print_ThreadCreated(FILE *fOut,
455                            PERF_Private *perf,
456                            unsigned long ulThreadID,
457                            unsigned long ulThreadName)
458 {
459     /* get debug private structure */
460     PERF_PRINT_Private *me = perf->cip.pDebug;
461 
462     fprintf(fOut, "%s%ld.%06ld%sThread%s%ld%s%c%c%c%c%s" __LINE_END__,
463             me->prompt, TIME_SECONDS(perf->time), TIME_MICROSECONDS(perf->time),
464             me->info,
465             me->csv ? "," : "(pid=",
466             ulThreadID,
467             me->csv ? "," : " name=",
468             PERF_FOUR_CHARS(ulThreadName),
469             me->csv ? "" : ")");
470 
471     print_print_location(perf, fOut, 2);
472 }
473 
474 #endif
475