diff --git a/include/rocksdb/env.h b/include/rocksdb/env.h index 0b12de5c9..093292f66 100644 --- a/include/rocksdb/env.h +++ b/include/rocksdb/env.h @@ -257,6 +257,8 @@ class Env { // Returns the number of micro-seconds since some fixed point in time. Only // useful for computing deltas of time. + // However, it is often used as system time such as in GenericRateLimiter + // and other places so a port needs to return system time in order to work. virtual uint64_t NowMicros() = 0; // Returns the number of nano-seconds since some fixed point in time. Only diff --git a/port/win/env_win.cc b/port/win/env_win.cc index 610de9a53..70c68b8fb 100644 --- a/port/win/env_win.cc +++ b/port/win/env_win.cc @@ -1816,15 +1816,24 @@ class WinEnv : public Env { } virtual uint64_t NowMicros() override { - // all std::chrono clocks on windows have the same resolution that is only - // On Windows 8 and Windows 2012 Server - // GetSystemTimePreciseAsFileTime(¤t_time) can be used + // all std::chrono clocks on windows proved to return + // values that may repeat that is not good enough for some uses. + const int64_t c_UnixEpochStartTicks = 116444736000000000i64; + const int64_t c_FtToMicroSec = 10; + + // This interface needs to return system time and not + // just any microseconds because it is often used as an argument + // to TimedWait() on condition variable + FILETIME ftSystemTime; + GetSystemTimePreciseAsFileTime(&ftSystemTime); + LARGE_INTEGER li; - QueryPerformanceCounter(&li); - // Convert to nanoseconds first to avoid loss of precision - // and divide by frequency - li.QuadPart *= std::micro::den; - li.QuadPart /= perf_counter_frequency_; + li.LowPart = ftSystemTime.dwLowDateTime; + li.HighPart = ftSystemTime.dwHighDateTime; + // Subtract unix epoch start + li.QuadPart -= c_UnixEpochStartTicks; + // Convert to microsecs + li.QuadPart /= c_FtToMicroSec; return li.QuadPart; } diff --git a/port/win/port_win.cc b/port/win/port_win.cc index 75cf36c2b..b0fb595ad 100644 --- a/port/win/port_win.cc +++ b/port/win/port_win.cc @@ -88,13 +88,16 @@ bool CondVar::TimedWait(uint64_t abs_time_us) { using namespace std::chrono; + // MSVC++ library implements wait_until in terms of wait_for so + // there is not an absolute wait anyway. microseconds usAbsTime(abs_time_us); + microseconds usNow( duration_cast(system_clock::now().time_since_epoch())); microseconds relTimeUs = (usAbsTime > usNow) ? (usAbsTime - usNow) : microseconds::zero(); - std::_Cv_status cvStatus = cv_.wait_for(mu_->getLock(), relTimeUs); + std::cv_status cvStatus = cv_.wait_for(mu_->getLock(), relTimeUs); #ifndef NDEBUG mu_->locked_ = true;