Skip to content

Commit

Permalink
Drop support for Win7 / Server 2008 R2 (microsoft#4742)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanTLavavej authored Jun 25, 2024
1 parent 881bcad commit 0be5257
Show file tree
Hide file tree
Showing 15 changed files with 385 additions and 718 deletions.
2 changes: 1 addition & 1 deletion stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,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}")
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/__msvc_chrono.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ namespace chrono {
return time_point<_Clock, _To>(_CHRONO round<_To>(_Time.time_since_epoch()));
}

_EXPORT_STD struct system_clock { // wraps GetSystemTimePreciseAsFileTime/GetSystemTimeAsFileTime
_EXPORT_STD struct system_clock { // wraps GetSystemTimePreciseAsFileTime
using rep = long long;
using period = ratio<1, 10'000'000>; // 100 nanoseconds
using duration = _CHRONO duration<rep, period>;
Expand Down
16 changes: 1 addition & 15 deletions stl/inc/xatomic_wait.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
10 changes: 3 additions & 7 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1927,7 +1927,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_WINBLUE 0x0603 // _WIN32_WINNT_WINBLUE from sdkddkver.h
#define _STL_WIN32_WINNT_WIN10 0x0A00 // _WIN32_WINNT_WIN10 from sdkddkver.h
Expand All @@ -1937,13 +1936,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
<TargetLib Include="$(CrtLibPath)\vcruntime$(BuildSuffix)$(ClrLibSuffix).lib"/>
<TargetLib Include="$(UniversalCRTLib)"/>
<TargetLib Condition="'$(MsvcpFlavor)' == 'kernel32' or '$(MsvcpFlavor)' == 'netfx'" Include="$(SdkLibPath)\advapi32.lib"/>
<TargetLib Condition="'$(MsvcpFlavor)' == 'kernel32' or '$(MsvcpFlavor)' == 'netfx'" Include="$(SdkLibPath)\synchronization.lib"/>
</ItemGroup>

<!-- Copy the output dll and pdb to various destinations -->
Expand Down
166 changes: 9 additions & 157 deletions stl/src/atomic_wait.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#include <Windows.h>

#pragma comment(lib, "synchronization")

namespace {
constexpr unsigned long long _Atomic_wait_no_deadline = 0xFFFF'FFFF'FFFF'FFFF;

Expand Down Expand Up @@ -89,120 +91,6 @@ 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<decltype(&::WaitOnAddress)> _Pfn_WaitOnAddress{nullptr};
_STD atomic<decltype(&::WakeByAddressSingle)> _Pfn_WakeByAddressSingle{nullptr};
_STD atomic<decltype(&::WakeByAddressAll)> _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<decltype(&::WaitOnAddress)>(GetProcAddress(_Sync_module, "WaitOnAddress"));
const auto _Wake_by_address_single =
reinterpret_cast<decltype(&::WakeByAddressSingle)>(GetProcAddress(_Sync_module, "WakeByAddressSingle"));
const auto _Wake_by_address_all =
reinterpret_cast<decltype(&::WakeByAddressAll)>(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<const char*>(_Storage)) == *static_cast<const char*>(_Comparand);
case 2:
return __iso_volatile_load16(static_cast<const short*>(_Storage)) == *static_cast<const short*>(_Comparand);
case 4:
return __iso_volatile_load32(static_cast<const int*>(_Storage)) == *static_cast<const int*>(_Comparand);
case 8:
return __iso_volatile_load64(static_cast<const long long*>(_Storage))
== *static_cast<const long long*>(_Comparand);
default:
_CSTD abort();
}
}
#endif // _ATOMIC_WAIT_ON_ADDRESS_STATICALLY_AVAILABLE

[[nodiscard]] unsigned char __std_atomic_compare_exchange_128_fallback(
_Inout_bytecount_(16) long long* _Destination, _In_ long long _ExchangeHigh, _In_ long long _ExchangeLow,
_Inout_bytecount_(16) long long* _ComparandResult) noexcept {
Expand All @@ -225,15 +113,8 @@ 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<volatile void*>(_Storage), const_cast<void*>(_Comparand), _Size, _Remaining_timeout);
const auto _Result =
WaitOnAddress(const_cast<volatile void*>(_Storage), const_cast<void*>(_Comparand), _Size, _Remaining_timeout);

if (!_Result) {
_Assume_timeout();
Expand All @@ -242,25 +123,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<void*>(_Storage));
WakeByAddressSingle(const_cast<void*>(_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<void*>(_Storage));
WakeByAddressAll(const_cast<void*>(_Storage));
}

void __stdcall __std_atomic_notify_one_indirect(const void* const _Storage) noexcept {
Expand Down Expand Up @@ -356,25 +223,10 @@ unsigned long __stdcall __std_atomic_wait_get_remaining_timeout(unsigned long lo
return static_cast<unsigned long>(_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)
Expand Down
11 changes: 0 additions & 11 deletions stl/src/awint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 0 additions & 6 deletions stl/src/ppltasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
Loading

0 comments on commit 0be5257

Please sign in to comment.