Crypto++ 8.7
Free C++ class library of cryptographic schemes
hrtimer.cpp
1// hrtimer.cpp - originally written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4#include "hrtimer.h"
5#include "misc.h"
6
7#include <stddef.h> // for NULL
8#include <time.h>
9
10#if defined(CRYPTOPP_WIN32_AVAILABLE)
11#define WIN32_LEAN_AND_MEAN
12#include <windows.h>
13# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
14# include <processthreadsapi.h>
15# if defined(WINAPI_FAMILY)
16# if (WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP))
17# include <profileapi.h>
18# endif
19# endif
20#endif
21#endif
22
23#if defined(CRYPTOPP_UNIX_AVAILABLE)
24#include <sys/time.h>
25#include <sys/times.h>
26#include <unistd.h>
27#endif
28
29#include "trap.h"
30
31NAMESPACE_BEGIN(CryptoPP)
32
33#if defined(CRYPTOPP_WIN32_AVAILABLE)
34static TimerWord InitializePerformanceCounterFrequency()
35{
36 LARGE_INTEGER freq = {0,0};
37 if (!QueryPerformanceFrequency(&freq))
38 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
39 return freq.QuadPart;
40}
41
42inline TimerWord PerformanceCounterFrequency()
43{
44 static const word64 freq = InitializePerformanceCounterFrequency();
45 return freq;
46}
47#endif
48
49#ifndef CRYPTOPP_IMPORTS
50
51double TimerBase::ConvertTo(TimerWord t, Unit unit)
52{
53 static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000};
54
55 // When 'unit' is an enum 'Unit', a Clang warning is generated.
56 CRYPTOPP_ASSERT(static_cast<unsigned int>(unit) < COUNTOF(unitsPerSecondTable));
57 return static_cast<double>(t) * unitsPerSecondTable[unit] / TicksPerSecond();
58}
59
61{
62 m_last = m_start = GetCurrentTimerValue();
63 m_started = true;
64}
65
67{
68 if (m_stuckAtZero)
69 return 0;
70
71 if (m_started)
72 {
74 if (m_last < now) // protect against OS bugs where time goes backwards
75 m_last = now;
76 return ConvertTo(m_last - m_start, m_timerUnit);
77 }
78
79 StartTimer();
80 return 0;
81}
82
83unsigned long TimerBase::ElapsedTime()
84{
85 double elapsed = ElapsedTimeAsDouble();
86 CRYPTOPP_ASSERT(elapsed <= (double)ULONG_MAX);
87 return (unsigned long)elapsed;
88}
89
91{
92#if defined(CRYPTOPP_WIN32_AVAILABLE)
93 // Use the first union member to avoid an uninitialized warning
94 LARGE_INTEGER now = {0,0};
95 if (!QueryPerformanceCounter(&now))
96 throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceCounter failed with error " + IntToString(GetLastError()));
97 return now.QuadPart;
98#elif defined(CRYPTOPP_UNIX_AVAILABLE)
99 timeval now;
100 gettimeofday(&now, NULLPTR);
101 return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
102#else
103 // clock_t now;
104 return clock();
105#endif
106}
107
109{
110#if defined(CRYPTOPP_WIN32_AVAILABLE)
111 return PerformanceCounterFrequency();
112#elif defined(CRYPTOPP_UNIX_AVAILABLE)
113 return 1000000;
114#else
115 return CLOCKS_PER_SEC;
116#endif
117}
118
119#endif // #ifndef CRYPTOPP_IMPORTS
120
122{
123#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE)
124 static bool getCurrentThreadImplemented = true;
125 if (getCurrentThreadImplemented)
126 {
127 FILETIME now, ignored;
128 if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now))
129 {
130 const DWORD lastError = GetLastError();
131 if (lastError == ERROR_CALL_NOT_IMPLEMENTED)
132 {
133 getCurrentThreadImplemented = false;
134 goto GetCurrentThreadNotImplemented;
135 }
136 throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: GetThreadTimes failed with error " + IntToString(lastError));
137 }
138 return now.dwLowDateTime + ((TimerWord)now.dwHighDateTime << 32);
139 }
140GetCurrentThreadNotImplemented:
141 return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC);
142#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)
143 LARGE_INTEGER now;
144 if (!QueryPerformanceCounter(&now))
145 {
146 const DWORD lastError = GetLastError();
147 throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: QueryPerformanceCounter failed with error " + IntToString(lastError));
148 }
149 return now.QuadPart;
150#elif defined(CRYPTOPP_UNIX_AVAILABLE)
151 tms now;
152 times(&now);
153 return now.tms_utime;
154#else
155 return clock();
156#endif
157}
158
160{
161#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE)
162 return 10*1000*1000;
163#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)
164 static const TimerWord ticksPerSecond = PerformanceCounterFrequency();
165 return ticksPerSecond;
166#elif defined(CRYPTOPP_UNIX_AVAILABLE)
167 static const long ticksPerSecond = sysconf(_SC_CLK_TCK);
168 return ticksPerSecond;
169#else
170 return CLOCKS_PER_SEC;
171#endif
172}
173
174NAMESPACE_END
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:159
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:177
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
Definition: hrtimer.cpp:121
TimerWord TicksPerSecond()
Retrieve ticks per second.
Definition: hrtimer.cpp:159
double ElapsedTimeAsDouble()
Retrieve the elapsed time.
void StartTimer()
Start the timer.
virtual TimerWord TicksPerSecond()=0
Retrieve ticks per second.
virtual TimerWord GetCurrentTimerValue()=0
Retrieve the current timer value.
unsigned long ElapsedTime()
Retrieve the elapsed time.
TimerWord GetCurrentTimerValue()
Retrieve the current timer value.
TimerWord TicksPerSecond()
Retrieve ticks per second.
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:91
Classes for timers.
word64 TimerWord
TimerWord is a 64-bit word.
Definition: hrtimer.h:19
Utility functions for the Crypto++ library.
#define COUNTOF(arr)
Counts elements in an array.
Definition: misc.h:191
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:724
Crypto++ library namespace.
Precompiled header file.
Debugging and diagnostic assertions.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68