source: trunk/src-cryptopp/hrtimer.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 4.7 KB
Line 
1// hrtimer.cpp - 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#ifndef CRYPTOPP_IMPORTS
34
35#if defined(CRYPTOPP_WIN32_AVAILABLE)
36static TimerWord InitializePerformanceCounterFrequency()
37{
38        LARGE_INTEGER freq = {0,0};
39        if (!QueryPerformanceFrequency(&freq))
40                throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError()));
41        return freq.QuadPart;
42}
43
44inline TimerWord PerformanceCounterFrequency()
45{
46        static const word64 freq = InitializePerformanceCounterFrequency();
47        return freq;
48}
49#endif
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 (double)CRYPTOPP_VC6_INT64 t * unitsPerSecondTable[unit] / CRYPTOPP_VC6_INT64 TicksPerSecond();
58}
59
60void TimerBase::StartTimer()
61{
62        m_last = m_start = GetCurrentTimerValue();
63        m_started = true;
64}
65
66double TimerBase::ElapsedTimeAsDouble()
67{
68        if (m_stuckAtZero)
69                return 0;
70
71        if (m_started)
72        {
73                TimerWord now = GetCurrentTimerValue();
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
90TimerWord Timer::GetCurrentTimerValue()
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, NULL);
101        return (TimerWord)now.tv_sec * 1000000 + now.tv_usec;
102#else
103        // clock_t now;
104        return clock();
105#endif
106}
107
108TimerWord Timer::TicksPerSecond()
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
121TimerWord ThreadUserTimer::GetCurrentTimerValue()
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
159TimerWord ThreadUserTimer::TicksPerSecond()
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
Note: See TracBrowser for help on using the repository browser.