2727 * then also delete it in the license file.
2828 */
2929
30+ #include " mongo/platform/basic.h"
31+
3032#include " mongo/util/timer.h"
3133
34+ #include < ctime>
3235#include < limits>
36+ #if defined(MONGO_HAVE_HEADER_UNISTD_H)
37+ #include < unistd.h>
38+ #endif
39+
40+ #include " mongo/util/assert_util.h"
41+ #include " mongo/util/time_support.h"
3342
3443namespace mongo {
3544
36- // default value of 1 so that during startup initialization if referenced no division by zero
37- long long Timer::_countsPerSecond = 1 ;
45+ // Set default value to reflect "generic" timer implementation.
46+ // Define Timer::_countsPerSecond before static initializer "atstartuputil" to ensure correct
47+ // relative sequencing regardless of how _countsPerSecond is initialized (static or dynamic).
48+ long long Timer::_countsPerSecond = Timer::microsPerSecond;
3849
3950 namespace {
4051
@@ -43,19 +54,66 @@ namespace mongo {
4354 AtStartup ();
4455 } atstartuputil;
4556
46- #if defined(MONGO_TIMER_IMPL_WIN32)
57+ // "Generic" implementation for Timer::now().
58+ long long _timerNowGeneric () {
59+ return curTimeMicros64 ();
60+ }
61+
62+ // Function pointer to Timer::now() implementation.
63+ // Overridden in AtStartup() with better implementation where available.
64+ long long (*_timerNow)() = &_timerNowGeneric;
65+
66+ #if defined(_WIN32)
67+
68+ /* *
69+ * Windows-specific implementation of the
70+ * Timer class. Windows selects the best available timer, in its estimation, for
71+ * measuring time at high resolution. This may be the HPET of the TSC on x86 systems,
72+ * but is promised to be synchronized across processors, barring BIOS errors.
73+ */
74+ long long timerNowWindows () {
75+ LARGE_INTEGER i;
76+ fassert (16161 , QueryPerformanceCounter (&i));
77+ return i.QuadPart ;
78+ }
4779
4880 AtStartup::AtStartup () {
4981 LARGE_INTEGER x;
5082 bool ok = QueryPerformanceFrequency (&x);
5183 verify (ok);
5284 Timer::_countsPerSecond = x.QuadPart ;
85+ _timerNow = &timerNowWindows;
5386 }
5487
55- #elif defined(MONGO_TIMER_IMPL_POSIX_MONOTONIC_CLOCK)
88+ #elif defined(MONGO_HAVE_POSIX_MONOTONIC_CLOCK)
89+
90+ /* *
91+ * Implementation for timer on systems that support the
92+ * POSIX clock API and CLOCK_MONOTONIC clock.
93+ */
94+ long long timerNowPosixMonotonicClock () {
95+ timespec the_time;
96+ long long result;
97+
98+ fassert (16160 , !clock_gettime (CLOCK_MONOTONIC, &the_time));
99+
100+ // Safe for 292 years after the clock epoch, even if we switch to a signed time value.
101+ // On Linux, the monotonic clock's epoch is the UNIX epoch.
102+ result = static_cast <long long >(the_time.tv_sec );
103+ result *= Timer::nanosPerSecond;
104+ result += static_cast <long long >(the_time.tv_nsec );
105+ return result;
106+ }
56107
57108 AtStartup::AtStartup () {
109+ // If the monotonic clock is not available at runtime (sysconf() returns 0 or -1),
110+ // do not override the generic implementation or modify Timer::_countsPerSecond.
111+ if (sysconf (_SC_MONOTONIC_CLOCK) <= 0 ) {
112+ return ;
113+ }
114+
58115 Timer::_countsPerSecond = Timer::nanosPerSecond;
116+ _timerNow = &timerNowPosixMonotonicClock;
59117
60118 // Make sure that the current time relative to the (unspecified) epoch isn't already too
61119 // big to represent as a 64-bit count of nanoseconds.
@@ -65,17 +123,14 @@ namespace mongo {
65123 fassert (16162 , !clock_gettime (CLOCK_MONOTONIC, &the_time));
66124 fassert (16163 , static_cast <long long >(the_time.tv_sec ) < maxSecs);
67125 }
68-
69- #elif defined(MONGO_TIMER_IMPL_GENERIC)
70-
71- AtStartup::AtStartup () {
72- Timer::_countsPerSecond = Timer::microsPerSecond;
73- }
74-
75126#else
76- # error "Unknown mongo::Timer implementation"
127+ AtStartup::AtStartup () { }
77128#endif
78129
79130 } // namespace
80131
132+ long long Timer::now () const {
133+ return _timerNow ();
134+ }
135+
81136} // namespace mongo
0 commit comments