6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
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
+
11
11
#include " src/__support/CPP/atomic.h"
12
12
#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"
13
16
#include " src/__support/time/units.h"
14
- #include < Windows.h>
15
17
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>
21
21
22
22
namespace LIBC_NAMESPACE_DECL {
23
23
namespace internal {
24
24
static long long get_ticks_per_second () {
25
25
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.
26
29
auto freq = frequency.load (cpp::MemoryOrder::RELAXED);
27
30
if (!freq) {
28
- UNINITIALIZED LARGE_INTEGER buffer;
31
+ [[clang::uninitialized]] LARGE_INTEGER buffer;
29
32
// On systems that run Windows XP or later, the function will always
30
33
// succeed and will thus never return zero.
31
34
::QueryPerformanceFrequency (&buffer);
@@ -37,6 +40,8 @@ static long long get_ticks_per_second() {
37
40
38
41
ErrorOr<int > clock_gettime (clockid_t clockid, timespec *ts) {
39
42
using namespace time_units ;
43
+ constexpr long long SEC_LIMIT =
44
+ cpp::numeric_limits<decltype (ts->tv_sec )>::max ();
40
45
ErrorOr<int > ret = 0 ;
41
46
switch (clockid) {
42
47
default :
@@ -48,14 +53,18 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
48
53
// https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps
49
54
// Is the performance counter monotonic (non-decreasing)?
50
55
// Yes. QPC does not go backward.
51
- UNINITIALIZED LARGE_INTEGER buffer;
56
+ [[clang::uninitialized]] LARGE_INTEGER buffer;
52
57
// On systems that run Windows XP or later, the function will always
53
58
// succeed and will thus never return zero.
54
59
::QueryPerformanceCounter (&buffer);
55
60
long long freq = get_ticks_per_second ();
56
61
long long ticks = buffer.QuadPart ;
57
62
long long tv_sec = ticks / freq;
58
63
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
+ }
59
68
ts->tv_sec = static_cast <decltype (ts->tv_sec )>(tv_sec);
60
69
ts->tv_nsec = static_cast <decltype (ts->tv_nsec )>(tv_nsec);
61
70
break ;
@@ -65,17 +74,27 @@ ErrorOr<int> clock_gettime(clockid_t clockid, timespec *ts) {
65
74
// GetSystemTimePreciseAsFileTime
66
75
// This function is best suited for high-resolution time-of-day
67
76
// 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;
70
79
::GetSystemTimePreciseAsFileTime (&file_time);
71
80
time.LowPart = file_time.dwLowDateTime ;
72
81
time.HighPart = file_time.dwHighDateTime ;
73
82
74
83
// adjust to POSIX epoch (from Jan 1, 1601 to Jan 1, 1970)
75
84
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
+ }
76
91
time.QuadPart -= (11644473600ULL * HNS_PER_SEC);
77
92
unsigned long long tv_sec = time.QuadPart / HNS_PER_SEC;
78
93
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
+ }
79
98
ts->tv_sec = static_cast <decltype (ts->tv_sec )>(tv_sec);
80
99
ts->tv_nsec = static_cast <decltype (ts->tv_nsec )>(tv_nsec);
81
100
break ;
0 commit comments