diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 968d98987ec..ac17fb0a55f 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -559,7 +559,7 @@ function(add_stl_dlls D_SUFFIX REL_OR_DBG) generate_satellite_def("atomic_wait" "${D_SUFFIX}") add_library(msvcp${D_SUFFIX}_atomic_wait SHARED "${CMAKE_BINARY_DIR}/msvcp_atomic_wait${D_SUFFIX}.def") - 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") + 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") set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES ARCHIVE_OUTPUT_NAME "msvcp140_atomic_wait${D_SUFFIX}${VCLIBS_SUFFIX}") set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") set_target_properties(msvcp${D_SUFFIX}_atomic_wait PROPERTIES OUTPUT_NAME "msvcp140${D_SUFFIX}_atomic_wait${VCLIBS_SUFFIX}") diff --git a/stl/inc/xatomic_wait.h b/stl/inc/xatomic_wait.h index 178f91fa9e8..5058335d974 100644 --- a/stl/inc/xatomic_wait.h +++ b/stl/inc/xatomic_wait.h @@ -21,23 +21,9 @@ _STL_DISABLE_CLANG_WARNINGS extern "C" { inline constexpr unsigned long __std_atomic_wait_no_timeout = 0xFFFF'FFFF; // Pass as partial timeout -enum class __std_atomic_api_level : unsigned long { - __not_set, - __detecting, - __has_srwlock, - __has_wait_on_address, -}; - -// This function allows testing the atomic wait support while always using the APIs for a platform with fewer -// capabilities; it attempts to lock the APIs used to the level `_Requested_api_level`, and returns the actual API level -// in use. Once the API level has been set by calling this function (or detected by a call to one of the atomic wait -// functions), it can no longer be changed. -__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level _Requested_api_level) noexcept; - // Support for atomic waits. // The "direct" functions are used when the underlying infrastructure can use WaitOnAddress directly; that is, _Size is -// 1, 2, 4, or 8. The contract is the same as the WaitOnAddress function from the Windows SDK. If WaitOnAddress is not -// available on the current platform, falls back to a similar solution based on SRWLOCK and CONDITION_VARIABLE. +// 1, 2, 4, or 8. The contract is the same as the WaitOnAddress function from the Windows SDK. int __stdcall __std_atomic_wait_direct( const void* _Storage, void* _Comparand, size_t _Size, unsigned long _Remaining_timeout) noexcept; void __stdcall __std_atomic_notify_one_direct(const void* _Storage) noexcept; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index fe1db005f75..57b25daf357 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1974,7 +1974,6 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error. #endif // defined(MRTDLL) && !defined(_M_CEE_PURE) #define _STL_WIN32_WINNT_VISTA 0x0600 // _WIN32_WINNT_VISTA from sdkddkver.h -#define _STL_WIN32_WINNT_WIN7 0x0601 // _WIN32_WINNT_WIN7 from sdkddkver.h #define _STL_WIN32_WINNT_WIN8 0x0602 // _WIN32_WINNT_WIN8 from sdkddkver.h #define _STL_WIN32_WINNT_WIN10 0x0A00 // _WIN32_WINNT_WIN10 from sdkddkver.h @@ -1983,13 +1982,10 @@ compiler option, or define _ALLOW_RTCc_IN_STL to suppress this error. #if defined(_M_ARM64) // The first ARM64 Windows was Windows 10 #define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN10 -#elif defined(_M_ARM) || defined(_ONECORE) || defined(_CRT_APP) -// The first ARM or OneCore or App Windows was Windows 8 +#else // ^^^ defined(_M_ARM64) / !defined(_M_ARM64) vvv +// The earliest Windows supported by this implementation is Windows 8 #define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN8 -#else // ^^^ default to Win8 / default to Win7 vvv -// The earliest Windows supported by this implementation is Windows 7 -#define _STL_WIN32_WINNT _STL_WIN32_WINNT_WIN7 -#endif // ^^^ !defined(_M_ARM) && !defined(_M_ARM64) && !defined(_ONECORE) && !defined(_CRT_APP) ^^^ +#endif // ^^^ !defined(_M_ARM64) ^^^ #endif // !defined(_STL_WIN32_WINNT) #ifdef __cpp_noexcept_function_type diff --git a/stl/msbuild/stl_atomic_wait/msvcp_atomic_wait.settings.targets b/stl/msbuild/stl_atomic_wait/msvcp_atomic_wait.settings.targets index 869f8a1ecd2..0f29c995877 100644 --- a/stl/msbuild/stl_atomic_wait/msvcp_atomic_wait.settings.targets +++ b/stl/msbuild/stl_atomic_wait/msvcp_atomic_wait.settings.targets @@ -70,6 +70,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + diff --git a/stl/src/atomic_wait.cpp b/stl/src/atomic_wait.cpp index 2ac108c9988..4bafb1a86bb 100644 --- a/stl/src/atomic_wait.cpp +++ b/stl/src/atomic_wait.cpp @@ -11,6 +11,8 @@ #include +#pragma comment(lib, "synchronization") + namespace { constexpr unsigned long long _Atomic_wait_no_deadline = 0xFFFF'FFFF'FFFF'FFFF; @@ -89,134 +91,13 @@ namespace { } #endif // defined(_DEBUG) } - -#ifndef _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE -#if _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8 -#define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 1 -#else // ^^^ _STL_WIN32_WINNT >= _STL_WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 vvv -#define _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE 0 -#endif // ^^^ _STL_WIN32_WINNT < _STL_WIN32_WINNT_WIN8 ^^^ -#endif // !defined(_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE) - -#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE - -#pragma comment(lib, "synchronization") - -#define __crtWaitOnAddress WaitOnAddress -#define __crtWakeByAddressSingle WakeByAddressSingle -#define __crtWakeByAddressAll WakeByAddressAll - -#else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv - - struct _Wait_functions_table { - _STD atomic _Pfn_WaitOnAddress{nullptr}; - _STD atomic _Pfn_WakeByAddressSingle{nullptr}; - _STD atomic _Pfn_WakeByAddressAll{nullptr}; - _STD atomic<__std_atomic_api_level> _Api_level{__std_atomic_api_level::__not_set}; - }; - - _Wait_functions_table _Wait_functions; - - void _Force_wait_functions_srwlock_only() noexcept { - auto _Local = _Wait_functions._Api_level.load(_STD memory_order_acquire); - if (_Local <= __std_atomic_api_level::__detecting) { - while (!_Wait_functions._Api_level.compare_exchange_weak( - _Local, __std_atomic_api_level::__has_srwlock, _STD memory_order_acq_rel)) { - if (_Local > __std_atomic_api_level::__detecting) { - return; - } - } - } - } - - [[nodiscard]] __std_atomic_api_level _Init_wait_functions(__std_atomic_api_level _Level) { - while (!_Wait_functions._Api_level.compare_exchange_weak( - _Level, __std_atomic_api_level::__detecting, _STD memory_order_acq_rel)) { - if (_Level > __std_atomic_api_level::__detecting) { - return _Level; - } - } - - _Level = __std_atomic_api_level::__has_srwlock; - - const HMODULE _Sync_module = GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll"); - if (_Sync_module != nullptr) { - const auto _Wait_on_address = - reinterpret_cast(GetProcAddress(_Sync_module, "WaitOnAddress")); - const auto _Wake_by_address_single = - reinterpret_cast(GetProcAddress(_Sync_module, "WakeByAddressSingle")); - const auto _Wake_by_address_all = - reinterpret_cast(GetProcAddress(_Sync_module, "WakeByAddressAll")); - - if (_Wait_on_address != nullptr && _Wake_by_address_single != nullptr && _Wake_by_address_all != nullptr) { - _Wait_functions._Pfn_WaitOnAddress.store(_Wait_on_address, _STD memory_order_relaxed); - _Wait_functions._Pfn_WakeByAddressSingle.store(_Wake_by_address_single, _STD memory_order_relaxed); - _Wait_functions._Pfn_WakeByAddressAll.store(_Wake_by_address_all, _STD memory_order_relaxed); - _Level = __std_atomic_api_level::__has_wait_on_address; - } - } - - // for __has_srwlock, relaxed would have been enough, not distinguishing for consistency - _Wait_functions._Api_level.store(_Level, _STD memory_order_release); - return _Level; - } - - [[nodiscard]] __std_atomic_api_level _Acquire_wait_functions() noexcept { - auto _Level = _Wait_functions._Api_level.load(_STD memory_order_acquire); - if (_Level <= __std_atomic_api_level::__detecting) { - _Level = _Init_wait_functions(_Level); - } - - return _Level; - } - - [[nodiscard]] BOOL __crtWaitOnAddress( - volatile VOID* Address, PVOID CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds) { - const auto _Wait_on_address = _Wait_functions._Pfn_WaitOnAddress.load(_STD memory_order_relaxed); - return _Wait_on_address(Address, CompareAddress, AddressSize, dwMilliseconds); - } - - VOID __crtWakeByAddressSingle(PVOID Address) { - const auto _Wake_by_address_single = _Wait_functions._Pfn_WakeByAddressSingle.load(_STD memory_order_relaxed); - _Wake_by_address_single(Address); - } - - VOID __crtWakeByAddressAll(PVOID Address) { - const auto _Wake_by_address_all = _Wait_functions._Pfn_WakeByAddressAll.load(_STD memory_order_relaxed); - _Wake_by_address_all(Address); - } - - bool __stdcall _Atomic_wait_are_equal_direct_fallback( - const void* _Storage, void* _Comparand, size_t _Size, void*) noexcept { - switch (_Size) { - case 1: - return __iso_volatile_load8(static_cast(_Storage)) == *static_cast(_Comparand); - case 2: - return __iso_volatile_load16(static_cast(_Storage)) == *static_cast(_Comparand); - case 4: - return __iso_volatile_load32(static_cast(_Storage)) == *static_cast(_Comparand); - case 8: - return __iso_volatile_load64(static_cast(_Storage)) - == *static_cast(_Comparand); - default: - _CSTD abort(); - } - } -#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE } // unnamed namespace extern "C" { int __stdcall __std_atomic_wait_direct(const void* const _Storage, void* const _Comparand, const size_t _Size, const unsigned long _Remaining_timeout) noexcept { -#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0 - if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) { - return __std_atomic_wait_indirect( - _Storage, _Comparand, _Size, nullptr, &_Atomic_wait_are_equal_direct_fallback, _Remaining_timeout); - } -#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0 - - const auto _Result = __crtWaitOnAddress( - const_cast(_Storage), const_cast(_Comparand), _Size, _Remaining_timeout); + const auto _Result = + WaitOnAddress(const_cast(_Storage), const_cast(_Comparand), _Size, _Remaining_timeout); if (!_Result) { _Assume_timeout(); @@ -225,25 +106,11 @@ int __stdcall __std_atomic_wait_direct(const void* const _Storage, void* const _ } void __stdcall __std_atomic_notify_one_direct(const void* const _Storage) noexcept { -#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0 - if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) { - __std_atomic_notify_one_indirect(_Storage); - return; - } -#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE = 0 - - __crtWakeByAddressSingle(const_cast(_Storage)); + WakeByAddressSingle(const_cast(_Storage)); } void __stdcall __std_atomic_notify_all_direct(const void* const _Storage) noexcept { -#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0 - if (_Acquire_wait_functions() < __std_atomic_api_level::__has_wait_on_address) { - __std_atomic_notify_all_indirect(_Storage); - return; - } -#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE == 0 - - __crtWakeByAddressAll(const_cast(_Storage)); + WakeByAddressAll(const_cast(_Storage)); } void __stdcall __std_atomic_notify_one_indirect(const void* const _Storage) noexcept { @@ -339,25 +206,10 @@ unsigned long __stdcall __std_atomic_wait_get_remaining_timeout(unsigned long lo return static_cast(_Remaining); } -__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level _Requested_api_level) noexcept { -#if _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE - (void) _Requested_api_level; +// TRANSITION, ABI: preserved for binary compatibility +enum class __std_atomic_api_level : unsigned long { __not_set, __detecting, __has_srwlock, __has_wait_on_address }; +__std_atomic_api_level __stdcall __std_atomic_set_api_level(__std_atomic_api_level) noexcept { return __std_atomic_api_level::__has_wait_on_address; -#else // ^^^ _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE / !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE vvv - switch (_Requested_api_level) { - case __std_atomic_api_level::__not_set: - case __std_atomic_api_level::__detecting: - _CSTD abort(); - case __std_atomic_api_level::__has_srwlock: - _Force_wait_functions_srwlock_only(); - break; - case __std_atomic_api_level::__has_wait_on_address: - default: // future compat: new header using an old DLL will get the highest requested level supported - break; - } - - return _Acquire_wait_functions(); -#endif // !_ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE } #pragma warning(push) diff --git a/stl/src/awint.hpp b/stl/src/awint.hpp index da1e26e470a..797801b7a98 100644 --- a/stl/src/awint.hpp +++ b/stl/src/awint.hpp @@ -14,17 +14,6 @@ _CRT_BEGIN_C_HEADER -#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8 - -#define __crtGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime) \ - GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime) - -#else // ^^^ _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8 / _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 vvv - -_CRTIMP2 void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpSystemTimeAsFileTime) noexcept; - -#endif // ^^^ _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 ^^^ - _CRTIMP2 int __cdecl __crtCompareStringA(_In_z_ LPCWSTR _LocaleName, _In_ DWORD _DwCmpFlags, _In_reads_(_CchCount1) LPCSTR _LpString1, _In_ int _CchCount1, _In_reads_(_CchCount2) LPCSTR _LpString2, _In_ int _CchCount2, _In_ int _CodePage) noexcept; diff --git a/stl/src/ppltasks.cpp b/stl/src/ppltasks.cpp index ef1048cad14..62cf885e54a 100644 --- a/stl/src/ppltasks.cpp +++ b/stl/src/ppltasks.cpp @@ -26,12 +26,6 @@ namespace Concurrency { namespace details { [[noreturn]] _CRTIMP2 void __cdecl _ReportUnobservedException() { -#if (defined(_M_IX86) || defined(_M_X64)) && !defined(_CRT_APP) && _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 - if (!IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)) { - std::abort(); - } -#endif // ^^^ __fastfail conditionally available ^^^ - __fastfail(FAST_FAIL_INVALID_ARG); } diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 747fe070d2a..de6f6ae4d29 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -14,10 +14,6 @@ namespace { // Use this macro for defining the following function pointers #define DEFINEFUNCTIONPOINTER(fn_name) decltype(&fn_name) __KERNEL32Function_##fn_name = nullptr -#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 - DEFINEFUNCTIONPOINTER(GetSystemTimePreciseAsFileTime); -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 - DEFINEFUNCTIONPOINTER(GetTempPath2W); // Use this macro for caching a function pointer from a DLL @@ -158,15 +154,9 @@ extern "C" _CRTIMP2 BOOL __cdecl __crtSetFileInformationByHandle(_In_ HANDLE con #if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 +// TRANSITION, ABI: preserved for binary compatibility extern "C" _CRTIMP2 void __cdecl __crtGetSystemTimePreciseAsFileTime(_Out_ LPFILETIME lpSystemTimeAsFileTime) noexcept { - // use GetSystemTimePreciseAsFileTime if it is available (only on Windows 8+)... - IFDYNAMICGETCACHEDFUNCTION(GetSystemTimePreciseAsFileTime) { - pfGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime); - return; - } - - // ...otherwise use GetSystemTimeAsFileTime. - GetSystemTimeAsFileTime(lpSystemTimeAsFileTime); + GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime); } #endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 @@ -196,10 +186,6 @@ static int __cdecl initialize_pointers() noexcept { HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll"); _Analysis_assume_(hKernel32); -#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 - STOREFUNCTIONPOINTER(hKernel32, GetSystemTimePreciseAsFileTime); -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN8 - // Note that GetTempPath2W is defined as of Windows 10 Build 20348 (a server release) or Windows 11, // but there is no "_WIN32_WINNT_WIN11" constant, so we will always dynamically load it STOREFUNCTIONPOINTER(hKernel32, GetTempPath2W); diff --git a/stl/src/xtime.cpp b/stl/src/xtime.cpp index c59d0fc73af..7499f42e19d 100644 --- a/stl/src/xtime.cpp +++ b/stl/src/xtime.cpp @@ -51,7 +51,7 @@ _CRTIMP2_PURE long long __cdecl _Xtime_get_ticks() noexcept { constexpr long long _Epoch = 0x19DB1DED53E8000LL; FILETIME ft; - __crtGetSystemTimePreciseAsFileTime(&ft); + GetSystemTimePreciseAsFileTime(&ft); return ((static_cast(ft.dwHighDateTime)) << 32) + static_cast(ft.dwLowDateTime) - _Epoch; } diff --git a/tests/std/test.lst b/tests/std/test.lst index ba093a6b814..7489fd82a95 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -542,7 +542,6 @@ tests\P1032R1_miscellaneous_constexpr tests\P1132R7_out_ptr tests\P1135R6_atomic_flag_test tests\P1135R6_atomic_wait -tests\P1135R6_atomic_wait_win7 tests\P1135R6_barrier tests\P1135R6_latch tests\P1135R6_semaphore diff --git a/tests/std/tests/P1135R6_atomic_wait_win7/env.lst b/tests/std/tests/P1135R6_atomic_wait_win7/env.lst deleted file mode 100644 index 351a8293d9d..00000000000 --- a/tests/std/tests/P1135R6_atomic_wait_win7/env.lst +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -RUNALL_INCLUDE ..\usual_20_matrix.lst diff --git a/tests/std/tests/P1135R6_atomic_wait_win7/test.cpp b/tests/std/tests/P1135R6_atomic_wait_win7/test.cpp deleted file mode 100644 index d6deabafaaf..00000000000 --- a/tests/std/tests/P1135R6_atomic_wait_win7/test.cpp +++ /dev/null @@ -1,371 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include -#include -#include -#include -#include -#include - -template