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