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 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 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 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__ 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 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 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 * 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 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 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 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 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 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 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 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 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