123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- /*
- * $Id: pa_trace.c 1916 2014-01-17 03:45:15Z philburk $
- * Portable Audio I/O Library Trace Facility
- * Store trace information in real-time for later printing.
- *
- * Based on the Open Source API proposed by Ross Bencina
- * Copyright (c) 1999-2000 Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
- /*
- * The text above constitutes the entire PortAudio license; however,
- * the PortAudio community also makes the following non-binding requests:
- *
- * Any person wishing to distribute modifications to the Software is
- * requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version. It is also
- * requested that these non-binding requests be included along with the
- * license above.
- */
- /** @file
- @ingroup common_src
- @brief Real-time safe event trace logging facility for debugging.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <assert.h>
- #include "pa_trace.h"
- #include "pa_util.h"
- #include "pa_debugprint.h"
- #if PA_TRACE_REALTIME_EVENTS
- static char const *traceTextArray[PA_MAX_TRACE_RECORDS];
- static int traceIntArray[PA_MAX_TRACE_RECORDS];
- static int traceIndex = 0;
- static int traceBlock = 0;
- /*********************************************************************/
- void PaUtil_ResetTraceMessages()
- {
- traceIndex = 0;
- }
- /*********************************************************************/
- void PaUtil_DumpTraceMessages()
- {
- int i;
- int messageCount = (traceIndex < PA_MAX_TRACE_RECORDS) ? traceIndex : PA_MAX_TRACE_RECORDS;
- printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
- for( i=0; i<messageCount; i++ )
- {
- printf("%3d: %s = 0x%08X\n",
- i, traceTextArray[i], traceIntArray[i] );
- }
- PaUtil_ResetTraceMessages();
- fflush(stdout);
- }
- /*********************************************************************/
- void PaUtil_AddTraceMessage( const char *msg, int data )
- {
- if( (traceIndex == PA_MAX_TRACE_RECORDS) && (traceBlock == 0) )
- {
- traceBlock = 1;
- /* PaUtil_DumpTraceMessages(); */
- }
- else if( traceIndex < PA_MAX_TRACE_RECORDS )
- {
- traceTextArray[traceIndex] = msg;
- traceIntArray[traceIndex] = data;
- traceIndex++;
- }
- }
- /************************************************************************/
- /* High performance log alternative */
- /************************************************************************/
- typedef unsigned long long PaUint64;
- typedef struct __PaHighPerformanceLog
- {
- unsigned magik;
- int writePtr;
- int readPtr;
- int size;
- double refTime;
- char* data;
- } PaHighPerformanceLog;
- static const unsigned kMagik = 0xcafebabe;
- #define USEC_PER_SEC (1000000ULL)
- int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes )
- {
- PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog));
- if (pLog == 0)
- {
- return paInsufficientMemory;
- }
- assert(phLog != 0);
- *phLog = pLog;
- pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes);
- if (pLog->data == 0)
- {
- PaUtil_FreeMemory(pLog);
- return paInsufficientMemory;
- }
- pLog->magik = kMagik;
- pLog->size = maxSizeInBytes;
- pLog->refTime = PaUtil_GetTime();
- return paNoError;
- }
- void PaUtil_ResetHighSpeedLogTimeRef( LogHandle hLog )
- {
- PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
- assert(pLog->magik == kMagik);
- pLog->refTime = PaUtil_GetTime();
- }
- typedef struct __PaLogEntryHeader
- {
- int size;
- double timeStamp;
- } PaLogEntryHeader;
- #ifdef __APPLE__
- #define _vsnprintf vsnprintf
- #define min(a,b) ((a)<(b)?(a):(b))
- #endif
- int PaUtil_AddHighSpeedLogMessage( LogHandle hLog, const char* fmt, ... )
- {
- va_list l;
- int n = 0;
- PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
- if (pLog != 0)
- {
- PaLogEntryHeader* pHeader;
- char* p;
- int maxN;
- assert(pLog->magik == kMagik);
- pHeader = (PaLogEntryHeader*)( pLog->data + pLog->writePtr );
- p = (char*)( pHeader + 1 );
- maxN = pLog->size - pLog->writePtr - 2 * sizeof(PaLogEntryHeader);
- pHeader->timeStamp = PaUtil_GetTime() - pLog->refTime;
- if (maxN > 0)
- {
- if (maxN > 32)
- {
- va_start(l, fmt);
- n = _vsnprintf(p, min(1024, maxN), fmt, l);
- va_end(l);
- }
- else {
- n = sprintf(p, "End of log...");
- }
- n = ((n + sizeof(unsigned)) & ~(sizeof(unsigned)-1)) + sizeof(PaLogEntryHeader);
- pHeader->size = n;
- #if 0
- PaUtil_DebugPrint("%05u.%03u: %s\n", pHeader->timeStamp/1000, pHeader->timeStamp%1000, p);
- #endif
- pLog->writePtr += n;
- }
- }
- return n;
- }
- void PaUtil_DumpHighSpeedLog( LogHandle hLog, const char* fileName )
- {
- FILE* f = (fileName != NULL) ? fopen(fileName, "w") : stdout;
- unsigned localWritePtr;
- PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
- assert(pLog->magik == kMagik);
- localWritePtr = pLog->writePtr;
- while (pLog->readPtr != localWritePtr)
- {
- const PaLogEntryHeader* pHeader = (const PaLogEntryHeader*)( pLog->data + pLog->readPtr );
- const char* p = (const char*)( pHeader + 1 );
- const PaUint64 ts = (const PaUint64)( pHeader->timeStamp * USEC_PER_SEC );
- assert(pHeader->size < (1024+sizeof(unsigned)+sizeof(PaLogEntryHeader)));
- fprintf(f, "%05u.%03u: %s\n", (unsigned)(ts/1000), (unsigned)(ts%1000), p);
- pLog->readPtr += pHeader->size;
- }
- if (f != stdout)
- {
- fclose(f);
- }
- }
- void PaUtil_DiscardHighSpeedLog( LogHandle hLog )
- {
- PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
- assert(pLog->magik == kMagik);
- PaUtil_FreeMemory(pLog->data);
- PaUtil_FreeMemory(pLog);
- }
- #else
- /* This stub was added so that this file will generate a symbol.
- * Otherwise linker/archiver programs will complain.
- */
- int PaUtil_TraceStubToSatisfyLinker(void)
- {
- return 0;
- }
- #endif /* TRACE_REALTIME_EVENTS */
|