Skip to content

Commit d2fa3a3

Browse files
Temporarily restore support for Win7 / Server 2008 R2 (#4857)
1 parent 6c32079 commit d2fa3a3

File tree

12 files changed

+590
-18
lines changed

12 files changed

+590
-18
lines changed

stl/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ function(add_stl_dlls D_SUFFIX REL_OR_DBG)
556556
generate_satellite_def("atomic_wait" "${D_SUFFIX}")
557557

558558
add_library(msvcp${D_SUFFIX}_atomic_wait SHARED "${CMAKE_BINARY_DIR}/msvcp_atomic_wait${D_SUFFIX}.def")
559-
target_link_libraries(msvcp${D_SUFFIX}_atomic_wait PRIVATE msvcp${D_SUFFIX}_atomic_wait_objects msvcp${D_SUFFIX}_satellite_objects msvcp${D_SUFFIX}_implib_objects "msvcp${D_SUFFIX}" "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib" "advapi32.lib" "synchronization.lib")
559+
target_link_libraries(msvcp${D_SUFFIX}_atomic_wait PRIVATE msvcp${D_SUFFIX}_atomic_wait_objects msvcp${D_SUFFIX}_satellite_objects msvcp${D_SUFFIX}_implib_objects "msvcp${D_SUFFIX}" "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib" "advapi32.lib")
560560
set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES ARCHIVE_OUTPUT_NAME "msvcp140_atomic_wait${D_SUFFIX}${VCLIBS_SUFFIX}")
561561
set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
562562
set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES OUTPUT_NAME "msvcp140${D_SUFFIX}_atomic_wait${VCLIBS_SUFFIX}")

stl/inc/xatomic_wait.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,23 @@ _STL_DISABLE_CLANG_WARNINGS
2121
extern "C" {
2222
inline constexpr unsigned long __std_atomic_wait_no_timeout = 0xFFFF'FFFF; // Pass as partial timeout
2323

24+
enum class __std_atomic_api_level : unsigned long {
25+
__not_set,
26+
__detecting,
27+
__has_srwlock,
28+
__has_wait_on_address,
29+
};
30+
31+
// This function allows testing the atomic wait support while always using the APIs for a platform with fewer
32+
// capabilities; it attempts to lock the APIs used to the level `_Requested_api_level`, and returns the actual API level
33+
// in use. Once the API level has been set by calling this function (or detected by a call to one of the atomic wait
34+
// functions), it can no longer be changed.
35+
__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level _Requested_api_level) noexcept;
36+
2437
// Support for atomic waits.
2538
// The "direct" functions are used when the underlying infrastructure can use WaitOnAddress directly; that is, _Size is
26-
// 1, 2, 4, or 8. The contract is the same as the WaitOnAddress function from the Windows SDK.
39+
// 1, 2, 4, or 8. The contract is the same as the WaitOnAddress function from the Windows SDK. If WaitOnAddress is not
40+
// available on the current platform, falls back to a similar solution based on SRWLOCK and CONDITION_VARIABLE.
2741
int __stdcall __std_atomic_wait_direct(
2842
const void* _Storage, void* _Comparand, size_t _Size, unsigned long _Remaining_timeout) noexcept;
2943
void __stdcall __std_atomic_notify_one_direct(const void* _Storage) noexcept;

stl/inc/yvals_core.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1939,6 +1939,7 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error.
19391939
#endif // defined(MRTDLL) && !defined(_M_CEE_PURE)
19401940

19411941
#define _STL_WIN32_WINNT_VISTA 0x0600 // _WIN32_WINNT_VISTA from sdkddkver.h
1942+
#define _STL_WIN32_WINNT_WIN7 0x0601 // _WIN32_WINNT_WIN7 from sdkddkver.h
19421943
#define _STL_WIN32_WINNT_WIN8 0x0602 // _WIN32_WINNT_WIN8 from sdkddkver.h
19431944
#define _STL_WIN32_WINNT_WIN10 0x0A00 // _WIN32_WINNT_WIN10 from sdkddkver.h
19441945

@@ -1947,10 +1948,13 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error.
19471948
#if defined(_M_ARM64)
19481949
// The first ARM64 Windows was Windows 10
19491950
#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN10
1950-
#else // ^^^ defined(_M_ARM64) / !defined(_M_ARM64) vvv
1951-
// The earliest Windows supported by this implementation is Windows 8
1951+
#elif defined(_M_ARM) || defined(_ONECORE) || defined(_CRT_APP)
1952+
// The first ARM or OneCore or App Windows was Windows 8
19521953
#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN8
1953-
#endif // ^^^ !defined(_M_ARM64) ^^^
1954+
#else // ^^^ default to Win8 / default to Win7 vvv
1955+
// The earliest Windows supported by this implementation is Windows 7
1956+
#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN7
1957+
#endif // ^^^ !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_ONECORE) && !defined(_CRT_APP) ^^^
19541958
#endif // !defined(_STL_WIN32_WINNT)
19551959

19561960
#ifdef __cpp_noexcept_function_type

stl/msbuild/stl_atomic_wait/msvcp_atomic_wait.settings.targets

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7070
<TargetLib Include="$(CrtLibPath)\vcruntime$(BuildSuffix)$(ClrLibSuffix).lib"/>
7171
<TargetLib Include="$(UniversalCRTLib)"/>
7272
<TargetLib Condition="'$(MsvcpFlavor)' == 'kernel32' or '$(MsvcpFlavor)' == 'netfx'" Include="$(SdkLibPath)\advapi32.lib"/>
73-
<TargetLib Condition="'$(MsvcpFlavor)' == 'kernel32' or '$(MsvcpFlavor)' == 'netfx'" Include="$(SdkLibPath)\synchronization.lib"/>
7473
</ItemGroup>
7574

7675
<!-- Copy the output dll and pdb to various destinations -->

stl/src/atomic_wait.cpp

Lines changed: 157 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
#include <Windows.h>
1313

14-
#pragma comment(lib, "synchronization")
15-
1614
namespace {
1715
constexpr unsigned long long _Atomic_wait_no_deadline = 0xFFFF'FFFF'FFFF'FFFF;
1816

@@ -91,13 +89,134 @@ namespace {
9189
}
9290
#endif // defined(_DEBUG)
9391
}
92+
93+
#ifndef _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
94+
#if _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8
95+
#define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 1
96+
#else // ^^^ _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 vvv
97+
#define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 0
98+
#endif // ^^^ _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 ^^^
99+
#endif // !defined(_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE)
100+
101+
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
102+
103+
#pragma comment(lib, "synchronization")
104+
105+
#define __crtWaitOnAddress WaitOnAddress
106+
#define __crtWakeByAddressSingle WakeByAddressSingle
107+
#define __crtWakeByAddressAll WakeByAddressAll
108+
109+
#else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv
110+
111+
struct _Wait_functions_table {
112+
_STD atomic<decltype(&::WaitOnAddress)> _Pfn_WaitOnAddress{nullptr};
113+
_STD atomic<decltype(&::WakeByAddressSingle)> _Pfn_WakeByAddressSingle{nullptr};
114+
_STD atomic<decltype(&::WakeByAddressAll)> _Pfn_WakeByAddressAll{nullptr};
115+
_STD atomic<__std_atomic_api_level> _Api_level{__std_atomic_api_level::__not_set};
116+
};
117+
118+
_Wait_functions_table _Wait_functions;
119+
120+
void _Force_wait_functions_srwlock_only() noexcept {
121+
auto _Local = _Wait_functions._Api_level.load(_STD memory_order_acquire);
122+
if (_Local <= __std_atomic_api_level::__detecting) {
123+
while (!_Wait_functions._Api_level.compare_exchange_weak(
124+
_Local, __std_atomic_api_level::__has_srwlock, _STD memory_order_acq_rel)) {
125+
if (_Local > __std_atomic_api_level::__detecting) {
126+
return;
127+
}
128+
}
129+
}
130+
}
131+
132+
[[nodiscard]] __std_atomic_api_level _Init_wait_functions(__std_atomic_api_level _Level) {
133+
while (!_Wait_functions._Api_level.compare_exchange_weak(
134+
_Level, __std_atomic_api_level::__detecting, _STD memory_order_acq_rel)) {
135+
if (_Level > __std_atomic_api_level::__detecting) {
136+
return _Level;
137+
}
138+
}
139+
140+
_Level = __std_atomic_api_level::__has_srwlock;
141+
142+
const HMODULE _Sync_module = GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll");
143+
if (_Sync_module != nullptr) {
144+
const auto _Wait_on_address =
145+
reinterpret_cast<decltype(&::WaitOnAddress)>(GetProcAddress(_Sync_module, "WaitOnAddress"));
146+
const auto _Wake_by_address_single =
147+
reinterpret_cast<decltype(&::WakeByAddressSingle)>(GetProcAddress(_Sync_module, "WakeByAddressSingle"));
148+
const auto _Wake_by_address_all =
149+
reinterpret_cast<decltype(&::WakeByAddressAll)>(GetProcAddress(_Sync_module, "WakeByAddressAll"));
150+
151+
if (_Wait_on_address != nullptr && _Wake_by_address_single != nullptr && _Wake_by_address_all != nullptr) {
152+
_Wait_functions._Pfn_WaitOnAddress.store(_Wait_on_address, _STD memory_order_relaxed);
153+
_Wait_functions._Pfn_WakeByAddressSingle.store(_Wake_by_address_single, _STD memory_order_relaxed);
154+
_Wait_functions._Pfn_WakeByAddressAll.store(_Wake_by_address_all, _STD memory_order_relaxed);
155+
_Level = __std_atomic_api_level::__has_wait_on_address;
156+
}
157+
}
158+
159+
// for __has_srwlock, relaxed would have been enough, not distinguishing for consistency
160+
_Wait_functions._Api_level.store(_Level, _STD memory_order_release);
161+
return _Level;
162+
}
163+
164+
[[nodiscard]] __std_atomic_api_level _Acquire_wait_functions() noexcept {
165+
auto _Level = _Wait_functions._Api_level.load(_STD memory_order_acquire);
166+
if (_Level <= __std_atomic_api_level::__detecting) {
167+
_Level = _Init_wait_functions(_Level);
168+
}
169+
170+
return _Level;
171+
}
172+
173+
[[nodiscard]] BOOL __crtWaitOnAddress(
174+
volatile VOID* Address, PVOID CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds) {
175+
const auto _Wait_on_address = _Wait_functions._Pfn_WaitOnAddress.load(_STD memory_order_relaxed);
176+
return _Wait_on_address(Address, CompareAddress, AddressSize, dwMilliseconds);
177+
}
178+
179+
VOID __crtWakeByAddressSingle(PVOID Address) {
180+
const auto _Wake_by_address_single = _Wait_functions._Pfn_WakeByAddressSingle.load(_STD memory_order_relaxed);
181+
_Wake_by_address_single(Address);
182+
}
183+
184+
VOID __crtWakeByAddressAll(PVOID Address) {
185+
const auto _Wake_by_address_all = _Wait_functions._Pfn_WakeByAddressAll.load(_STD memory_order_relaxed);
186+
_Wake_by_address_all(Address);
187+
}
188+
189+
bool __stdcall _Atomic_wait_are_equal_direct_fallback(
190+
const void* _Storage, void* _Comparand, size_t _Size, void*) noexcept {
191+
switch (_Size) {
192+
case 1:
193+
return __iso_volatile_load8(static_cast<const char*>(_Storage)) == *static_cast<const char*>(_Comparand);
194+
case 2:
195+
return __iso_volatile_load16(static_cast<const short*>(_Storage)) == *static_cast<const short*>(_Comparand);
196+
case 4:
197+
return __iso_volatile_load32(static_cast<const int*>(_Storage)) == *static_cast<const int*>(_Comparand);
198+
case 8:
199+
return __iso_volatile_load64(static_cast<const long long*>(_Storage))
200+
== *static_cast<const long long*>(_Comparand);
201+
default:
202+
_CSTD abort();
203+
}
204+
}
205+
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
94206
} // unnamed namespace
95207

96208
extern "C" {
97209
int __stdcall __std_atomic_wait_direct(const void* const _Storage, void* const _Comparand, const size_t _Size,
98210
const unsigned long _Remaining_timeout) noexcept {
99-
const auto _Result =
100-
WaitOnAddress(const_cast<volatile void*>(_Storage), const_cast<void*>(_Comparand), _Size, _Remaining_timeout);
211+
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
212+
if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) {
213+
return __std_atomic_wait_indirect(
214+
_Storage, _Comparand, _Size, nullptr, &_Atomic_wait_are_equal_direct_fallback, _Remaining_timeout);
215+
}
216+
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
217+
218+
const auto _Result = __crtWaitOnAddress(
219+
const_cast<volatile void*>(_Storage), const_cast<void*>(_Comparand), _Size, _Remaining_timeout);
101220

102221
if (!_Result) {
103222
_Assume_timeout();
@@ -106,11 +225,25 @@ int __stdcall __std_atomic_wait_direct(const void* const _Storage, void* const _
106225
}
107226

108227
void __stdcall __std_atomic_notify_one_direct(const void* const _Storage) noexcept {
109-
WakeByAddressSingle(const_cast<void*>(_Storage));
228+
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
229+
if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) {
230+
__std_atomic_notify_one_indirect(_Storage);
231+
return;
232+
}
233+
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE = 0
234+
235+
__crtWakeByAddressSingle(const_cast<void*>(_Storage));
110236
}
111237

112238
void __stdcall __std_atomic_notify_all_direct(const void* const _Storage) noexcept {
113-
WakeByAddressAll(const_cast<void*>(_Storage));
239+
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
240+
if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) {
241+
__std_atomic_notify_all_indirect(_Storage);
242+
return;
243+
}
244+
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0
245+
246+
__crtWakeByAddressAll(const_cast<void*>(_Storage));
114247
}
115248

116249
void __stdcall __std_atomic_notify_one_indirect(const void* const _Storage) noexcept {
@@ -206,10 +339,25 @@ unsigned long __stdcall __std_atomic_wait_get_remaining_timeout(unsigned long lo
206339
return static_cast<unsigned long>(_Remaining);
207340
}
208341

209-
// TRANSITION, ABI: preserved for binary compatibility
210-
enum class __std_atomic_api_level : unsigned long { __not_set, __detecting, __has_srwlock, __has_wait_on_address };
211-
__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level) noexcept {
342+
__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level _Requested_api_level) noexcept {
343+
#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
344+
(void) _Requested_api_level;
212345
return __std_atomic_api_level::__has_wait_on_address;
346+
#else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv
347+
switch (_Requested_api_level) {
348+
case __std_atomic_api_level::__not_set:
349+
case __std_atomic_api_level::__detecting:
350+
_CSTD abort();
351+
case __std_atomic_api_level::__has_srwlock:
352+
_Force_wait_functions_srwlock_only();
353+
break;
354+
case __std_atomic_api_level::__has_wait_on_address:
355+
default: // future compat: new header using an old DLL will get the highest requested level supported
356+
break;
357+
}
358+
359+
return _Acquire_wait_functions();
360+
#endif // !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE
213361
}
214362

215363
#pragma warning(push)

stl/src/awint.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@
1414

1515
_CRT_BEGIN_C_HEADER
1616

17+
#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8
18+
19+
#define __crtGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime) \
20+
GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime)
21+
22+
#else // ^^^ _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 vvv
23+
24+
_CRTIMP2 void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpSystemTimeAsFileTime) noexcept;
25+
26+
#endif // ^^^ _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 ^^^
27+
1728
_CRTIMP2 int __cdecl __crtCompareStringA(_In_z_ LPCWSTR _LocaleName, _In_ DWORD _DwCmpFlags,
1829
_In_reads_(_CchCount1) LPCSTR _LpString1, _In_ int _CchCount1, _In_reads_(_CchCount2) LPCSTR _LpString2,
1930
_In_ int _CchCount2, _In_ int _CodePage) noexcept;

stl/src/ppltasks.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ namespace Concurrency {
2626

2727
namespace details {
2828
[[noreturn]] _CRTIMP2 void __cdecl _ReportUnobservedException() {
29+
#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_CRT_APP) && _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
30+
if (!IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)) {
31+
std::abort();
32+
}
33+
#endif // ^^^ __fastfail conditionally available ^^^
34+
2935
__fastfail(FAST_FAIL_INVALID_ARG);
3036
}
3137

stl/src/winapisupp.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ namespace {
1414
// Use this macro for defining the following function pointers
1515
#define DEFINEFUNCTIONPOINTER(fn_name) decltype(&fn_name) __KERNEL32Function_##fn_name = nullptr
1616

17+
#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
18+
DEFINEFUNCTIONPOINTER(GetSystemTimePreciseAsFileTime);
19+
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
20+
1721
DEFINEFUNCTIONPOINTER(GetTempPath2W);
1822

1923
// Use this macro for caching a function pointer from a DLL
@@ -154,9 +158,15 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtSetFileInformationByHandle(_In_ HANDLE con
154158

155159
#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
156160

157-
// TRANSITION, ABI: preserved for binary compatibility
158161
extern "C" _CRTIMP2 void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpSystemTimeAsFileTime) noexcept {
159-
GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime);
162+
// use GetSystemTimePreciseAsFileTime if it is available (only on Windows 8+)...
163+
IFDYNAMICGETCACHEDFUNCTION(GetSystemTimePreciseAsFileTime) {
164+
pfGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime);
165+
return;
166+
}
167+
168+
// ...otherwise use GetSystemTimeAsFileTime.
169+
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime);
160170
}
161171

162172
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
@@ -186,6 +196,10 @@ static int __cdecl initialize_pointers() noexcept {
186196
HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll");
187197
_Analysis_assume_(hKernel32);
188198

199+
#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
200+
STOREFUNCTIONPOINTER(hKernel32, GetSystemTimePreciseAsFileTime);
201+
#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8
202+
189203
// Note that GetTempPath2W is defined as of Windows 10 Build 20348 (a server release) or Windows 11,
190204
// but there is no "_WIN32_WINNT_WIN11" constant, so we will always dynamically load it
191205
STOREFUNCTIONPOINTER(hKernel32, GetTempPath2W);

stl/src/xtime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ _CRTIMP2_PURE long long __cdecl _Xtime_get_ticks() noexcept {
5151
constexpr long long _Epoch = 0x19DB1DED53E8000LL;
5252

5353
FILETIME ft;
54-
GetSystemTimePreciseAsFileTime(&ft);
54+
__crtGetSystemTimePreciseAsFileTime(&ft);
5555
return ((static_cast<long long>(ft.dwHighDateTime)) << 32) + static_cast<long long>(ft.dwLowDateTime) - _Epoch;
5656
}
5757

tests/std/test.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ tests\P1032R1_miscellaneous_constexpr
523523
tests\P1132R7_out_ptr
524524
tests\P1135R6_atomic_flag_test
525525
tests\P1135R6_atomic_wait
526+
tests\P1135R6_atomic_wait_win7
526527
tests\P1135R6_barrier
527528
tests\P1135R6_latch
528529
tests\P1135R6_semaphore

0 commit comments

Comments
 (0)