On Jan 1, 2017, at 3:20 PM, Saleem Abdulrasool via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > Author: compnerd > Date: Sun Jan 1 14:20:41 2017 > New Revision: 290803 > > URL: http://llvm.org/viewvc/llvm-project?rev=290803&view=rev > Log: > chrono: implement a Windows version of system_clock::now > > system_clock::now is not entirely straight forward on Windows, which > does not have a clock_gettime function. > > GetSystemTimeAsFileTime gives us the value relative to the NT epoch (Jan > 1 1601) rather than the Unix epoch (Jan 1 1970). However, this function > has a low resolution (~10ms). Newer versions of Windows provide > GetSystemTimePreciseAsFileTime which gives us a much more accurate time > (<1us). Unfortunately, the latter is only available on Windows 8+ when > targeting desktop apps. > > Modified: > libcxx/trunk/src/chrono.cpp > > Modified: libcxx/trunk/src/chrono.cpp > URL: > http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/chrono.cpp?rev=290803&r1=290802&r2=290803&view=diff > ============================================================================== > --- libcxx/trunk/src/chrono.cpp (original) > +++ libcxx/trunk/src/chrono.cpp Sun Jan 1 14:20:41 2017 > @@ -12,9 +12,18 @@ > #include "system_error" // __throw_system_error > #include <time.h> // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME > > +#if defined(_WIN32) > +#define WIN32_LEAN_AND_MEAN > +#define VC_EXTRA_LEAN > +#include <Windows.h> > +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 > +#include <winapifamily.h> > +#endif > +#else > #if !defined(CLOCK_REALTIME) > #include <sys/time.h> // for gettimeofday and timeval > #endif > +#endif > > #if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK) && !defined(CLOCK_MONOTONIC) > #if __APPLE__ > @@ -36,6 +45,28 @@ const bool system_clock::is_steady; > system_clock::time_point > system_clock::now() _NOEXCEPT > { > +#if defined(_WIN32) > + // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970. The > difference > + // in nanoseconds is the windows epoch offset. > + static const constexpr __int64 kWindowsEpochOffset = 0x19db1ded53e8000;
This is the correct difference, but the comment is wrong. It isn’t nanoseconds. It is 100ns units. > + > + FILETIME ftSystemTime; > +#if _WIN32_WINNT >= _WIN32_WINNT_WIN8 > +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) > + GetSystemTimePreciseAsFileTime(&ftSystemTime); > +#else > + GetSystemTimeAsFileTime(&ftSystemTime); > +#endif > +#else > + GetSystemTimeAsFileTime(&ftSystemTime); > +#endif > + __int64 llWinTimeNS = > + ((static_cast<__int64>(ftSystemTime.dwHighDateTime) << 32) | > + static_cast<__int64>(ftSystemTime.dwLowDateTime)) * > + 100; The * 100 will overflow. The * 100 converts 100ns to ns. ns has a signed 64bit range of +/- 292 years, which is greater than the difference between the two epochs. > + return time_point(duration_cast<duration>( > + (nanoseconds(llWinTimeNS - kWindowsEpochOffset)))); It really isn’t desirable to bounce this off of nanoseconds because of the overflow. > +#else > #ifdef CLOCK_REALTIME > struct timespec tp; > if (0 != clock_gettime(CLOCK_REALTIME, &tp)) > @@ -46,6 +77,7 @@ system_clock::now() _NOEXCEPT > gettimeofday(&tv, 0); > return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec)); > #endif // CLOCK_REALTIME > +#endif > } Thank you for preserving the 1970 epoch. Though not currently specified by the standard, it is very important. And hopefully will be specified by a future standard. Here is code written by Billy O’Neal (MS) doing the conversion you’re looking for: https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#FILETIME It has no intermediate results with precision finer than 100ns. The range of the 64bit 100ns unit goes out to +/- 29 thousand years. Howard _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits