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
33void 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
49char * const domains_normal[] = { "AD,", "VD,", "ID,", "AE,", "VE,", "IE,"};
50char * const domains_csv[]    = { "+AD", "+VD", "+ID", "+AE", "+VE", "+IE"};
51
52static
53void print_header(FILE *fOut)
54{
55    fprintf(fOut, "time,PID,handle,name,domAD,domVD,domID,domAE,domVE,domIE,"
56            "type,operation\n");
57}
58
59int 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__
138void __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
151void 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
160void 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
200PERF_PRINT_Private *
201PERF_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
268void __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
290static const char *sendRecvTxt[] = {
291        "received", "sending", "requesting", "sent",
292    };
293
294void __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
349void __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
381void __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
394void __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
407void __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
429void __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
454void __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