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