diff options
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | hrtimer.cpp | 65 | ||||
-rw-r--r-- | hrtimer.h | 35 |
3 files changed, 74 insertions, 28 deletions
@@ -193,7 +193,7 @@ NAMESPACE_END #define CRYPTOPP_UNIX_AVAILABLE #endif -#if defined(WORD64_AVAILABLE) && (defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) || defined(macintosh)) +#if defined(WORD64_AVAILABLE) && (defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)) # define HIGHRES_TIMER_AVAILABLE #endif diff --git a/hrtimer.cpp b/hrtimer.cpp index 24fb6f9..7da494f 100644 --- a/hrtimer.cpp +++ b/hrtimer.cpp @@ -11,8 +11,7 @@ #include <windows.h> #elif defined(CRYPTOPP_UNIX_AVAILABLE) #include <sys/time.h> -#elif defined(macintosh) -#include <Timer.h> +#include <unistd.h> #endif #include <assert.h> @@ -30,10 +29,6 @@ word64 Timer::GetCurrentTimerValue() timeval now; gettimeofday(&now, NULL); return (word64)now.tv_sec * 1000000 + now.tv_usec; -#elif defined(macintosh) - UnsignedWide now; - Microseconds(&now); - return now.lo + ((word64)now.hi << 32); #endif } @@ -47,32 +42,64 @@ word64 Timer::TicksPerSecond() throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); } return freq.QuadPart; -#elif defined(CRYPTOPP_UNIX_AVAILABLE) || defined(macintosh) +#elif defined(CRYPTOPP_UNIX_AVAILABLE) return 1000000; #endif } -word64 Timer::ConvertTo(word64 t, Unit unit) +word64 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 + ((word64)now.dwHighDateTime << 32); + } +GetCurrentThreadNotImplemented: + return (word64)clock() * (10*1000*1000 / CLOCKS_PER_SEC); +#elif defined(CRYPTOPP_UNIX_AVAILABLE) + tms now; + times(&now); + return now.tms_utime; +#endif +} + +word64 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; +#endif +} + +double TimerBase::ConvertTo(word64 t, Unit unit) { static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000}; assert(unit < sizeof(unitsPerSecondTable) / sizeof(unitsPerSecondTable[0])); - unsigned long unitsPerSecond = unitsPerSecondTable[unit]; - const word64 freq = TicksPerSecond(); - - if (freq % unitsPerSecond == 0) - return t / (freq / unitsPerSecond); - else - return word64((double)t * unitsPerSecond / freq); + return (double)t * unitsPerSecondTable[unit] / TicksPerSecond(); } -void Timer::StartTimer() +void TimerBase::StartTimer() { m_start = GetCurrentTimerValue(); m_started = true; } -word64 Timer::ElapsedTimeInWord64() +double TimerBase::ElapsedTimeAsDouble() { if (m_stuckAtZero) return 0; @@ -85,9 +112,9 @@ word64 Timer::ElapsedTimeInWord64() } } -unsigned long Timer::ElapsedTime() +unsigned long TimerBase::ElapsedTime() { - word64 elapsed = ElapsedTimeInWord64(); + double elapsed = ElapsedTimeAsDouble(); assert(elapsed <= ULONG_MAX); return (unsigned long)elapsed; } @@ -7,28 +7,47 @@ NAMESPACE_BEGIN(CryptoPP) #ifdef HIGHRES_TIMER_AVAILABLE -//! high resolution timer -class Timer +class TimerBase { public: enum Unit {SECONDS = 0, MILLISECONDS, MICROSECONDS, NANOSECONDS}; - Timer(Unit unit, bool stuckAtZero = false) : m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false) {} + TimerBase(Unit unit, bool stuckAtZero) : m_timerUnit(unit), m_stuckAtZero(stuckAtZero), m_started(false) {} - static word64 GetCurrentTimerValue(); // GetCurrentTime is a macro in MSVC 6.0 - static word64 ConvertTo(word64 t, Unit unit); - // this is not the resolution, just a conversion factor into seconds - static word64 TicksPerSecond(); + virtual word64 GetCurrentTimerValue() =0; // GetCurrentTime is a macro in MSVC 6.0 + virtual word64 TicksPerSecond() =0; // this is not the resolution, just a conversion factor into seconds void StartTimer(); - word64 ElapsedTimeInWord64(); + double ElapsedTimeAsDouble(); unsigned long ElapsedTime(); private: + double ConvertTo(word64 t, Unit unit); + Unit m_timerUnit; // HPUX workaround: m_unit is a system macro on HPUX bool m_stuckAtZero, m_started; word64 m_start; }; +//! high resolution timer +class Timer : public TimerBase +{ +public: + Timer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {} + word64 GetCurrentTimerValue(); + word64 TicksPerSecond(); +}; + +//! measure CPU time spent executing instructions of this thread (if supported by OS) +/*! /note This only works correctly on Windows NT or later. On Unix it reports process time, and on Windows 98 wall clock time. +*/ +class ThreadUserTimer : public TimerBase +{ +public: + ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {} + word64 GetCurrentTimerValue(); + word64 TicksPerSecond(); +}; + #endif NAMESPACE_END |