You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.3 KiB
139 lines
3.3 KiB
// hrtimer.cpp - written and placed in the public domain by Wei Dai |
|
|
|
#include "pch.h" |
|
#include "hrtimer.h" |
|
#include "misc.h" |
|
#include <stddef.h> // for NULL |
|
#include <time.h> |
|
|
|
#if defined(CRYPTOPP_WIN32_AVAILABLE) |
|
#include <windows.h> |
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE) |
|
#include <sys/time.h> |
|
#include <sys/times.h> |
|
#include <unistd.h> |
|
#endif |
|
|
|
#include <assert.h> |
|
|
|
NAMESPACE_BEGIN(CryptoPP) |
|
|
|
#ifndef CRYPTOPP_IMPORTS |
|
|
|
double TimerBase::ConvertTo(TimerWord t, Unit unit) |
|
{ |
|
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000}; |
|
|
|
assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0])); |
|
return (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond(); |
|
} |
|
|
|
void TimerBase::StartTimer() |
|
{ |
|
m_last = m_start = GetCurrentTimerValue(); |
|
m_started = true; |
|
} |
|
|
|
double TimerBase::ElapsedTimeAsDouble() |
|
{ |
|
if (m_stuckAtZero) |
|
return 0; |
|
|
|
if (m_started) |
|
{ |
|
TimerWord now = GetCurrentTimerValue(); |
|
if (m_last < now) // protect against OS bugs where time goes backwards |
|
m_last = now; |
|
return ConvertTo(m_last - m_start, m_timerUnit); |
|
} |
|
|
|
StartTimer(); |
|
return 0; |
|
} |
|
|
|
unsigned long TimerBase::ElapsedTime() |
|
{ |
|
double elapsed = ElapsedTimeAsDouble(); |
|
assert(elapsed <= ULONG_MAX); |
|
return (unsigned long)elapsed; |
|
} |
|
|
|
TimerWord Timer::GetCurrentTimerValue() |
|
{ |
|
#if defined(CRYPTOPP_WIN32_AVAILABLE) |
|
LARGE_INTEGER now; |
|
if (!QueryPerformanceCounter(&now)) |
|
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError())); |
|
return now.QuadPart; |
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE) |
|
timeval now; |
|
gettimeofday(&now, NULL); |
|
return (TimerWord)now.tv_sec * 1000000 + now.tv_usec; |
|
#else |
|
clock_t now; |
|
return clock(); |
|
#endif |
|
} |
|
|
|
TimerWord Timer::TicksPerSecond() |
|
{ |
|
#if defined(CRYPTOPP_WIN32_AVAILABLE) |
|
static LARGE_INTEGER freq = {0}; |
|
if (freq.QuadPart == 0) |
|
{ |
|
if (!QueryPerformanceFrequency(&freq)) |
|
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); |
|
} |
|
return freq.QuadPart; |
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE) |
|
return 1000000; |
|
#else |
|
return CLOCKS_PER_SEC; |
|
#endif |
|
} |
|
|
|
#endif // #ifndef CRYPTOPP_IMPORTS |
|
|
|
TimerWord ThreadUserTimer::GetCurrentTimerValue() |
|
{ |
|
#if defined(CRYPTOPP_WIN32_AVAILABLE) |
|
static bool getCurrentThreadImplemented = true; |
|
if (getCurrentThreadImplemented) |
|
{ |
|
FILETIME now, ignored; |
|
if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now)) |
|
{ |
|
DWORD lastError = GetLastError(); |
|
if (lastError == ERROR_CALL_NOT_IMPLEMENTED) |
|
{ |
|
getCurrentThreadImplemented = false; |
|
goto GetCurrentThreadNotImplemented; |
|
} |
|
throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError)); |
|
} |
|
return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32); |
|
} |
|
GetCurrentThreadNotImplemented: |
|
return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC); |
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE) |
|
tms now; |
|
times(&now); |
|
return now.tms_utime; |
|
#else |
|
return clock(); |
|
#endif |
|
} |
|
|
|
TimerWord ThreadUserTimer::TicksPerSecond() |
|
{ |
|
#if defined(CRYPTOPP_WIN32_AVAILABLE) |
|
return 10*1000*1000; |
|
#elif defined(CRYPTOPP_UNIX_AVAILABLE) |
|
static const long ticksPerSecond = sysconf(_SC_CLK_TCK); |
|
return ticksPerSecond; |
|
#else |
|
return CLOCKS_PER_SEC; |
|
#endif |
|
} |
|
|
|
NAMESPACE_END
|
|
|