Crypto++  8.8
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 
31 NAMESPACE_BEGIN(CryptoPP)
32 
33 #if defined(CRYPTOPP_WIN32_AVAILABLE)
34 static 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 
42 inline TimerWord PerformanceCounterFrequency()
43 {
44  static const word64 freq = InitializePerformanceCounterFrequency();
45  return freq;
46 }
47 #endif
48 
49 #ifndef CRYPTOPP_IMPORTS
50 
51 double 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 
83 unsigned 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  }
140 GetCurrentThreadNotImplemented:
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 
174 NAMESPACE_END
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:164
@ OTHER_ERROR
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:182
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:101
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:193
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
Definition: misc.h:929
Crypto++ library namespace.
Precompiled header file.
Debugging and diagnostic assertions.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68