From e1461a709e734084667293dcf02b4f6c75e175c6 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 30 Oct 2021 20:30:20 +0300 Subject: [PATCH 01/21] constexpr mutex Fixes #2285 --- stl/inc/mutex | 15 +++++---- stl/inc/xthreads.h | 76 +++++++++++++++++++++++++++++++++++++++++++--- stl/src/mutex.cpp | 5 +++ 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index eea7d5426a..fb9b304fe1 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -35,13 +35,13 @@ class condition_variable_any; class _Mutex_base { // base class for all mutex types public: - _Mutex_base(int _Flags = 0) noexcept { - _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); + constexpr _Mutex_base(int _Flags = 0) noexcept { + _Mtx_storage._Count = 0; + _Mtx_storage._Type = _Flags | _Mtx_try; + _Mtx_storage._Thread_id = -1; } - ~_Mutex_base() noexcept { - _Mtx_destroy_in_situ(_Mymtx()); - } + ~_Mutex_base() noexcept {} _Mutex_base(const _Mutex_base&) = delete; _Mutex_base& operator=(const _Mutex_base&) = delete; @@ -76,7 +76,7 @@ private: friend condition_variable; friend condition_variable_any; - aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage; + _Mtx_internal_imp_2_t _Mtx_storage; _Mtx_t _Mymtx() noexcept { // get pointer to _Mtx_internal_imp_t inside _Mtx_storage return reinterpret_cast<_Mtx_t>(&_Mtx_storage); @@ -85,8 +85,7 @@ private: class mutex : public _Mutex_base { // class for mutual exclusion public: - /* constexpr */ mutex() noexcept // TRANSITION, ABI - : _Mutex_base() {} + constexpr mutex() noexcept : _Mutex_base() {} mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index a1b8ee2bfe..e96fe22015 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -40,10 +40,10 @@ _INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 4; #endif // _WIN64 #else // _CRT_WINDOWS #ifdef _WIN64 -_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80; -_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8; -_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; -_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8; +_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80; +_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8; +_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; +_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8; #else // _WIN64 _INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 48; _INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 4; @@ -134,6 +134,74 @@ inline int _Check_C_return(int _Res) { // throw exception on failure return _Res; } _STD_END + +#if defined(_M_IX86) || defined(_M_ARM) +_INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; +_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; +#elif defined(_M_X64) || defined(_M_ARM64) +_INLINE_VAR constexpr size_t _Stl_critical_section_size = 64; +_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 8; +#else +#error Unknown architecture +#endif + + +// Corresponds to internal Concurrency::details::stl_critical_section with changes to expose it in headers +class __declspec(novtable) _Stl_critical_section_interface { +public: + virtual void __cdecl _Lock() = 0; + virtual bool __cdecl _Try_lock() = 0; + virtual bool __cdecl _Try_lock_for(unsigned int) = 0; + virtual void __cdecl _Unlock() = 0; + virtual void __cdecl _Destroy() = 0; +}; + +// Corresponds to internal Concurrency::details::stl_critical_section_win7 with changes to expose it in headers +// and make its construction constexpr +class _Stl_critical_section_interface_win7 final : public _Stl_critical_section_interface { +public: + constexpr _Stl_critical_section_interface_win7() noexcept = default; + + _Stl_critical_section_interface_win7(const _Stl_critical_section_interface_win7&) = delete; + _Stl_critical_section_interface_win7& operator=(const _Stl_critical_section_interface_win7&) = delete; + + void _Destroy() override {} + + void _Lock() override { + _Smtx_lock_exclusive(&_Mtx); + } + + bool _Try_lock() override { + return _Smtx_try_lock_exclusive(&_Mtx) != 0; + } + + bool _Try_lock_for(unsigned int) override { + // STL will call try_lock_for once again if this call will not succeed + return _Stl_critical_section_interface_win7::_Try_lock(); + } + + void _Unlock() override { + _Smtx_unlock_exclusive(&_Mtx); + } + +private: + _Smtx_t _Mtx = {}; +}; + +// Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr +struct _Mtx_internal_imp_2_t { + int _Type; + union alignas(_Stl_critical_section_alignment) _Cs_t { + _Stl_critical_section_interface_win7 _Cs_win7; + char _Data[_Stl_critical_section_size]; + + constexpr _Cs_t() : _Cs_win7() {} + ~_Cs_t() {} + } _Cs; + long _Thread_id; + int _Count; +}; + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index 5db8385bec..2fced884d7 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -49,6 +49,11 @@ struct _Mtx_internal_imp_t { // ConcRT mutex return reinterpret_cast(&cs); } }; +static_assert(Concurrency::details::stl_critical_section_max_size == _Stl_critical_section_size, + "Incorrect stl_critical_section_max_size"); + +static_assert(Concurrency::details::stl_critical_section_max_alignment == _Stl_critical_section_alignment, + "Incorrect stl_critical_section_max_alignment"); static_assert(sizeof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_size, "incorrect _Mtx_internal_imp_size"); static_assert(alignof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_alignment, "incorrect _Mtx_internal_imp_alignment"); From c80c783440eaece38114b87fba30647db1e30518 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 30 Oct 2021 22:07:26 +0300 Subject: [PATCH 02/21] some fixes, tests still will hang --- stl/inc/mutex | 6 +----- stl/inc/xthreads.h | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index fb9b304fe1..ac643ed694 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -35,11 +35,7 @@ class condition_variable_any; class _Mutex_base { // base class for all mutex types public: - constexpr _Mutex_base(int _Flags = 0) noexcept { - _Mtx_storage._Count = 0; - _Mtx_storage._Type = _Flags | _Mtx_try; - _Mtx_storage._Thread_id = -1; - } + constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) {} ~_Mutex_base() noexcept {} diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index e96fe22015..026d8323c3 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -135,15 +135,13 @@ inline int _Check_C_return(int _Res) { // throw exception on failure } _STD_END -#if defined(_M_IX86) || defined(_M_ARM) -_INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; -_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; -#elif defined(_M_X64) || defined(_M_ARM64) +#ifdef _WIN64 _INLINE_VAR constexpr size_t _Stl_critical_section_size = 64; _INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 8; -#else -#error Unknown architecture -#endif +#else // ^^^ 64-bit OS ^^^ / vvv 32-bit OS vvv +_INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; +_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; +#endif // ^^^32 - bit OS ^^^ // Corresponds to internal Concurrency::details::stl_critical_section with changes to expose it in headers @@ -190,16 +188,23 @@ class _Stl_critical_section_interface_win7 final : public _Stl_critical_section_ // Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr struct _Mtx_internal_imp_2_t { + struct alignas(_Stl_critical_section_alignment) _Align_t { + char _Pad[_Stl_critical_section_alignment]; + }; + int _Type; - union alignas(_Stl_critical_section_alignment) _Cs_t { + union _Cs_t { _Stl_critical_section_interface_win7 _Cs_win7; char _Data[_Stl_critical_section_size]; + _Align_t _Align; constexpr _Cs_t() : _Cs_win7() {} ~_Cs_t() {} } _Cs; - long _Thread_id; - int _Count; + long _Thread_id = -1; + int _Count = 0; + + constexpr _Mtx_internal_imp_2_t(int _Type_) : _Type(_Type_) {} }; #pragma pop_macro("new") From 13446e37862993cab4c4225d46e89be154d01285 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 10:29:13 +0200 Subject: [PATCH 03/21] runtime --- stl/inc/mutex | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index ac643ed694..3f9e6774ed 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -35,9 +35,17 @@ class condition_variable_any; class _Mutex_base { // base class for all mutex types public: - constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) {} + constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) { + if (!__builtin_is_constant_evaluated()) { + // If mutex is created in runtime, it may outlive the module it is allocated in; + // Use usual in-place construction. + _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); + } + } - ~_Mutex_base() noexcept {} + ~_Mutex_base() noexcept { + _Mtx_destroy_in_situ(_Mymtx()); + } _Mutex_base(const _Mutex_base&) = delete; _Mutex_base& operator=(const _Mutex_base&) = delete; From 46dfd7fbb3e40d26dcc18ff1ea10da3aa8c8e70e Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 12:01:19 +0200 Subject: [PATCH 04/21] fake vtable --- stl/inc/xthreads.h | 79 ++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 026d8323c3..f41f1df259 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -143,63 +143,60 @@ _INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; _INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; #endif // ^^^32 - bit OS ^^^ - -// Corresponds to internal Concurrency::details::stl_critical_section with changes to expose it in headers -class __declspec(novtable) _Stl_critical_section_interface { -public: - virtual void __cdecl _Lock() = 0; - virtual bool __cdecl _Try_lock() = 0; - virtual bool __cdecl _Try_lock_for(unsigned int) = 0; - virtual void __cdecl _Unlock() = 0; - virtual void __cdecl _Destroy() = 0; -}; - -// Corresponds to internal Concurrency::details::stl_critical_section_win7 with changes to expose it in headers -// and make its construction constexpr -class _Stl_critical_section_interface_win7 final : public _Stl_critical_section_interface { -public: - constexpr _Stl_critical_section_interface_win7() noexcept = default; - - _Stl_critical_section_interface_win7(const _Stl_critical_section_interface_win7&) = delete; - _Stl_critical_section_interface_win7& operator=(const _Stl_critical_section_interface_win7&) = delete; - - void _Destroy() override {} - - void _Lock() override { - _Smtx_lock_exclusive(&_Mtx); +struct alignas(_Stl_critical_section_alignment) _Data_win7_t { + static void __fastcall _Destroy_impl(_Data_win7_t*) {} + static void __fastcall _Lock_impl(_Data_win7_t* _Data) { + _Smtx_lock_exclusive(&_Data->_Mtx); } - bool _Try_lock() override { - return _Smtx_try_lock_exclusive(&_Mtx) != 0; + static bool __fastcall _Try_lock_impl(_Data_win7_t* _Data) { + return _Smtx_try_lock_exclusive(&_Data->_Mtx) != 0; } - bool _Try_lock_for(unsigned int) override { +#ifdef _M_IX86 + static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int, unsigned int) { + // STL will call try_lock_for once again if this call will not succeed + return _Data_win7_t::_Try_lock_impl(_Data); + } +#else // ^^^ x86 ^^^ / vvv not x86 vvv + static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int) { // STL will call try_lock_for once again if this call will not succeed - return _Stl_critical_section_interface_win7::_Try_lock(); + return _Data_win7_t::_Try_lock_impl(_Data); } +#endif // ^^^ not x86 - void _Unlock() override { - _Smtx_unlock_exclusive(&_Mtx); + static void __fastcall _Unlock_impl(_Data_win7_t* _Data) { + _Smtx_unlock_exclusive(&_Data->_Mtx); } -private: - _Smtx_t _Mtx = {}; + struct _VTable { + void(__fastcall* _Destroy)(_Data_win7_t*) = _Destroy_impl; + void(__fastcall* _Lock)(_Data_win7_t*) = _Lock_impl; + bool(__fastcall* _Try_lock)(_Data_win7_t*) = _Try_lock_impl; +#ifdef _M_IX86 + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int) = _Try_lock_for_impl; +#else // ^^^ x86 ^^^ / vvv not x86 vvv + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int) = _Try_lock_for_impl; +#endif // ^^^ not x86 + void(__fastcall* _Unlock)(_Data_win7_t*) = _Unlock_impl; + }; + + static constexpr _VTable _Vtbl{}; + + const _VTable* _VPtr = &_Vtbl; + _Smtx_t _Mtx = {}; }; // Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr struct _Mtx_internal_imp_2_t { - struct alignas(_Stl_critical_section_alignment) _Align_t { - char _Pad[_Stl_critical_section_alignment]; - }; - int _Type; - union _Cs_t { - _Stl_critical_section_interface_win7 _Cs_win7; + + union alignas(_Stl_critical_section_alignment) _Data_t { char _Data[_Stl_critical_section_size]; - _Align_t _Align; + _Data_win7_t _Data_win7; - constexpr _Cs_t() : _Cs_win7() {} - ~_Cs_t() {} + constexpr _Data_t() : _Data_win7() {} + ~_Data_t() {} } _Cs; long _Thread_id = -1; int _Count = 0; From 46802623b803789b208cfd54564cc61fc772a566 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 13:22:51 +0200 Subject: [PATCH 05/21] outside --- stl/inc/xthreads.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index f41f1df259..ec81172618 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -170,18 +170,18 @@ struct alignas(_Stl_critical_section_alignment) _Data_win7_t { } struct _VTable { - void(__fastcall* _Destroy)(_Data_win7_t*) = _Destroy_impl; - void(__fastcall* _Lock)(_Data_win7_t*) = _Lock_impl; - bool(__fastcall* _Try_lock)(_Data_win7_t*) = _Try_lock_impl; + void(__fastcall* _Destroy)(_Data_win7_t*); + void(__fastcall* _Lock)(_Data_win7_t*); + bool(__fastcall* _Try_lock)(_Data_win7_t*); #ifdef _M_IX86 - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int) = _Try_lock_for_impl; + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int); #else // ^^^ x86 ^^^ / vvv not x86 vvv - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int) = _Try_lock_for_impl; + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int); #endif // ^^^ not x86 - void(__fastcall* _Unlock)(_Data_win7_t*) = _Unlock_impl; + void(__fastcall* _Unlock)(_Data_win7_t*); }; - static constexpr _VTable _Vtbl{}; + static constexpr _VTable _Vtbl{_Destroy_impl, _Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl}; const _VTable* _VPtr = &_Vtbl; _Smtx_t _Mtx = {}; From 639c3192637612669543291eff5a3e2190e357e9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 13:28:45 +0200 Subject: [PATCH 06/21] inner --- stl/inc/xthreads.h | 67 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index ec81172618..f72dd3d676 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -143,54 +143,53 @@ _INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; _INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; #endif // ^^^32 - bit OS ^^^ -struct alignas(_Stl_critical_section_alignment) _Data_win7_t { - static void __fastcall _Destroy_impl(_Data_win7_t*) {} - static void __fastcall _Lock_impl(_Data_win7_t* _Data) { - _Smtx_lock_exclusive(&_Data->_Mtx); - } +// Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr +struct _Mtx_internal_imp_2_t { + struct alignas(_Stl_critical_section_alignment) _Data_win7_t { + static void __fastcall _Destroy_impl(_Data_win7_t*) {} + static void __fastcall _Lock_impl(_Data_win7_t* _Data) { + _Smtx_lock_exclusive(&_Data->_Mtx); + } - static bool __fastcall _Try_lock_impl(_Data_win7_t* _Data) { - return _Smtx_try_lock_exclusive(&_Data->_Mtx) != 0; - } + static bool __fastcall _Try_lock_impl(_Data_win7_t* _Data) { + return _Smtx_try_lock_exclusive(&_Data->_Mtx) != 0; + } #ifdef _M_IX86 - static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int, unsigned int) { - // STL will call try_lock_for once again if this call will not succeed - return _Data_win7_t::_Try_lock_impl(_Data); - } + static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int, unsigned int) { + // STL will call try_lock_for once again if this call will not succeed + return _Data_win7_t::_Try_lock_impl(_Data); + } #else // ^^^ x86 ^^^ / vvv not x86 vvv - static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int) { - // STL will call try_lock_for once again if this call will not succeed - return _Data_win7_t::_Try_lock_impl(_Data); - } + static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int) { + // STL will call try_lock_for once again if this call will not succeed + return _Data_win7_t::_Try_lock_impl(_Data); + } #endif // ^^^ not x86 - static void __fastcall _Unlock_impl(_Data_win7_t* _Data) { - _Smtx_unlock_exclusive(&_Data->_Mtx); - } + static void __fastcall _Unlock_impl(_Data_win7_t* _Data) { + _Smtx_unlock_exclusive(&_Data->_Mtx); + } - struct _VTable { - void(__fastcall* _Destroy)(_Data_win7_t*); - void(__fastcall* _Lock)(_Data_win7_t*); - bool(__fastcall* _Try_lock)(_Data_win7_t*); + struct _VTable { + void(__fastcall* _Destroy)(_Data_win7_t*); + void(__fastcall* _Lock)(_Data_win7_t*); + bool(__fastcall* _Try_lock)(_Data_win7_t*); #ifdef _M_IX86 - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int); + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int); #else // ^^^ x86 ^^^ / vvv not x86 vvv - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int); + bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int); #endif // ^^^ not x86 - void(__fastcall* _Unlock)(_Data_win7_t*); - }; + void(__fastcall* _Unlock)(_Data_win7_t*); + }; - static constexpr _VTable _Vtbl{_Destroy_impl, _Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl}; + static constexpr _VTable _Vtbl{_Destroy_impl, _Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl}; - const _VTable* _VPtr = &_Vtbl; - _Smtx_t _Mtx = {}; -}; + const _VTable* _VPtr = &_Vtbl; + _Smtx_t _Mtx = {}; + }; -// Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr -struct _Mtx_internal_imp_2_t { int _Type; - union alignas(_Stl_critical_section_alignment) _Data_t { char _Data[_Stl_critical_section_size]; _Data_win7_t _Data_win7; From 25d57337bfe43f4c5340560dbec8807cf1ef9dcb Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 13:51:06 +0200 Subject: [PATCH 07/21] Don't create Vista primitives --- stl/src/primitives.hpp | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index f5e37f505f..b2574ed85d 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -193,45 +193,11 @@ namespace Concurrency { } inline void create_stl_critical_section(stl_critical_section_interface* p) { -#ifdef _CRT_WINDOWS new (p) stl_critical_section_win7; -#else - switch (__stl_sync_api_impl_mode) { - case __stl_sync_api_modes_enum::normal: - case __stl_sync_api_modes_enum::win7: - if (are_win7_sync_apis_available()) { - new (p) stl_critical_section_win7; - return; - } - // fall through - case __stl_sync_api_modes_enum::vista: - new (p) stl_critical_section_vista; - return; - default: - abort(); - } -#endif // _CRT_WINDOWS } inline void create_stl_condition_variable(stl_condition_variable_interface* p) { -#ifdef _CRT_WINDOWS new (p) stl_condition_variable_win7; -#else - switch (__stl_sync_api_impl_mode) { - case __stl_sync_api_modes_enum::normal: - case __stl_sync_api_modes_enum::win7: - if (are_win7_sync_apis_available()) { - new (p) stl_condition_variable_win7; - return; - } - // fall through - case __stl_sync_api_modes_enum::vista: - new (p) stl_condition_variable_vista; - return; - default: - abort(); - } -#endif // _CRT_WINDOWS } #if defined _CRT_WINDOWS From 8b3ffcb66387df6ddb19564da44c28ca3c4b8319 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 14:03:47 +0200 Subject: [PATCH 08/21] destroy is last --- stl/inc/xthreads.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index f72dd3d676..dc9f1ecedc 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -146,7 +146,6 @@ _INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; // Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr struct _Mtx_internal_imp_2_t { struct alignas(_Stl_critical_section_alignment) _Data_win7_t { - static void __fastcall _Destroy_impl(_Data_win7_t*) {} static void __fastcall _Lock_impl(_Data_win7_t* _Data) { _Smtx_lock_exclusive(&_Data->_Mtx); } @@ -166,13 +165,13 @@ struct _Mtx_internal_imp_2_t { return _Data_win7_t::_Try_lock_impl(_Data); } #endif // ^^^ not x86 - static void __fastcall _Unlock_impl(_Data_win7_t* _Data) { _Smtx_unlock_exclusive(&_Data->_Mtx); } + static void __fastcall _Destroy_impl(_Data_win7_t*) {} + struct _VTable { - void(__fastcall* _Destroy)(_Data_win7_t*); void(__fastcall* _Lock)(_Data_win7_t*); bool(__fastcall* _Try_lock)(_Data_win7_t*); #ifdef _M_IX86 @@ -181,9 +180,10 @@ struct _Mtx_internal_imp_2_t { bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int); #endif // ^^^ not x86 void(__fastcall* _Unlock)(_Data_win7_t*); + void(__fastcall* _Destroy)(_Data_win7_t*); }; - static constexpr _VTable _Vtbl{_Destroy_impl, _Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl}; + static constexpr _VTable _Vtbl{_Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl, _Destroy_impl}; const _VTable* _VPtr = &_Vtbl; _Smtx_t _Mtx = {}; From 31700682203e644deebe06dc1441f2cef48dd94b Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 14:29:08 +0200 Subject: [PATCH 09/21] Cuda? --- stl/inc/mutex | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/stl/inc/mutex b/stl/inc/mutex index 3f9e6774ed..1d300c289c 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -35,6 +35,11 @@ class condition_variable_any; class _Mutex_base { // base class for all mutex types public: +#ifdef __CUDACC__ // TRANSITION, CUDA + _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) { + _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); + } +#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) { if (!__builtin_is_constant_evaluated()) { // If mutex is created in runtime, it may outlive the module it is allocated in; @@ -42,6 +47,7 @@ public: _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); } } +#endif // ^^^ not CUDA ^^^ ~_Mutex_base() noexcept { _Mtx_destroy_in_situ(_Mymtx()); @@ -89,7 +95,11 @@ private: class mutex : public _Mutex_base { // class for mutual exclusion public: +#ifdef __CUDACC__ // TRANSITION, CUDA + mutex() noexcept : _Mutex_base() {} +#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv constexpr mutex() noexcept : _Mutex_base() {} +#endif // ^^^ not CUDA ^^^ mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; From 820e41e076b85b89fd24d1b83600afc931ac55fb Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 31 Oct 2021 14:35:37 +0200 Subject: [PATCH 10/21] TryAcquireSRWLockExclusive --- stl/src/primitives.hpp | 2 +- stl/src/winapisupp.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index b2574ed85d..d2755d0a49 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -125,7 +125,7 @@ namespace Concurrency { } bool try_lock() override { - return __crtTryAcquireSRWLockExclusive(&m_srw_lock) != 0; + return TryAcquireSRWLockExclusive(&m_srw_lock) != 0; } bool try_lock_for(unsigned int) override { diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index aa583d138a..385f292ebd 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -339,9 +339,7 @@ extern "C" BOOL __cdecl __crtQueueUserWorkItem(_In_ LPTHREAD_START_ROUTINE, _In_ #if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 extern "C" BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK const pLock) { - DYNAMICGETCACHEDFUNCTION(PFNTRYACQUIRESRWLOCKEXCLUSIVE, TryAcquireSRWLockExclusive, pfTryAcquireSRWLockExclusive); - return pfTryAcquireSRWLockExclusive(pLock); - // Don't have fallbacks because the only caller (in primitives.hpp) will check the existence before calling + return TryAcquireSRWLockExclusive(pLock); } #endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 From de050dc654f4b80f09900957ea6115a99fe19ab6 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 1 Nov 2021 08:10:54 +0200 Subject: [PATCH 11/21] reduce conditional compilation --- stl/inc/mutex | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 1d300c289c..11abc82070 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -95,11 +95,7 @@ private: class mutex : public _Mutex_base { // class for mutual exclusion public: -#ifdef __CUDACC__ // TRANSITION, CUDA - mutex() noexcept : _Mutex_base() {} -#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv - constexpr mutex() noexcept : _Mutex_base() {} -#endif // ^^^ not CUDA ^^^ + mutex() noexcept = default; // Implied constexpr if _Mutex_base default constructor is constexpr mutex(const mutex&) = delete; mutex& operator=(const mutex&) = delete; From 322b5b04af2bfa1c6cee05bbb8c0187ee0c88b35 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 20:08:22 +0200 Subject: [PATCH 12/21] C++20 only fix without scary tricks --- stl/inc/mutex | 25 +++++++----- stl/inc/xthreads.h | 92 ++++++++++++++++-------------------------- stl/src/mutex.cpp | 12 +++--- stl/src/primitives.hpp | 40 +++++++++--------- 4 files changed, 72 insertions(+), 97 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 11abc82070..e161bd1258 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -35,19 +35,22 @@ class condition_variable_any; class _Mutex_base { // base class for all mutex types public: -#ifdef __CUDACC__ // TRANSITION, CUDA - _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) { - _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); - } -#else // ^^^ TRANSITION, CUDA ^^^ / vvv not CUDA vvv - constexpr _Mutex_base(int _Flags = 0) noexcept : _Mtx_storage(_Flags | _Mtx_try) { - if (!__builtin_is_constant_evaluated()) { - // If mutex is created in runtime, it may outlive the module it is allocated in; - // Use usual in-place construction. +#if _HAS_CXX20 + constexpr +#endif // _HAS_CXX20 + _Mutex_base(int _Flags = 0) noexcept { +#if _HAS_CXX20 + if (_STD is_constant_evaluated()) { + ::new (static_cast(&_Mtx_storage)) _Stl_critical_section_constexpr{}; + } else +#endif // _HAS_CXX20 + { + // C++20: For /MD, if mutex is created in runtime, it may outlive the module it is allocated in; + // Use usual construction from the STL DLL. + // Pre-C++20: Always use construction from the STL DLL. _Mtx_init_in_situ(_Mymtx(), _Flags | _Mtx_try); } } -#endif // ^^^ not CUDA ^^^ ~_Mutex_base() noexcept { _Mtx_destroy_in_situ(_Mymtx()); @@ -86,7 +89,7 @@ private: friend condition_variable; friend condition_variable_any; - _Mtx_internal_imp_2_t _Mtx_storage; + aligned_storage_t<_Mtx_internal_imp_size, _Mtx_internal_imp_alignment> _Mtx_storage; _Mtx_t _Mymtx() noexcept { // get pointer to _Mtx_internal_imp_t inside _Mtx_storage return reinterpret_cast<_Mtx_t>(&_Mtx_storage); diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index dc9f1ecedc..6f7b893a5d 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -143,66 +143,42 @@ _INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; _INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; #endif // ^^^32 - bit OS ^^^ -// Corresponds to internal _Mtx_internal_imp_t with changes to expose it in headers and make its construction constexpr -struct _Mtx_internal_imp_2_t { - struct alignas(_Stl_critical_section_alignment) _Data_win7_t { - static void __fastcall _Lock_impl(_Data_win7_t* _Data) { - _Smtx_lock_exclusive(&_Data->_Mtx); - } - - static bool __fastcall _Try_lock_impl(_Data_win7_t* _Data) { - return _Smtx_try_lock_exclusive(&_Data->_Mtx) != 0; - } - -#ifdef _M_IX86 - static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int, unsigned int) { - // STL will call try_lock_for once again if this call will not succeed - return _Data_win7_t::_Try_lock_impl(_Data); - } -#else // ^^^ x86 ^^^ / vvv not x86 vvv - static bool __fastcall _Try_lock_for_impl(_Data_win7_t* _Data, unsigned int) { - // STL will call try_lock_for once again if this call will not succeed - return _Data_win7_t::_Try_lock_impl(_Data); - } -#endif // ^^^ not x86 - static void __fastcall _Unlock_impl(_Data_win7_t* _Data) { - _Smtx_unlock_exclusive(&_Data->_Mtx); - } - - static void __fastcall _Destroy_impl(_Data_win7_t*) {} - - struct _VTable { - void(__fastcall* _Lock)(_Data_win7_t*); - bool(__fastcall* _Try_lock)(_Data_win7_t*); -#ifdef _M_IX86 - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int, unsigned int); -#else // ^^^ x86 ^^^ / vvv not x86 vvv - bool(__fastcall* _Try_lock_for)(_Data_win7_t*, unsigned int); -#endif // ^^^ not x86 - void(__fastcall* _Unlock)(_Data_win7_t*); - void(__fastcall* _Destroy)(_Data_win7_t*); - }; - - static constexpr _VTable _Vtbl{_Lock_impl, _Try_lock_impl, _Try_lock_for_impl, _Unlock_impl, _Destroy_impl}; - - const _VTable* _VPtr = &_Vtbl; - _Smtx_t _Mtx = {}; - }; - - int _Type; - union alignas(_Stl_critical_section_alignment) _Data_t { - char _Data[_Stl_critical_section_size]; - _Data_win7_t _Data_win7; - - constexpr _Data_t() : _Data_win7() {} - ~_Data_t() {} - } _Cs; - long _Thread_id = -1; - int _Count = 0; - - constexpr _Mtx_internal_imp_2_t(int _Type_) : _Type(_Type_) {} +class __declspec(novtable) _Stl_critical_section_interface { +public: + virtual void __thiscall _Lock() = 0; + virtual bool __thiscall _Try_lock() = 0; + virtual bool __thiscall _Try_lock_for(unsigned int) = 0; + virtual void __thiscall _Unlock() = 0; + virtual void __thiscall _Destroy() = 0; }; + +class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_critical_section_interface { +public: + void __thiscall _Lock() override { + _Smtx_lock_exclusive(&_Mtx); + } + + bool __thiscall _Try_lock() override { + return _Smtx_try_lock_exclusive(&_Mtx) != 0; + } + + bool __thiscall _Try_lock_for(unsigned int) override { + // STL will call try_lock_for once again if this call will not succeed + return _Stl_critical_section_constexpr::_Try_lock(); + } + + void __thiscall _Unlock() override { + _Smtx_unlock_exclusive(&_Mtx); + } + + void __thiscall _Destroy() override {} + +private: + _Smtx_t _Mtx; +}; + + #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index 2fced884d7..c0bfeb9a4e 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -67,7 +67,7 @@ void _Mtx_init_in_situ(_Mtx_t mtx, int type) { // initialize mutex in situ void _Mtx_destroy_in_situ(_Mtx_t mtx) { // destroy mutex in situ _THREAD_ASSERT(mtx->count == 0, "mutex destroyed while busy"); - mtx->_get_cs()->destroy(); + mtx->_get_cs()->_Destroy(); } int _Mtx_init(_Mtx_t* mtx, int type) { // initialize mutex @@ -95,7 +95,7 @@ void _Mtx_destroy(_Mtx_t mtx) { // destroy mutex static int mtx_do_lock(_Mtx_t mtx, const xtime* target) { // lock mutex if ((mtx->type & ~_Mtx_recursive) == _Mtx_plain) { // set the lock if (mtx->thread_id != static_cast(GetCurrentThreadId())) { // not current thread, do lock - mtx->_get_cs()->lock(); + mtx->_get_cs()->_Lock(); mtx->thread_id = static_cast(GetCurrentThreadId()); } ++mtx->count; @@ -105,7 +105,7 @@ static int mtx_do_lock(_Mtx_t mtx, const xtime* target) { // lock mutex int res = WAIT_TIMEOUT; if (target == nullptr) { // no target --> plain wait (i.e. infinite timeout) if (mtx->thread_id != static_cast(GetCurrentThreadId())) { - mtx->_get_cs()->lock(); + mtx->_get_cs()->_Lock(); } res = WAIT_OBJECT_0; @@ -113,7 +113,7 @@ static int mtx_do_lock(_Mtx_t mtx, const xtime* target) { // lock mutex } else if (target->sec < 0 || target->sec == 0 && target->nsec <= 0) { // target time <= 0 --> plain trylock or timed wait for time that has passed; try to lock with 0 timeout if (mtx->thread_id != static_cast(GetCurrentThreadId())) { // not this thread, lock it - if (mtx->_get_cs()->try_lock()) { + if (mtx->_get_cs()->_Try_lock()) { res = WAIT_OBJECT_0; } else { res = WAIT_TIMEOUT; @@ -127,7 +127,7 @@ static int mtx_do_lock(_Mtx_t mtx, const xtime* target) { // lock mutex xtime_get(&now, TIME_UTC); while (now.sec < target->sec || now.sec == target->sec && now.nsec < target->nsec) { // time has not expired if (mtx->thread_id == static_cast(GetCurrentThreadId()) - || mtx->_get_cs()->try_lock_for(_Xtime_diff_to_millis2(target, &now))) { // stop waiting + || mtx->_get_cs()->_Try_lock_for(_Xtime_diff_to_millis2(target, &now))) { // stop waiting res = WAIT_OBJECT_0; break; } else { @@ -172,7 +172,7 @@ int _Mtx_unlock(_Mtx_t mtx) { // unlock mutex if (--mtx->count == 0) { // leave critical section mtx->thread_id = -1; - mtx->_get_cs()->unlock(); + mtx->_get_cs()->_Unlock(); } return _Thrd_success; // TRANSITION, ABI: always returns _Thrd_success } diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index d2755d0a49..f08d1cadf2 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -6,6 +6,7 @@ #include // for __max #include #include +#include #include "awint.hpp" @@ -15,14 +16,8 @@ extern __stl_sync_api_modes_enum __stl_sync_api_impl_mode; namespace Concurrency { namespace details { - class __declspec(novtable) stl_critical_section_interface { - public: - virtual void lock() = 0; - virtual bool try_lock() = 0; - virtual bool try_lock_for(unsigned int) = 0; - virtual void unlock() = 0; - virtual void destroy() = 0; - }; + using stl_critical_section_interface = ::_Stl_critical_section_interface; + class __declspec(novtable) stl_condition_variable_interface { public: @@ -43,24 +38,21 @@ namespace Concurrency { stl_critical_section_vista& operator=(const stl_critical_section_vista&) = delete; ~stl_critical_section_vista() = delete; - void destroy() override { - DeleteCriticalSection(&_M_critical_section); - } - void lock() override { + void _Lock() override { EnterCriticalSection(&_M_critical_section); } - bool try_lock() override { + bool _Try_lock() override { return TryEnterCriticalSection(&_M_critical_section) != 0; } - bool try_lock_for(unsigned int) override { + bool _Try_lock_for(unsigned int) override { // STL will call try_lock_for once again if this call will not succeed - return stl_critical_section_vista::try_lock(); + return stl_critical_section_vista::_Try_lock(); } - void unlock() override { + void _Unlock() override { LeaveCriticalSection(&_M_critical_section); } @@ -68,6 +60,10 @@ namespace Concurrency { return &_M_critical_section; } + void _Destroy() override { + DeleteCriticalSection(&_M_critical_section); + } + private: CRITICAL_SECTION _M_critical_section; }; @@ -118,22 +114,22 @@ namespace Concurrency { stl_critical_section_win7(const stl_critical_section_win7&) = delete; stl_critical_section_win7& operator=(const stl_critical_section_win7&) = delete; - void destroy() override {} + void _Destroy() override {} - void lock() override { + void _Lock() override { AcquireSRWLockExclusive(&m_srw_lock); } - bool try_lock() override { + bool _Try_lock() override { return TryAcquireSRWLockExclusive(&m_srw_lock) != 0; } - bool try_lock_for(unsigned int) override { + bool _Try_lock_for(unsigned int) override { // STL will call try_lock_for once again if this call will not succeed - return stl_critical_section_win7::try_lock(); + return stl_critical_section_win7::_Try_lock(); } - void unlock() override { + void _Unlock() override { ReleaseSRWLockExclusive(&m_srw_lock); } From 1c811f61c96f0251c41e9bc0fc5b9a3e5f030ce2 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 20:12:27 +0200 Subject: [PATCH 13/21] remove some no longer needed defines --- stl/inc/xthreads.h | 17 ++++------------- stl/src/mutex.cpp | 5 ----- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 6f7b893a5d..bb2666dba0 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -40,10 +40,10 @@ _INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 4; #endif // _WIN64 #else // _CRT_WINDOWS #ifdef _WIN64 -_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80; -_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8; -_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; -_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8; +_INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 80; +_INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 8; +_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; +_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = 8; #else // _WIN64 _INLINE_VAR constexpr size_t _Mtx_internal_imp_size = 48; _INLINE_VAR constexpr size_t _Mtx_internal_imp_alignment = 4; @@ -135,14 +135,6 @@ inline int _Check_C_return(int _Res) { // throw exception on failure } _STD_END -#ifdef _WIN64 -_INLINE_VAR constexpr size_t _Stl_critical_section_size = 64; -_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 8; -#else // ^^^ 64-bit OS ^^^ / vvv 32-bit OS vvv -_INLINE_VAR constexpr size_t _Stl_critical_section_size = 36; -_INLINE_VAR constexpr size_t _Stl_critical_section_alignment = 4; -#endif // ^^^32 - bit OS ^^^ - class __declspec(novtable) _Stl_critical_section_interface { public: virtual void __thiscall _Lock() = 0; @@ -152,7 +144,6 @@ class __declspec(novtable) _Stl_critical_section_interface { virtual void __thiscall _Destroy() = 0; }; - class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_critical_section_interface { public: void __thiscall _Lock() override { diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index c0bfeb9a4e..79ebb3b6fa 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -49,11 +49,6 @@ struct _Mtx_internal_imp_t { // ConcRT mutex return reinterpret_cast(&cs); } }; -static_assert(Concurrency::details::stl_critical_section_max_size == _Stl_critical_section_size, - "Incorrect stl_critical_section_max_size"); - -static_assert(Concurrency::details::stl_critical_section_max_alignment == _Stl_critical_section_alignment, - "Incorrect stl_critical_section_max_alignment"); static_assert(sizeof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_size, "incorrect _Mtx_internal_imp_size"); static_assert(alignof(_Mtx_internal_imp_t) <= _Mtx_internal_imp_alignment, "incorrect _Mtx_internal_imp_alignment"); From 85bab9c602ba087776b3bb16d96b99b8992777ff Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 20:14:40 +0200 Subject: [PATCH 14/21] undo more changes --- stl/inc/xthreads.h | 1 - stl/src/primitives.hpp | 7 +++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index bb2666dba0..3974d6d3bc 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -169,7 +169,6 @@ class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_c _Smtx_t _Mtx; }; - #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index f08d1cadf2..3de5c60cd9 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -38,6 +38,9 @@ namespace Concurrency { stl_critical_section_vista& operator=(const stl_critical_section_vista&) = delete; ~stl_critical_section_vista() = delete; + void _Destroy() override { + DeleteCriticalSection(&_M_critical_section); + } void _Lock() override { EnterCriticalSection(&_M_critical_section); @@ -60,10 +63,6 @@ namespace Concurrency { return &_M_critical_section; } - void _Destroy() override { - DeleteCriticalSection(&_M_critical_section); - } - private: CRITICAL_SECTION _M_critical_section; }; From 13f4db8b2c329e6435b788e2a6580fedc9bdeee9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 20:21:09 +0200 Subject: [PATCH 15/21] Fully drop Vista --- stl/src/awint.hpp | 10 ---------- stl/src/filesystem.cpp | 15 --------------- stl/src/primitives.hpp | 17 +++-------------- stl/src/winapisupp.cpp | 2 +- 4 files changed, 4 insertions(+), 40 deletions(-) diff --git a/stl/src/awint.hpp b/stl/src/awint.hpp index 66eed7ab9c..657ab2e472 100644 --- a/stl/src/awint.hpp +++ b/stl/src/awint.hpp @@ -16,16 +16,6 @@ _CRT_BEGIN_C_HEADER _CRTIMP2 BOOL __cdecl __crtIsPackagedApp(); #endif // !defined(_CRT_WINDOWS) && !defined(UNDOCKED_WINDOWS_UCRT) -#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 - -#define __crtTryAcquireSRWLockExclusive(pLock) TryAcquireSRWLockExclusive(pLock) - -#else // _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 - -BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK); - -#endif // _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 - #if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8 #define __crtGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime) \ diff --git a/stl/src/filesystem.cpp b/stl/src/filesystem.cpp index 97a404bde0..d6112fdef5 100644 --- a/stl/src/filesystem.cpp +++ b/stl/src/filesystem.cpp @@ -230,21 +230,6 @@ static_assert(alignof(WIN32_FIND_DATAW) == alignof(__std_fs_find_data)); return __std_win_error::_Success; } -#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 - // If the above call failed, we might be on pre Windows 7 / Windows Server 2008 R2, which doesn't support - // FindExInfoBasic; try again with FindExInfoStandard if we got an invalid parameter error. - const __std_win_error _Last_error{GetLastError()}; - if (_Last_error != __std_win_error::_Not_supported && _Last_error != __std_win_error::_Invalid_parameter) { - return _Last_error; - } - - *_Handle = __std_fs_dir_handle{reinterpret_cast( - FindFirstFileExW(_Path_spec, FindExInfoStandard, _Results, FindExSearchNameMatch, nullptr, 0))}; - if (*_Handle != __std_fs_dir_handle::_Invalid) { - return __std_win_error::_Success; - } -#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 - return __std_win_error{GetLastError()}; } diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index 3de5c60cd9..5affdc5b9a 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -176,17 +176,6 @@ namespace Concurrency { CONDITION_VARIABLE m_condition_variable; }; - inline bool are_win7_sync_apis_available() { -#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 - return true; -#else - // TryAcquireSRWLockExclusive ONLY available on Windows 7+ - DYNAMICGETCACHEDFUNCTION( - PFNTRYACQUIRESRWLOCKEXCLUSIVE, TryAcquireSRWLockExclusive, pfTryAcquireSRWLockExclusive); - return pfTryAcquireSRWLockExclusive != nullptr; -#endif - } - inline void create_stl_critical_section(stl_critical_section_interface* p) { new (p) stl_critical_section_win7; } @@ -203,9 +192,9 @@ namespace Concurrency { #elif defined _STL_CONCRT_SUPPORT #ifdef _WIN64 - const size_t sizeof_stl_critical_section_concrt = 64; - const size_t sizeof_stl_condition_variable_concrt = 72; - const size_t alignof_stl_critical_section_concrt = 8; + const size_t sizeof_stl_critical_section_concrt = 64; + const size_t sizeof_stl_condition_variable_concrt = 72; + const size_t alignof_stl_critical_section_concrt = 8; const size_t alignof_stl_condition_variable_concrt = 8; #else // ^^^ 64-bit / 32-bit vvv const size_t sizeof_stl_critical_section_concrt = 36; diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 385f292ebd..69974a9696 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -337,7 +337,7 @@ extern "C" BOOL __cdecl __crtQueueUserWorkItem(_In_ LPTHREAD_START_ROUTINE, _In_ #if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 - +// TRANSITION, ABI: preserved for binary compatibility extern "C" BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK const pLock) { return TryAcquireSRWLockExclusive(pLock); } From 1a882ba41f3192b17281753ed544dd576bc24285 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 21:46:48 +0200 Subject: [PATCH 16/21] Revert "Fully drop Vista" This reverts commit 13f4db8b2c329e6435b788e2a6580fedc9bdeee9. --- stl/src/awint.hpp | 10 ++++++++++ stl/src/filesystem.cpp | 15 +++++++++++++++ stl/src/primitives.hpp | 17 ++++++++++++++--- stl/src/winapisupp.cpp | 2 +- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/stl/src/awint.hpp b/stl/src/awint.hpp index 657ab2e472..66eed7ab9c 100644 --- a/stl/src/awint.hpp +++ b/stl/src/awint.hpp @@ -16,6 +16,16 @@ _CRT_BEGIN_C_HEADER _CRTIMP2 BOOL __cdecl __crtIsPackagedApp(); #endif // !defined(_CRT_WINDOWS) && !defined(UNDOCKED_WINDOWS_UCRT) +#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 + +#define __crtTryAcquireSRWLockExclusive(pLock) TryAcquireSRWLockExclusive(pLock) + +#else // _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 + +BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK); + +#endif // _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 + #if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN8 #define __crtGetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime) \ diff --git a/stl/src/filesystem.cpp b/stl/src/filesystem.cpp index d6112fdef5..97a404bde0 100644 --- a/stl/src/filesystem.cpp +++ b/stl/src/filesystem.cpp @@ -230,6 +230,21 @@ static_assert(alignof(WIN32_FIND_DATAW) == alignof(__std_fs_find_data)); return __std_win_error::_Success; } +#if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 + // If the above call failed, we might be on pre Windows 7 / Windows Server 2008 R2, which doesn't support + // FindExInfoBasic; try again with FindExInfoStandard if we got an invalid parameter error. + const __std_win_error _Last_error{GetLastError()}; + if (_Last_error != __std_win_error::_Not_supported && _Last_error != __std_win_error::_Invalid_parameter) { + return _Last_error; + } + + *_Handle = __std_fs_dir_handle{reinterpret_cast( + FindFirstFileExW(_Path_spec, FindExInfoStandard, _Results, FindExSearchNameMatch, nullptr, 0))}; + if (*_Handle != __std_fs_dir_handle::_Invalid) { + return __std_win_error::_Success; + } +#endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 + return __std_win_error{GetLastError()}; } diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index 5affdc5b9a..3de5c60cd9 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -176,6 +176,17 @@ namespace Concurrency { CONDITION_VARIABLE m_condition_variable; }; + inline bool are_win7_sync_apis_available() { +#if _STL_WIN32_WINNT >= _WIN32_WINNT_WIN7 + return true; +#else + // TryAcquireSRWLockExclusive ONLY available on Windows 7+ + DYNAMICGETCACHEDFUNCTION( + PFNTRYACQUIRESRWLOCKEXCLUSIVE, TryAcquireSRWLockExclusive, pfTryAcquireSRWLockExclusive); + return pfTryAcquireSRWLockExclusive != nullptr; +#endif + } + inline void create_stl_critical_section(stl_critical_section_interface* p) { new (p) stl_critical_section_win7; } @@ -192,9 +203,9 @@ namespace Concurrency { #elif defined _STL_CONCRT_SUPPORT #ifdef _WIN64 - const size_t sizeof_stl_critical_section_concrt = 64; - const size_t sizeof_stl_condition_variable_concrt = 72; - const size_t alignof_stl_critical_section_concrt = 8; + const size_t sizeof_stl_critical_section_concrt = 64; + const size_t sizeof_stl_condition_variable_concrt = 72; + const size_t alignof_stl_critical_section_concrt = 8; const size_t alignof_stl_condition_variable_concrt = 8; #else // ^^^ 64-bit / 32-bit vvv const size_t sizeof_stl_critical_section_concrt = 36; diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 69974a9696..385f292ebd 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -337,7 +337,7 @@ extern "C" BOOL __cdecl __crtQueueUserWorkItem(_In_ LPTHREAD_START_ROUTINE, _In_ #if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 -// TRANSITION, ABI: preserved for binary compatibility + extern "C" BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK const pLock) { return TryAcquireSRWLockExclusive(pLock); } From 60630eef3fc8003772ae1aefac2d57a2e41b5ebd Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 21:52:46 +0200 Subject: [PATCH 17/21] Addressing @CaseyCarter's lawyerism --- stl/inc/mutex | 2 +- stl/inc/xthreads.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index e161bd1258..5c2fd2b67a 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -41,7 +41,7 @@ public: _Mutex_base(int _Flags = 0) noexcept { #if _HAS_CXX20 if (_STD is_constant_evaluated()) { - ::new (static_cast(&_Mtx_storage)) _Stl_critical_section_constexpr{}; + new (static_cast(&_Mtx_storage), _Constexpr_mutex_new_tag_t{}) _Stl_critical_section_constexpr{}; } else #endif // _HAS_CXX20 { diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 3974d6d3bc..f8a82e16dd 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -135,6 +135,8 @@ inline int _Check_C_return(int _Res) { // throw exception on failure } _STD_END +struct _Constexpr_mutex_new_tag_t {}; + class __declspec(novtable) _Stl_critical_section_interface { public: virtual void __thiscall _Lock() = 0; @@ -165,6 +167,10 @@ class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_c void __thiscall _Destroy() override {} + constexpr void* operator new(size_t, void* p, _Constexpr_mutex_new_tag_t) noexcept { + return p; + } + private: _Smtx_t _Mtx; }; From e151ee40b12b2f0b899727b19afc94c08d12d97e Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 21:55:00 +0200 Subject: [PATCH 18/21] This is in another change now --- stl/src/winapisupp.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/stl/src/winapisupp.cpp b/stl/src/winapisupp.cpp index 385f292ebd..aa583d138a 100644 --- a/stl/src/winapisupp.cpp +++ b/stl/src/winapisupp.cpp @@ -339,7 +339,9 @@ extern "C" BOOL __cdecl __crtQueueUserWorkItem(_In_ LPTHREAD_START_ROUTINE, _In_ #if _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 extern "C" BOOLEAN __cdecl __crtTryAcquireSRWLockExclusive(_Inout_ PSRWLOCK const pLock) { - return TryAcquireSRWLockExclusive(pLock); + DYNAMICGETCACHEDFUNCTION(PFNTRYACQUIRESRWLOCKEXCLUSIVE, TryAcquireSRWLockExclusive, pfTryAcquireSRWLockExclusive); + return pfTryAcquireSRWLockExclusive(pLock); + // Don't have fallbacks because the only caller (in primitives.hpp) will check the existence before calling } #endif // _STL_WIN32_WINNT < _WIN32_WINNT_WIN7 From 07e14d825ae7414f5c0cb2a70858f9640067ffa9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 21:59:54 +0200 Subject: [PATCH 19/21] Revert "Addressing @CaseyCarter's lawyerism" This reverts commit 60630eef3fc8003772ae1aefac2d57a2e41b5ebd. Doesn't really address --- stl/inc/mutex | 2 +- stl/inc/xthreads.h | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 5c2fd2b67a..e161bd1258 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -41,7 +41,7 @@ public: _Mutex_base(int _Flags = 0) noexcept { #if _HAS_CXX20 if (_STD is_constant_evaluated()) { - new (static_cast(&_Mtx_storage), _Constexpr_mutex_new_tag_t{}) _Stl_critical_section_constexpr{}; + ::new (static_cast(&_Mtx_storage)) _Stl_critical_section_constexpr{}; } else #endif // _HAS_CXX20 { diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index f8a82e16dd..3974d6d3bc 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -135,8 +135,6 @@ inline int _Check_C_return(int _Res) { // throw exception on failure } _STD_END -struct _Constexpr_mutex_new_tag_t {}; - class __declspec(novtable) _Stl_critical_section_interface { public: virtual void __thiscall _Lock() = 0; @@ -167,10 +165,6 @@ class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_c void __thiscall _Destroy() override {} - constexpr void* operator new(size_t, void* p, _Constexpr_mutex_new_tag_t) noexcept { - return p; - } - private: _Smtx_t _Mtx; }; From b2cad8e811238e6c41fc744df6e02a2a0e982ecb Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 22:03:26 +0200 Subject: [PATCH 20/21] `construct_at` --- stl/inc/mutex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index e161bd1258..6c2a7216b5 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -41,7 +41,7 @@ public: _Mutex_base(int _Flags = 0) noexcept { #if _HAS_CXX20 if (_STD is_constant_evaluated()) { - ::new (static_cast(&_Mtx_storage)) _Stl_critical_section_constexpr{}; + construct_at(static_cast<_Stl_critical_section_constexpr*>(static_cast(&_Mtx_storage))); } else #endif // _HAS_CXX20 { From c15c8f7c738d44ca65262441c0cb5f7121b200d4 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 2 Nov 2021 22:10:15 +0200 Subject: [PATCH 21/21] I guess a final class should have vtable... --- stl/inc/xthreads.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 3974d6d3bc..d637ac2fbf 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -144,7 +144,7 @@ class __declspec(novtable) _Stl_critical_section_interface { virtual void __thiscall _Destroy() = 0; }; -class __declspec(novtable) _Stl_critical_section_constexpr final : public _Stl_critical_section_interface { +class _Stl_critical_section_constexpr final : public _Stl_critical_section_interface { public: void __thiscall _Lock() override { _Smtx_lock_exclusive(&_Mtx);