pa_trace.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * $Id: pa_trace.c 1916 2014-01-17 03:45:15Z philburk $
  3. * Portable Audio I/O Library Trace Facility
  4. * Store trace information in real-time for later printing.
  5. *
  6. * Based on the Open Source API proposed by Ross Bencina
  7. * Copyright (c) 1999-2000 Phil Burk
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining
  10. * a copy of this software and associated documentation files
  11. * (the "Software"), to deal in the Software without restriction,
  12. * including without limitation the rights to use, copy, modify, merge,
  13. * publish, distribute, sublicense, and/or sell copies of the Software,
  14. * and to permit persons to whom the Software is furnished to do so,
  15. * subject to the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be
  18. * included in all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  23. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  24. * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  25. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28. /*
  29. * The text above constitutes the entire PortAudio license; however,
  30. * the PortAudio community also makes the following non-binding requests:
  31. *
  32. * Any person wishing to distribute modifications to the Software is
  33. * requested to send the modifications to the original developer so that
  34. * they can be incorporated into the canonical version. It is also
  35. * requested that these non-binding requests be included along with the
  36. * license above.
  37. */
  38. /** @file
  39. @ingroup common_src
  40. @brief Real-time safe event trace logging facility for debugging.
  41. */
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <stdarg.h>
  45. #include <string.h>
  46. #include <assert.h>
  47. #include "pa_trace.h"
  48. #include "pa_util.h"
  49. #include "pa_debugprint.h"
  50. #if PA_TRACE_REALTIME_EVENTS
  51. static char const *traceTextArray[PA_MAX_TRACE_RECORDS];
  52. static int traceIntArray[PA_MAX_TRACE_RECORDS];
  53. static int traceIndex = 0;
  54. static int traceBlock = 0;
  55. /*********************************************************************/
  56. void PaUtil_ResetTraceMessages()
  57. {
  58. traceIndex = 0;
  59. }
  60. /*********************************************************************/
  61. void PaUtil_DumpTraceMessages()
  62. {
  63. int i;
  64. int messageCount = (traceIndex < PA_MAX_TRACE_RECORDS) ? traceIndex : PA_MAX_TRACE_RECORDS;
  65. printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
  66. for( i=0; i<messageCount; i++ )
  67. {
  68. printf("%3d: %s = 0x%08X\n",
  69. i, traceTextArray[i], traceIntArray[i] );
  70. }
  71. PaUtil_ResetTraceMessages();
  72. fflush(stdout);
  73. }
  74. /*********************************************************************/
  75. void PaUtil_AddTraceMessage( const char *msg, int data )
  76. {
  77. if( (traceIndex == PA_MAX_TRACE_RECORDS) && (traceBlock == 0) )
  78. {
  79. traceBlock = 1;
  80. /* PaUtil_DumpTraceMessages(); */
  81. }
  82. else if( traceIndex < PA_MAX_TRACE_RECORDS )
  83. {
  84. traceTextArray[traceIndex] = msg;
  85. traceIntArray[traceIndex] = data;
  86. traceIndex++;
  87. }
  88. }
  89. /************************************************************************/
  90. /* High performance log alternative */
  91. /************************************************************************/
  92. typedef unsigned long long PaUint64;
  93. typedef struct __PaHighPerformanceLog
  94. {
  95. unsigned magik;
  96. int writePtr;
  97. int readPtr;
  98. int size;
  99. double refTime;
  100. char* data;
  101. } PaHighPerformanceLog;
  102. static const unsigned kMagik = 0xcafebabe;
  103. #define USEC_PER_SEC (1000000ULL)
  104. int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes )
  105. {
  106. PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog));
  107. if (pLog == 0)
  108. {
  109. return paInsufficientMemory;
  110. }
  111. assert(phLog != 0);
  112. *phLog = pLog;
  113. pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes);
  114. if (pLog->data == 0)
  115. {
  116. PaUtil_FreeMemory(pLog);
  117. return paInsufficientMemory;
  118. }
  119. pLog->magik = kMagik;
  120. pLog->size = maxSizeInBytes;
  121. pLog->refTime = PaUtil_GetTime();
  122. return paNoError;
  123. }
  124. void PaUtil_ResetHighSpeedLogTimeRef( LogHandle hLog )
  125. {
  126. PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
  127. assert(pLog->magik == kMagik);
  128. pLog->refTime = PaUtil_GetTime();
  129. }
  130. typedef struct __PaLogEntryHeader
  131. {
  132. int size;
  133. double timeStamp;
  134. } PaLogEntryHeader;
  135. #ifdef __APPLE__
  136. #define _vsnprintf vsnprintf
  137. #define min(a,b) ((a)<(b)?(a):(b))
  138. #endif
  139. int PaUtil_AddHighSpeedLogMessage( LogHandle hLog, const char* fmt, ... )
  140. {
  141. va_list l;
  142. int n = 0;
  143. PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
  144. if (pLog != 0)
  145. {
  146. PaLogEntryHeader* pHeader;
  147. char* p;
  148. int maxN;
  149. assert(pLog->magik == kMagik);
  150. pHeader = (PaLogEntryHeader*)( pLog->data + pLog->writePtr );
  151. p = (char*)( pHeader + 1 );
  152. maxN = pLog->size - pLog->writePtr - 2 * sizeof(PaLogEntryHeader);
  153. pHeader->timeStamp = PaUtil_GetTime() - pLog->refTime;
  154. if (maxN > 0)
  155. {
  156. if (maxN > 32)
  157. {
  158. va_start(l, fmt);
  159. n = _vsnprintf(p, min(1024, maxN), fmt, l);
  160. va_end(l);
  161. }
  162. else {
  163. n = sprintf(p, "End of log...");
  164. }
  165. n = ((n + sizeof(unsigned)) & ~(sizeof(unsigned)-1)) + sizeof(PaLogEntryHeader);
  166. pHeader->size = n;
  167. #if 0
  168. PaUtil_DebugPrint("%05u.%03u: %s\n", pHeader->timeStamp/1000, pHeader->timeStamp%1000, p);
  169. #endif
  170. pLog->writePtr += n;
  171. }
  172. }
  173. return n;
  174. }
  175. void PaUtil_DumpHighSpeedLog( LogHandle hLog, const char* fileName )
  176. {
  177. FILE* f = (fileName != NULL) ? fopen(fileName, "w") : stdout;
  178. unsigned localWritePtr;
  179. PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
  180. assert(pLog->magik == kMagik);
  181. localWritePtr = pLog->writePtr;
  182. while (pLog->readPtr != localWritePtr)
  183. {
  184. const PaLogEntryHeader* pHeader = (const PaLogEntryHeader*)( pLog->data + pLog->readPtr );
  185. const char* p = (const char*)( pHeader + 1 );
  186. const PaUint64 ts = (const PaUint64)( pHeader->timeStamp * USEC_PER_SEC );
  187. assert(pHeader->size < (1024+sizeof(unsigned)+sizeof(PaLogEntryHeader)));
  188. fprintf(f, "%05u.%03u: %s\n", (unsigned)(ts/1000), (unsigned)(ts%1000), p);
  189. pLog->readPtr += pHeader->size;
  190. }
  191. if (f != stdout)
  192. {
  193. fclose(f);
  194. }
  195. }
  196. void PaUtil_DiscardHighSpeedLog( LogHandle hLog )
  197. {
  198. PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)hLog;
  199. assert(pLog->magik == kMagik);
  200. PaUtil_FreeMemory(pLog->data);
  201. PaUtil_FreeMemory(pLog);
  202. }
  203. #else
  204. /* This stub was added so that this file will generate a symbol.
  205. * Otherwise linker/archiver programs will complain.
  206. */
  207. int PaUtil_TraceStubToSatisfyLinker(void)
  208. {
  209. return 0;
  210. }
  211. #endif /* TRACE_REALTIME_EVENTS */