b3Clock.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "b3Clock.h"
  2. template <class T>
  3. const T& b3ClockMin(const T& a, const T& b)
  4. {
  5. return a < b ? a : b ;
  6. }
  7. #ifdef __CELLOS_LV2__
  8. #include <sys/sys_time.h>
  9. #include <sys/time_util.h>
  10. #include <stdio.h>
  11. #endif
  12. #if defined (SUNOS) || defined (__SUNOS__)
  13. #include <stdio.h>
  14. #endif
  15. #if defined(WIN32) || defined(_WIN32)
  16. #define B3_USE_WINDOWS_TIMERS
  17. #define WIN32_LEAN_AND_MEAN
  18. #define NOWINRES
  19. #define NOMCX
  20. #define NOIME
  21. #ifdef _XBOX
  22. #include <Xtl.h>
  23. #else //_XBOX
  24. #include <windows.h>
  25. #endif //_XBOX
  26. #include <time.h>
  27. #else //_WIN32
  28. #include <sys/time.h>
  29. #endif //_WIN32
  30. struct b3ClockData
  31. {
  32. #ifdef B3_USE_WINDOWS_TIMERS
  33. LARGE_INTEGER mClockFrequency;
  34. DWORD mStartTick;
  35. LONGLONG mPrevElapsedTime;
  36. LARGE_INTEGER mStartTime;
  37. #else
  38. #ifdef __CELLOS_LV2__
  39. uint64_t mStartTime;
  40. #else
  41. struct timeval mStartTime;
  42. #endif
  43. #endif //__CELLOS_LV2__
  44. };
  45. ///The b3Clock is a portable basic clock that measures accurate time in seconds, use for profiling.
  46. b3Clock::b3Clock()
  47. {
  48. m_data = new b3ClockData;
  49. #ifdef B3_USE_WINDOWS_TIMERS
  50. QueryPerformanceFrequency(&m_data->mClockFrequency);
  51. #endif
  52. reset();
  53. }
  54. b3Clock::~b3Clock()
  55. {
  56. delete m_data;
  57. }
  58. b3Clock::b3Clock(const b3Clock& other)
  59. {
  60. m_data = new b3ClockData;
  61. *m_data = *other.m_data;
  62. }
  63. b3Clock& b3Clock::operator=(const b3Clock& other)
  64. {
  65. *m_data = *other.m_data;
  66. return *this;
  67. }
  68. /// Resets the initial reference time.
  69. void b3Clock::reset()
  70. {
  71. #ifdef B3_USE_WINDOWS_TIMERS
  72. QueryPerformanceCounter(&m_data->mStartTime);
  73. m_data->mStartTick = GetTickCount();
  74. m_data->mPrevElapsedTime = 0;
  75. #else
  76. #ifdef __CELLOS_LV2__
  77. typedef uint64_t ClockSize;
  78. ClockSize newTime;
  79. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  80. SYS_TIMEBASE_GET( newTime );
  81. m_data->mStartTime = newTime;
  82. #else
  83. gettimeofday(&m_data->mStartTime, 0);
  84. #endif
  85. #endif
  86. }
  87. /// Returns the time in ms since the last call to reset or since
  88. /// the b3Clock was created.
  89. unsigned long int b3Clock::getTimeMilliseconds()
  90. {
  91. #ifdef B3_USE_WINDOWS_TIMERS
  92. LARGE_INTEGER currentTime;
  93. QueryPerformanceCounter(&currentTime);
  94. LONGLONG elapsedTime = currentTime.QuadPart -
  95. m_data->mStartTime.QuadPart;
  96. // Compute the number of millisecond ticks elapsed.
  97. unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
  98. m_data->mClockFrequency.QuadPart);
  99. // Check for unexpected leaps in the Win32 performance counter.
  100. // (This is caused by unexpected data across the PCI to ISA
  101. // bridge, aka south bridge. See Microsoft KB274323.)
  102. unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
  103. signed long msecOff = (signed long)(msecTicks - elapsedTicks);
  104. if (msecOff < -100 || msecOff > 100)
  105. {
  106. // Adjust the starting time forwards.
  107. LONGLONG msecAdjustment = b3ClockMin(msecOff *
  108. m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
  109. m_data->mPrevElapsedTime);
  110. m_data->mStartTime.QuadPart += msecAdjustment;
  111. elapsedTime -= msecAdjustment;
  112. // Recompute the number of millisecond ticks elapsed.
  113. msecTicks = (unsigned long)(1000 * elapsedTime /
  114. m_data->mClockFrequency.QuadPart);
  115. }
  116. // Store the current elapsed time for adjustments next time.
  117. m_data->mPrevElapsedTime = elapsedTime;
  118. return msecTicks;
  119. #else
  120. #ifdef __CELLOS_LV2__
  121. uint64_t freq=sys_time_get_timebase_frequency();
  122. double dFreq=((double) freq) / 1000.0;
  123. typedef uint64_t ClockSize;
  124. ClockSize newTime;
  125. SYS_TIMEBASE_GET( newTime );
  126. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  127. return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
  128. #else
  129. struct timeval currentTime;
  130. gettimeofday(&currentTime, 0);
  131. return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
  132. (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
  133. #endif //__CELLOS_LV2__
  134. #endif
  135. }
  136. /// Returns the time in us since the last call to reset or since
  137. /// the Clock was created.
  138. unsigned long int b3Clock::getTimeMicroseconds()
  139. {
  140. #ifdef B3_USE_WINDOWS_TIMERS
  141. LARGE_INTEGER currentTime;
  142. QueryPerformanceCounter(&currentTime);
  143. LONGLONG elapsedTime = currentTime.QuadPart -
  144. m_data->mStartTime.QuadPart;
  145. // Compute the number of millisecond ticks elapsed.
  146. unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
  147. m_data->mClockFrequency.QuadPart);
  148. // Check for unexpected leaps in the Win32 performance counter.
  149. // (This is caused by unexpected data across the PCI to ISA
  150. // bridge, aka south bridge. See Microsoft KB274323.)
  151. unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
  152. signed long msecOff = (signed long)(msecTicks - elapsedTicks);
  153. if (msecOff < -100 || msecOff > 100)
  154. {
  155. // Adjust the starting time forwards.
  156. LONGLONG msecAdjustment = b3ClockMin(msecOff *
  157. m_data->mClockFrequency.QuadPart / 1000, elapsedTime -
  158. m_data->mPrevElapsedTime);
  159. m_data->mStartTime.QuadPart += msecAdjustment;
  160. elapsedTime -= msecAdjustment;
  161. }
  162. // Store the current elapsed time for adjustments next time.
  163. m_data->mPrevElapsedTime = elapsedTime;
  164. // Convert to microseconds.
  165. unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime /
  166. m_data->mClockFrequency.QuadPart);
  167. return usecTicks;
  168. #else
  169. #ifdef __CELLOS_LV2__
  170. uint64_t freq=sys_time_get_timebase_frequency();
  171. double dFreq=((double) freq)/ 1000000.0;
  172. typedef uint64_t ClockSize;
  173. ClockSize newTime;
  174. //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
  175. SYS_TIMEBASE_GET( newTime );
  176. return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
  177. #else
  178. struct timeval currentTime;
  179. gettimeofday(&currentTime, 0);
  180. return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
  181. (currentTime.tv_usec - m_data->mStartTime.tv_usec);
  182. #endif//__CELLOS_LV2__
  183. #endif
  184. }