Skip to content

Commit e34d23f

Browse files
authored
Merge pull request #76310 from al45tair/eng/PR-135413803
[Windows][Concurrency] Use the same clock as Dispatch.
2 parents 080c20c + 8e91ae4 commit e34d23f

File tree

2 files changed

+17
-39
lines changed

2 files changed

+17
-39
lines changed

stdlib/public/Concurrency/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ set(SWIFT_RUNTIME_CONCURRENCY_SWIFT_FLAGS -I${CMAKE_CURRENT_SOURCE_DIR}/Internal
1515

1616
set(swift_concurrency_private_link_libraries)
1717
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
18-
list(APPEND swift_concurrency_private_link_libraries Synchronization)
18+
list(APPEND swift_concurrency_private_link_libraries
19+
Synchronization
20+
mincore.lib # For QueryInterruptTime()
21+
)
1922
endif()
2023

2124
set(swift_concurrency_incorporate_object_libraries_so swiftThreading)

stdlib/public/Concurrency/Clock.cpp

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,15 @@ void swift_get_time(
4141
#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__))
4242
clock_gettime(CLOCK_MONOTONIC, &continuous);
4343
#elif defined(_WIN32)
44-
LARGE_INTEGER freq;
45-
QueryPerformanceFrequency(&freq);
46-
LARGE_INTEGER count;
47-
QueryPerformanceCounter(&count);
48-
// Divide count (number of ticks) by frequency (number of ticks per
49-
// second) to get the counter in seconds. We also need to multiply the
50-
// count by 1,000,000,000 to get nanosecond resolution. By multiplying
51-
// first, we maintain high precision. The resulting value is the tick
52-
// count in nanoseconds. Use 128-bit math to avoid overflowing.
53-
auto quadPart = static_cast<unsigned _BitInt(128)>(count.QuadPart);
54-
auto ns = (quadPart * 1'000'000'000) / freq.QuadPart;
55-
continuous.tv_sec = ns / 1'000'000'000;
56-
continuous.tv_nsec = ns % 1'000'000'000;
44+
// This needs to match what swift-corelibs-libdispatch does
45+
46+
// QueryInterruptTimePrecise() outputs a value measured in 100ns
47+
// units. We must divide the output by 10,000,000 to get a value in
48+
// seconds and multiply the remainder by 100 to get nanoseconds.
49+
ULONGLONG interruptTime;
50+
(void)QueryInterruptTimePrecise(&interruptTime);
51+
continuous.tv_sec = interruptTime / 10'000'000;
52+
continuous.tv_nsec = (interruptTime % 10'000'000) * 100;
5753
#else
5854
#error Missing platform continuous time definition
5955
#endif
@@ -72,32 +68,13 @@ void swift_get_time(
7268
#elif (defined(__OpenBSD__) || defined(__FreeBSD__))
7369
clock_gettime(CLOCK_UPTIME, &suspending);
7470
#elif defined(_WIN32)
75-
// QueryUnbiasedInterruptTimePrecise() was added in Windows 10 and is, as
76-
// the name suggests, more precise than QueryUnbiasedInterruptTime().
77-
// Unfortunately, the symbol is not listed in any .lib file in the SDK and
78-
// must be looked up dynamically at runtime even if our minimum deployment
79-
// target is Windows 10.
80-
typedef decltype(QueryUnbiasedInterruptTimePrecise) *QueryUITP_FP;
81-
static QueryUITP_FP queryUITP = nullptr;
82-
static swift::once_t onceToken;
83-
swift::once(onceToken, [] {
84-
if (HMODULE hKernelBase = GetModuleHandleW(L"KernelBase.dll")) {
85-
queryUITP = reinterpret_cast<QueryUITP_FP>(
86-
GetProcAddress(hKernelBase, "QueryUnbiasedInterruptTimePrecise")
87-
);
88-
}
89-
});
71+
// This needs to match what swift-corelibs-libdispatch does
9072

91-
// Call whichever API is available. Both output a value measured in 100ns
73+
// QueryUnbiasedInterruptTimePrecise() outputs a value measured in 100ns
9274
// units. We must divide the output by 10,000,000 to get a value in
9375
// seconds and multiply the remainder by 100 to get nanoseconds.
9476
ULONGLONG unbiasedTime;
95-
if (queryUITP) {
96-
(* queryUITP)(&unbiasedTime);
97-
} else {
98-
// Fall back to the older, less precise API.
99-
(void)QueryUnbiasedInterruptTime(&unbiasedTime);
100-
}
77+
(void)QueryUnbiasedInterruptTimePrecise(&unbiasedTime);
10178
suspending.tv_sec = unbiasedTime / 10'000'000;
10279
suspending.tv_nsec = (unbiasedTime % 10'000'000) * 100;
10380
#else
@@ -128,10 +105,8 @@ switch (clock_id) {
128105
#elif (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__wasi__))
129106
clock_getres(CLOCK_MONOTONIC, &continuous);
130107
#elif defined(_WIN32)
131-
LARGE_INTEGER freq;
132-
QueryPerformanceFrequency(&freq);
133108
continuous.tv_sec = 0;
134-
continuous.tv_nsec = 1'000'000'000 / freq.QuadPart;
109+
continuous.tv_nsec = 100;
135110
#else
136111
#error Missing platform continuous time definition
137112
#endif

0 commit comments

Comments
 (0)