hrtimer.cpp
// hrtimer.cpp - originally 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)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
# include <processthreadsapi.h>
# if defined(WINAPI_FAMILY)
# if (WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP))
# include <profileapi.h>
# endif
# endif
#endif
#endif
#if defined(CRYPTOPP_UNIX_AVAILABLE)
#include <sys/time.h>
#include <sys/times.h>
#include <unistd.h>
#endif
#include "trap.h"
NAMESPACE_BEGIN(CryptoPP)
#if defined(CRYPTOPP_WIN32_AVAILABLE)
static TimerWord InitializePerformanceCounterFrequency()
{
LARGE_INTEGER freq = {{0,0}};
if (!QueryPerformanceFrequency(&freq))
throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
return freq.QuadPart;
}
inline TimerWord PerformanceCounterFrequency()
{
static const word64 freq = InitializePerformanceCounterFrequency();
return freq;
}
#endif
#ifndef CRYPTOPP_IMPORTS
double TimerBase::ConvertTo(TimerWord t, Unit unit)
{
static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
// When 'unit' is an enum 'Unit', a Clang warning is generated.
CRYPTOPP_ASSERT(static_cast<unsigned int>(unit) < COUNTOF(unitsPerSecondTable));
return static_cast<double>(t) * unitsPerSecondTable[unit] / 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();
CRYPTOPP_ASSERT(elapsed <= (double)ULONG_MAX);
return (unsigned long)elapsed;
}
TimerWord Timer::GetCurrentTimerValue()
{
#if defined(CRYPTOPP_WIN32_AVAILABLE)
// Use the first union member to avoid an uninitialized warning
LARGE_INTEGER now = {{0,0}};
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, NULLPTR);
return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
#else
// clock_t now;
return clock();
#endif
}
TimerWord Timer::TicksPerSecond()
{
#if defined(CRYPTOPP_WIN32_AVAILABLE)
return PerformanceCounterFrequency();
#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) && defined(THREAD_TIMER_AVAILABLE)
static bool getCurrentThreadImplemented = true;
if (getCurrentThreadImplemented)
{
FILETIME now, ignored;
if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
{
const 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_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)
LARGE_INTEGER now;
if (!QueryPerformanceCounter(&now))
{
const DWORD lastError = GetLastError();
throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: QueryPerformanceCounter failed with error " + IntToString(lastError));
}
return now.QuadPart;
#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) && defined(THREAD_TIMER_AVAILABLE)
return 10*1000*1000;
#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)
static const TimerWord ticksPerSecond = PerformanceCounterFrequency();
return ticksPerSecond;
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
return ticksPerSecond;
#else
return CLOCKS_PER_SEC;
#endif
}
NAMESPACE_END
Exception
Base class for all exceptions thrown by the library.
Definition cryptlib.h:164
Exception::OTHER_ERROR
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition cryptlib.h:182
ThreadUserTimer::GetCurrentTimerValue
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
Definition hrtimer.cpp:121
ThreadUserTimer::TicksPerSecond
TimerWord TicksPerSecond()
Retrieve ticks per second.
Definition hrtimer.cpp:159
TimerBase::ElapsedTimeAsDouble
double ElapsedTimeAsDouble()
Retrieve the elapsed time.
TimerBase::StartTimer
void StartTimer()
Start the timer.
TimerBase::TicksPerSecond
virtual TimerWord TicksPerSecond()=0
Retrieve ticks per second.
TimerBase::GetCurrentTimerValue
virtual TimerWord GetCurrentTimerValue()=0
Retrieve the current timer value.
TimerBase::ElapsedTime
unsigned long ElapsedTime()
Retrieve the elapsed time.
Timer::GetCurrentTimerValue
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
Timer::TicksPerSecond
TimerWord TicksPerSecond()
Retrieve ticks per second.
word64
unsigned long long word64
64-bit unsigned datatype
Definition config_int.h:101
hrtimer.h
Classes for timers.
TimerWord
word64 TimerWord
TimerWord is a 64-bit word.
Definition hrtimer.h:19
misc.h
Utility functions for the Crypto++ library.
COUNTOF
#define COUNTOF(arr)
Counts elements in an array.
Definition misc.h:193
IntToString
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition misc.h:929
CryptoPP
Crypto++ library namespace.
pch.h
Precompiled header file.
trap.h
Debugging and diagnostic assertions.
CRYPTOPP_ASSERT
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition trap.h:68