66//
77// ===----------------------------------------------------------------------===//
88
9- #include " src/__support/time/clock_gettime .h"
10- # include " include/llvm-libc-macros/windows/time-macros-ext.h "
9+ #include " hdr/time_macros .h"
10+
1111#include " src/__support/CPP/atomic.h"
1212#include " src/__support/CPP/bit.h"
13+ #include " src/__support/CPP/limits.h"
14+ #include " src/__support/macros/optimization.h"
15+ #include " src/__support/time/clock_gettime.h"
1316#include " src/__support/time/units.h"
14- #include < Windows.h>
1517
16- #ifdef __clang__
17- #define UNINITIALIZED [[clang::uninitialized]]
18- #else
19- #define UNINITIALIZED
20- #endif
18+ #define WIN32_LEAN_AND_MEAN
19+ #define NOMINMAX
20+ #include < Windows.h>
2121
2222namespace LIBC_NAMESPACE_DECL {
2323namespace internal {
2424static long long get_ticks_per_second () {
2525 static cpp::Atomic<long long > frequency = 0 ;
26+ // Relaxed ordering is enough. It is okay to record the frequency multiple
27+ // times. The store operation itself is atomic and the value must propagate
28+ // as required by cache coherence.
2629 auto freq = frequency.load (cpp::MemoryOrder::RELAXED);
2730 if (!freq) {
28- UNINITIALIZED LARGE_INTEGER buffer;
31+ [[clang::uninitialized]] LARGE_INTEGER buffer;
2932 // On systems that run Windows XP or later, the function will always
3033 // succeed and will thus never return zero.
3134 ::QueryPerformanceFrequency (&buffer);
@@ -37,6 +40,8 @@ static long long get_ticks_per_second() {
3740
3841ErrorOr<int > clock_gettime (clockid_t clockid, timespec *ts) {
3942 using namespace time_units ;
43+ constexpr long long SEC_LIMIT =
44+ cpp::numeric_limits<decltype (ts->tv_sec )>::max ();
4045 ErrorOr<int > ret = 0 ;
4146 switch (clockid) {
4247 default :
@@ -48,14 +53,18 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
4853 // https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps
4954 // Is the performance counter monotonic (non-decreasing)?
5055 // Yes. QPC does not go backward.
51- UNINITIALIZED LARGE_INTEGER buffer;
56+ [[clang::uninitialized]] LARGE_INTEGER buffer;
5257 // On systems that run Windows XP or later, the function will always
5358 // succeed and will thus never return zero.
5459 ::QueryPerformanceCounter (&buffer);
5560 long long freq = get_ticks_per_second ();
5661 long long ticks = buffer.QuadPart ;
5762 long long tv_sec = ticks / freq;
5863 long long tv_nsec = (ticks % freq) * 1_s_ns / freq;
64+ if (LIBC_UNLIKELY (tv_sec > SEC_LIMIT)) {
65+ ret = cpp::unexpected (EOVERFLOW);
66+ break ;
67+ }
5968 ts->tv_sec = static_cast <decltype (ts->tv_sec )>(tv_sec);
6069 ts->tv_nsec = static_cast <decltype (ts->tv_nsec )>(tv_nsec);
6170 break ;
@@ -65,17 +74,27 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
6574 // GetSystemTimePreciseAsFileTime
6675 // This function is best suited for high-resolution time-of-day
6776 // measurements, or time stamps that are synchronized to UTC
68- UNINITIALIZED FILETIME file_time;
69- UNINITIALIZED ULARGE_INTEGER time;
77+ [[clang::uninitialized]] FILETIME file_time;
78+ [[clang::uninitialized]] ULARGE_INTEGER time;
7079 ::GetSystemTimePreciseAsFileTime (&file_time);
7180 time.LowPart = file_time.dwLowDateTime ;
7281 time.HighPart = file_time.dwHighDateTime ;
7382
7483 // adjust to POSIX epoch (from Jan 1, 1601 to Jan 1, 1970)
7584 constexpr unsigned long long HNS_PER_SEC = 1_s_ns / 100ULL ;
85+ constexpr unsigned long long POSIX_TIME_SHIFT =
86+ (11644473600ULL * HNS_PER_SEC);
87+ if (LIBC_UNLIKELY (POSIX_TIME_SHIFT > time.QuadPart )) {
88+ ret = cpp::unexpected (EOVERFLOW);
89+ break ;
90+ }
7691 time.QuadPart -= (11644473600ULL * HNS_PER_SEC);
7792 unsigned long long tv_sec = time.QuadPart / HNS_PER_SEC;
7893 unsigned long long tv_nsec = (time.QuadPart % HNS_PER_SEC) * 100ULL ;
94+ if (LIBC_UNLIKELY (tv_sec > SEC_LIMIT)) {
95+ ret = cpp::unexpected (EOVERFLOW);
96+ break ;
97+ }
7998 ts->tv_sec = static_cast <decltype (ts->tv_sec )>(tv_sec);
8099 ts->tv_nsec = static_cast <decltype (ts->tv_nsec )>(tv_nsec);
81100 break ;
0 commit comments