00001
00002
00003 #include "pch.h"
00004 #include "hrtimer.h"
00005 #include "misc.h"
00006 #include <stddef.h>
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
00028 assert(static_cast<unsigned int>(unit) < COUNTOF(unitsPerSecondTable));
00029 return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
00030 }
00031
00032 void TimerBase::StartTimer()
00033 {
00034 m_last = m_start = GetCurrentTimerValue();
00035 m_started = true;
00036 }
00037
00038 double TimerBase::ElapsedTimeAsDouble()
00039 {
00040 if (m_stuckAtZero)
00041 return 0;
00042
00043 if (m_started)
00044 {
00045 TimerWord now = GetCurrentTimerValue();
00046 if (m_last < now)
00047 m_last = now;
00048 return ConvertTo(m_last - m_start, m_timerUnit);
00049 }
00050
00051 StartTimer();
00052 return 0;
00053 }
00054
00055 unsigned long TimerBase::ElapsedTime()
00056 {
00057 double elapsed = ElapsedTimeAsDouble();
00058 assert(elapsed <= ULONG_MAX);
00059 return (unsigned long)elapsed;
00060 }
00061
00062 TimerWord Timer::GetCurrentTimerValue()
00063 {
00064 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00065
00066 LARGE_INTEGER now = {0,0};
00067 if (!QueryPerformanceCounter(&now))
00068 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
00069 return now.QuadPart;
00070 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00071 timeval now;
00072 gettimeofday(&now, NULL);
00073 return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
00074 #else
00075
00076 return clock();
00077 #endif
00078 }
00079
00080 TimerWord Timer::TicksPerSecond()
00081 {
00082 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00083
00084 static LARGE_INTEGER freq = {0,0};
00085 if (freq.QuadPart == 0)
00086 {
00087 if (!QueryPerformanceFrequency(&freq))
00088 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
00089 }
00090 return freq.QuadPart;
00091 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00092 return 1000000;
00093 #else
00094 return CLOCKS_PER_SEC;
00095 #endif
00096 }
00097
00098 #endif // #ifndef CRYPTOPP_IMPORTS
00099
00100 TimerWord ThreadUserTimer::GetCurrentTimerValue()
00101 {
00102 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00103 static bool getCurrentThreadImplemented = true;
00104 if (getCurrentThreadImplemented)
00105 {
00106 FILETIME now, ignored;
00107 if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
00108 {
00109 DWORD lastError = GetLastError();
00110 if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
00111 {
00112 getCurrentThreadImplemented = false;
00113 goto GetCurrentThreadNotImplemented;
00114 }
00115 throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
00116 }
00117 return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
00118 }
00119 GetCurrentThreadNotImplemented:
00120 return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
00121 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00122 tms now;
00123 times(&now);
00124 return now.tms_utime;
00125 #else
00126 return clock();
00127 #endif
00128 }
00129
00130 TimerWord ThreadUserTimer::TicksPerSecond()
00131 {
00132 #if defined(CRYPTOPP_WIN32_AVAILABLE)
00133 return 10*1000*1000;
00134 #elif defined(CRYPTOPP_UNIX_AVAILABLE)
00135 static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
00136 return ticksPerSecond;
00137 #else
00138 return CLOCKS_PER_SEC;
00139 #endif
00140 }
00141
00142 NAMESPACE_END