Crypto++
|
00001 // hrtimer.cpp - written and placed in the public domain by Wei Dai 00002 00003 #include "pch.h" 00004 #include "hrtimer.h" 00005 #include "misc.h" 00006 #include <stddef.h> // for NULL 00007 #include <time.h> 00008 00009 #if defined(CRYPTOPP_WIN32_AVAILABLE) 00010 #include <windows.h> 00011 #elif defined(CRYPTOPP_UNIX_AVAILABLE) 00012 #include <sys/time.h> 00013 #include <sys/times.h> 00014 #include <unistd.h> 00015 #endif 00016 00017 #include <assert.h> 00018 00019 NAMESPACE_BEGIN(CryptoPP) 00020 00021 #ifndef CRYPTOPP_IMPORTS 00022 00023 double TimerBase::ConvertTo(TimerWord t, Unit unit) 00024 { 00025 static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000}; 00026 00027 assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0])); 00028 return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond(); 00029 } 00030 00031 void TimerBase::StartTimer() 00032 { 00033 m_last = m_start = GetCurrentTimerValue(); 00034 m_started = true; 00035 } 00036 00037 double TimerBase::ElapsedTimeAsDouble() 00038 { 00039 if (m_stuckAtZero) 00040 return 0; 00041 00042 if (m_started) 00043 { 00044 TimerWord now = GetCurrentTimerValue(); 00045 if (m_last < now) // protect against OS bugs where time goes backwards 00046 m_last = now; 00047 return ConvertTo(m_last - m_start, m_timerUnit); 00048 } 00049 00050 StartTimer(); 00051 return 0; 00052 } 00053 00054 unsigned long TimerBase::ElapsedTime() 00055 { 00056 double elapsed = ElapsedTimeAsDouble(); 00057 assert(elapsed <= ULONG_MAX); 00058 return (unsigned long)elapsed; 00059 } 00060 00061 TimerWord Timer::GetCurrentTimerValue() 00062 { 00063 #if defined(CRYPTOPP_WIN32_AVAILABLE) 00064 LARGE_INTEGER now; 00065 if (!QueryPerformanceCounter(&now)) 00066 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError())); 00067 return now.QuadPart; 00068 #elif defined(CRYPTOPP_UNIX_AVAILABLE) 00069 timeval now; 00070 gettimeofday(&now, NULL); 00071 return (TimerWord)now.tv_sec * 1000000 + now.tv_usec; 00072 #else 00073 clock_t now; 00074 return clock(); 00075 #endif 00076 } 00077 00078 TimerWord Timer::TicksPerSecond() 00079 { 00080 #if defined(CRYPTOPP_WIN32_AVAILABLE) 00081 static LARGE_INTEGER freq = {0}; 00082 if (freq.QuadPart == 0) 00083 { 00084 if (!QueryPerformanceFrequency(&freq)) 00085 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); 00086 } 00087 return freq.QuadPart; 00088 #elif defined(CRYPTOPP_UNIX_AVAILABLE) 00089 return 1000000; 00090 #else 00091 return CLOCKS_PER_SEC; 00092 #endif 00093 } 00094 00095 #endif // #ifndef CRYPTOPP_IMPORTS 00096 00097 TimerWord ThreadUserTimer::GetCurrentTimerValue() 00098 { 00099 #if defined(CRYPTOPP_WIN32_AVAILABLE) 00100 static bool getCurrentThreadImplemented = true; 00101 if (getCurrentThreadImplemented) 00102 { 00103 FILETIME now, ignored; 00104 if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now)) 00105 { 00106 DWORD lastError = GetLastError(); 00107 if (lastError == ERROR_CALL_NOT_IMPLEMENTED) 00108 { 00109 getCurrentThreadImplemented = false; 00110 goto GetCurrentThreadNotImplemented; 00111 } 00112 throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError)); 00113 } 00114 return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32); 00115 } 00116 GetCurrentThreadNotImplemented: 00117 return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC); 00118 #elif defined(CRYPTOPP_UNIX_AVAILABLE) 00119 tms now; 00120 times(&now); 00121 return now.tms_utime; 00122 #else 00123 return clock(); 00124 #endif 00125 } 00126 00127 TimerWord ThreadUserTimer::TicksPerSecond() 00128 { 00129 #if defined(CRYPTOPP_WIN32_AVAILABLE) 00130 return 10*1000*1000; 00131 #elif defined(CRYPTOPP_UNIX_AVAILABLE) 00132 static const long ticksPerSecond = sysconf(_SC_CLK_TCK); 00133 return ticksPerSecond; 00134 #else 00135 return CLOCKS_PER_SEC; 00136 #endif 00137 } 00138 00139 NAMESPACE_END