From d45c91ee00a699d72b656c74b87f10796023e8eb Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:02:45 +0200 Subject: [PATCH 01/14] Fix #718 --- stl/CMakeLists.txt | 1 + stl/inc/__msvc_threads_core.hpp | 109 ++++++++++++++++++++++++++++++++ stl/inc/condition_variable | 21 ++---- stl/inc/header-units.json | 1 + stl/inc/mutex | 8 +-- stl/inc/thread | 30 ++++++--- stl/inc/xthreads.h | 65 +------------------ stl/src/cond.cpp | 13 +--- stl/src/mutex.cpp | 3 +- stl/src/primitives.hpp | 21 +++--- stl/src/sharedmutex.cpp | 24 ++++++- 11 files changed, 180 insertions(+), 116 deletions(-) create mode 100644 stl/inc/__msvc_threads_core.hpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 31e1ead9de..d91dc3aaa3 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -19,6 +19,7 @@ set(HEADERS ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_print.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_sanitizer_annotate_container.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_system_error_abi.hpp + ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_threads_core.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_tzdb.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/__msvc_xlocinfo_types.hpp ${CMAKE_CURRENT_LIST_DIR}/inc/algorithm diff --git a/stl/inc/__msvc_threads_core.hpp b/stl/inc/__msvc_threads_core.hpp new file mode 100644 index 0000000000..35eda02c91 --- /dev/null +++ b/stl/inc/__msvc_threads_core.hpp @@ -0,0 +1,109 @@ +// __msvc_threads_core.hpp internal header (core) + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef __MSVC_THREADS_CORE_HPP +#define __MSVC_THREADS_CORE_HPP +#include +#if _STL_COMPILER_PREPROCESSOR +#include + +#pragma pack(push, _CRT_PACKING) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : _STL_DISABLED_WARNINGS) +_STL_DISABLE_CLANG_WARNINGS +#pragma push_macro("new") +#undef new + +namespace Concurrency { + namespace details { + class stl_condition_variable_win7; + } // namespace details +} // namespace Concurrency + +extern "C" { +using _Thrd_id_t = unsigned int; +struct _Thrd_t { // thread identifier for Win32 + void* _Hnd; // Win32 HANDLE + _Thrd_id_t _Id; +}; + +using _Smtx_t = void*; + +enum class _Thrd_result : int { _Success, _Nomem, _Timedout, _Busy, _Error }; + +struct _Stl_critical_section { + void* _Unused = nullptr; // TRANSITION, ABI: was the vptr + _Smtx_t _M_srw_lock = nullptr; +}; + +struct _Mtx_internal_imp_t { +#if defined(_CRT_WINDOWS) || defined(UNDOCKED_WINDOWS_UCRT) +#ifdef _WIN64 + static constexpr size_t _Critical_section_size = 16; +#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv + static constexpr size_t _Critical_section_size = 8; +#endif // ^^^ !defined(_WIN64) ^^^ +#else // ^^^ Windows private STL / public STL vvv +#ifdef _WIN64 + static constexpr size_t _Critical_section_size = 64; +#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv + static constexpr size_t _Critical_section_size = 36; +#endif // ^^^ !defined(_WIN64) ^^^ +#endif // ^^^ public STL ^^^ + + static constexpr size_t _Critical_section_align = alignof(void*); + + int _Type{}; + union { + _Stl_critical_section _Critical_section{}; + _STD _Aligned_storage_t<_Critical_section_size, _Critical_section_align> _Cs_storage; + }; + long _Thread_id{}; + int _Count{}; +}; + +// Size and alignment for _Cnd_internal_imp_t +#if defined(_CRT_WINDOWS) // for Windows-internal code +_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 2 * sizeof(void*); +#elif defined(_WIN64) // ordinary 64-bit code +_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; +#else // vvv ordinary 32-bit code vvv +_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 40; +#endif // ^^^ ordinary 32-bit code ^^^ + +_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = alignof(void*); + +using _Mtx_t = _Mtx_internal_imp_t*; + +#ifdef _M_CEE // avoid warning LNK4248: unresolved typeref token for '_Cnd_internal_imp_t'; image may not run +using _Cnd_t = void*; +#else // ^^^ defined(_M_CEE) / !defined(_M_CEE) vvv +struct _Cnd_internal_imp_t; +using _Cnd_t = _Cnd_internal_imp_t*; +#endif // ^^^ !defined(_M_CEE) ^^^ +} // extern "C" + +#pragma pop_macro("new") +_STL_RESTORE_CLANG_WARNINGS +#pragma warning(pop) +#pragma pack(pop) +#endif // _STL_COMPILER_PREPROCESSOR +#endif // __MSVC_THREADS_CORE_HPP + +/* + * This file is derived from software bearing the following + * restrictions: + * + * (c) Copyright William E. Kempf 2001 + * + * Permission to use, copy, modify, distribute and sell this + * software and its documentation for any purpose is hereby + * granted without fee, provided that the above copyright + * notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting + * documentation. William E. Kempf makes no representations + * about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + */ diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index 8e1145db88..92d88368c1 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -124,12 +124,9 @@ public: return cv_status::timeout; } - // TRANSITION, ABI: The standard says that we should use a steady clock, - // but unfortunately our ABI relies on the system clock. - _timespec64 _Tgt; - const bool _Clamped = _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time); - const cv_status _Result = _Wait_until_sys_time(_Lck, &_Tgt); - if (_Clamped) { + const auto _Rel_time_ms = _Clamped_rel_time_ms_count(_Rel_time); + const cv_status _Result = _Wait_for_ms_count(_Lck, _Rel_time_ms._Count); + if (_Rel_time_ms._Clamped) { return cv_status::no_timeout; } @@ -206,12 +203,8 @@ public: break; } - const auto _Rel_time = _Abs_time - _Now; - // TRANSITION, ABI: The standard says that we should use a steady clock, - // but unfortunately our ABI relies on the system clock. - _timespec64 _Tgt; - (void) _To_timespec64_sys_10_day_clamped(_Tgt, _Rel_time); - (void) _Cnd_timedwait(_Mycnd(), _Myptr->_Mymtx(), &_Tgt); + const unsigned long _Rel_ms_count = _Clamped_rel_time_ms_count(_Abs_time - _Now)._Count; + (void) _Cnd_timedwait_for(_Mycnd(), _Myptr->_Mymtx(), _Rel_ms_count); _Guard_unlocks_before_locking_outer.unlock(); } // relock @@ -234,12 +227,12 @@ private: } template - cv_status _Wait_until_sys_time(_Lock& _Lck, const _timespec64* const _Abs_time) { + cv_status _Wait_for_ms_count(_Lock& _Lck, const unsigned _Rel_ms_count) { // wait for signal with timeout const shared_ptr _Ptr = _Myptr; // for immunity to *this destruction unique_lock _Guard{*_Ptr}; _Unlock_guard<_Lock> _Unlock_outer{_Lck}; - const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Ptr->_Mymtx(), _Abs_time); + const _Thrd_result _Res = _Cnd_timedwait_for(_Mycnd(), _Ptr->_Mymtx(), _Rel_ms_count); _Guard.unlock(); if (_Res == _Thrd_result::_Success) { diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index f4bdd9ce8f..125d94f600 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -17,6 +17,7 @@ "__msvc_print.hpp", "__msvc_sanitizer_annotate_container.hpp", "__msvc_system_error_abi.hpp", + "__msvc_threads_core.hpp", "__msvc_tzdb.hpp", "__msvc_xlocinfo_types.hpp", "algorithm", diff --git a/stl/inc/mutex b/stl/inc/mutex index 46f26bfda2..42544d2204 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -601,11 +601,9 @@ public: return cv_status::timeout; } - // TRANSITION, ABI: should use a steady clock - _timespec64 _Tgt; - (void) _To_timespec64_sys_10_day_clamped(_Tgt, _Abs_time - _Now); - // Nothing to do to comply with LWG-2135 because std::mutex lock/unlock are nothrow - const _Thrd_result _Res = _Cnd_timedwait(_Mycnd(), _Lck.mutex()->_Mymtx(), &_Tgt); + const unsigned long _Rel_ms_count = _Clamped_rel_time_ms_count(_Abs_time - _Now)._Count; + + const _Thrd_result _Res = _Cnd_timedwait_for(_Mycnd(), _Lck.mutex()->_Mymtx(), _Rel_ms_count); if (_Res == _Thrd_result::_Success) { return cv_status::no_timeout; } diff --git a/stl/inc/thread b/stl/inc/thread index 8bd1f188f2..2bf8534423 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -179,6 +179,24 @@ _NODISCARD auto _To_absolute_time(const chrono::duration<_Rep, _Period>& _Rel_ti return _Abs_time; } +struct _Clamped_rel_time_ms_count_result { + unsigned long _Count; + bool _Clamped; +}; + +template +_NODISCARD _Clamped_rel_time_ms_count_result _Clamped_rel_time_ms_count(const _Duration& _Rel) { + // _Clamp must be less than 2^32 - 1 (INFINITE) milliseconds, but is otherwise arbitrary. + constexpr chrono::milliseconds _Clamp{chrono::hours{24}}; + + if (_Rel >= _Clamp) { + return {static_cast(_Clamp.count()), true}; + } else { + const auto _Rel_ms = chrono::ceil(_Rel); + return {static_cast(_Rel_ms.count()), false}; + } +} + namespace this_thread { _EXPORT_STD _NODISCARD thread::id get_id() noexcept; @@ -197,16 +215,8 @@ namespace this_thread { return; } - // _Clamp must be less than 2^32 - 1 (INFINITE) milliseconds, but is otherwise arbitrary. - constexpr chrono::milliseconds _Clamp{chrono::hours{24}}; - - const auto _Rel = _Abs_time - _Now; - if (_Rel >= _Clamp) { - _Thrd_sleep_for(static_cast(_Clamp.count())); - } else { - const auto _Rel_ms = chrono::ceil(_Rel); - _Thrd_sleep_for(static_cast(_Rel_ms.count())); - } + const unsigned long _Rel_ms_count = _Clamped_rel_time_ms_count(_Abs_time - _Now)._Count; + _Thrd_sleep_for(_Rel_ms_count); } } diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 41836610fe..99f53797cd 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -7,8 +7,8 @@ #define _THR_XTHREADS_H #include #if _STL_COMPILER_PREPROCESSOR +#include <__msvc_threads_core.hpp> #include -#include #include #pragma pack(push, _CRT_PACKING) @@ -19,67 +19,6 @@ _STL_DISABLE_CLANG_WARNINGS #undef new extern "C" { -using _Thrd_id_t = unsigned int; -struct _Thrd_t { // thread identifier for Win32 - void* _Hnd; // Win32 HANDLE - _Thrd_id_t _Id; -}; - -using _Smtx_t = void*; - -struct _Stl_critical_section { - void* _Unused = nullptr; // TRANSITION, ABI: was the vptr - _Smtx_t _M_srw_lock = nullptr; -}; - -struct _Mtx_internal_imp_t { -#if defined(_CRT_WINDOWS) || defined(UNDOCKED_WINDOWS_UCRT) -#ifdef _WIN64 - static constexpr size_t _Critical_section_size = 16; -#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv - static constexpr size_t _Critical_section_size = 8; -#endif // ^^^ !defined(_WIN64) ^^^ -#else // ^^^ Windows private STL / public STL vvv -#ifdef _WIN64 - static constexpr size_t _Critical_section_size = 64; -#else // ^^^ defined(_WIN64) / !defined(_WIN64) vvv - static constexpr size_t _Critical_section_size = 36; -#endif // ^^^ !defined(_WIN64) ^^^ -#endif // ^^^ public STL ^^^ - - static constexpr size_t _Critical_section_align = alignof(void*); - - int _Type{}; - union { - _Stl_critical_section _Critical_section{}; - _STD _Aligned_storage_t<_Critical_section_size, _Critical_section_align> _Cs_storage; - }; - long _Thread_id{}; - int _Count{}; -}; - -// Size and alignment for _Cnd_internal_imp_t -#if defined(_CRT_WINDOWS) // for Windows-internal code -_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 2 * sizeof(void*); -#elif defined(_WIN64) // ordinary 64-bit code -_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 72; -#else // vvv ordinary 32-bit code vvv -_INLINE_VAR constexpr size_t _Cnd_internal_imp_size = 40; -#endif // ^^^ ordinary 32-bit code ^^^ - -_INLINE_VAR constexpr size_t _Cnd_internal_imp_alignment = alignof(void*); - -using _Mtx_t = _Mtx_internal_imp_t*; - -#ifdef _M_CEE // avoid warning LNK4248: unresolved typeref token for '_Cnd_internal_imp_t'; image may not run -using _Cnd_t = void*; -#else // ^^^ defined(_M_CEE) / !defined(_M_CEE) vvv -struct _Cnd_internal_imp_t; -using _Cnd_t = _Cnd_internal_imp_t*; -#endif // ^^^ !defined(_M_CEE) ^^^ - -enum class _Thrd_result : int { _Success, _Nomem, _Timedout, _Busy, _Error }; - // threads _CRTIMP2_PURE _Thrd_result __cdecl _Thrd_detach(_Thrd_t) noexcept; _CRTIMP2_PURE _Thrd_result __cdecl _Thrd_join(_Thrd_t, int*) noexcept; @@ -123,12 +62,12 @@ _CRTIMP2_PURE void __cdecl _Cnd_destroy(_Cnd_t) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_init_in_situ(_Cnd_t) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_destroy_in_situ(_Cnd_t) noexcept; _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_wait(_Cnd_t, _Mtx_t) noexcept; // TRANSITION, ABI: Always succeeds -_CRTIMP2_PURE _Thrd_result __cdecl _Cnd_timedwait(_Cnd_t, _Mtx_t, const _timespec64*) noexcept; _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_broadcast(_Cnd_t) noexcept; // TRANSITION, ABI: Always succeeds _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_signal(_Cnd_t) noexcept; // TRANSITION, ABI: Always succeeds _CRTIMP2_PURE void __cdecl _Cnd_register_at_thread_exit(_Cnd_t, _Mtx_t, int*) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_t) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_do_broadcast_at_thread_exit() noexcept; +_Thrd_result __stdcall _Cnd_timedwait_for(_Cnd_t, _Mtx_t, unsigned) noexcept; } // extern "C" _STD_BEGIN diff --git a/stl/src/cond.cpp b/stl/src/cond.cpp index 114475ee3a..38ae9c20a9 100644 --- a/stl/src/cond.cpp +++ b/stl/src/cond.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -11,17 +12,9 @@ extern "C" { -struct _Cnd_internal_imp_t { - typename std::_Aligned_storage<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment>::type cv; - - [[nodiscard]] Concurrency::details::stl_condition_variable_win7* _get_cv() noexcept { - // get pointer to implementation - return reinterpret_cast(&cv); - } -}; _CRTIMP2_PURE void __cdecl _Cnd_init_in_situ(const _Cnd_t cond) noexcept { // initialize condition variable in situ - Concurrency::details::create_stl_condition_variable(cond->_get_cv()); + new (cond->_get_cv()) Concurrency::details::stl_condition_variable_win7; } _CRTIMP2_PURE void __cdecl _Cnd_destroy_in_situ(_Cnd_t) noexcept {} // destroy condition variable in situ @@ -66,7 +59,7 @@ _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_wait(const _Cnd_t cond, const _Mtx_t mtx return _Thrd_result::_Success; // TRANSITION, ABI: Always succeeds } -// wait until signaled or timeout +// TRANSITION, ABI: preserved for compatibility; wait until signaled or timeout _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_timedwait( const _Cnd_t cond, const _Mtx_t mtx, const _timespec64* const target) noexcept { _Thrd_result res = _Thrd_result::_Success; diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index 44c5c2b9b4..7c046515ec 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ _CRTIMP2 void __cdecl __set_stl_sync_api_mode(__stl_sync_api_modes_enum) noexcep // TRANSITION, only used when constexpr mutex constructor is not enabled _CRTIMP2_PURE void __cdecl _Mtx_init_in_situ(_Mtx_t mtx, int type) noexcept { // initialize mutex in situ - Concurrency::details::create_stl_critical_section(&mtx->_Critical_section); + new (&mtx->_Critical_section) _Stl_critical_section; mtx->_Thread_id = -1; mtx->_Type = type; mtx->_Count = 0; diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index 15dd3f6237..d0df23c3af 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -3,9 +3,7 @@ #pragma once -#include -#include - +#include #include namespace Concurrency { @@ -43,13 +41,14 @@ namespace Concurrency { CONDITION_VARIABLE m_condition_variable = CONDITION_VARIABLE_INIT; }; - // TRANSITION, only used when constexpr mutex constructor is not enabled - inline void create_stl_critical_section(_Stl_critical_section* p) { - new (p) _Stl_critical_section; - } - - inline void create_stl_condition_variable(stl_condition_variable_win7* p) { - new (p) stl_condition_variable_win7; - } } // namespace details } // namespace Concurrency + +struct _Cnd_internal_imp_t { + typename std::_Aligned_storage<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment>::type cv; + + [[nodiscard]] Concurrency::details::stl_condition_variable_win7* _get_cv() noexcept { + // get pointer to implementation + return reinterpret_cast(&cv); + } +}; diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 64f50fe742..e80bf2fb19 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -1,13 +1,14 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include <__msvc_threads_core.hpp> #include +#include "primitives.hpp" + // these declarations must be in sync with those in xthreads.h extern "C" { -using _Smtx_t = void*; - static_assert(sizeof(_Smtx_t) == sizeof(SRWLOCK), "_Smtx_t must be the same size as SRWLOCK."); static_assert(alignof(_Smtx_t) == alignof(SRWLOCK), "_Smtx_t must be the same alignment as SRWLOCK."); @@ -39,4 +40,23 @@ void __cdecl _Smtx_unlock_shared(_Smtx_t* smtx) noexcept { // unlock non-exclusi void __stdcall _Thrd_sleep_for(const unsigned long ms) noexcept { // suspend current thread for `ms` milliseconds Sleep(ms); } + +_Thrd_result __stdcall _Cnd_timedwait_for( + const _Cnd_t cond, const _Mtx_t mtx, const unsigned target) noexcept { + _Thrd_result res = _Thrd_result::_Success; + const auto cs = &mtx->_Critical_section; + const auto start = GetTickCount64(); + if (!cond->_get_cv()->wait_for(cs, target)) { // report timeout + const auto end = GetTickCount64(); + if ((end - start) >= target) { + res = _Thrd_result::_Timedout; + } + } + // TRANSITION: replace with _Mtx_reset_owner(mtx); + mtx->_Thread_id = static_cast(GetCurrentThreadId()); + ++mtx->_Count; + + return res; +} + } // extern "C" From 2368361302fe522da2862e8d9692d7cd3cbbd2f1 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:10:49 +0200 Subject: [PATCH 02/14] can't have this forward and don't need one --- stl/inc/__msvc_threads_core.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/stl/inc/__msvc_threads_core.hpp b/stl/inc/__msvc_threads_core.hpp index 35eda02c91..27cc751b44 100644 --- a/stl/inc/__msvc_threads_core.hpp +++ b/stl/inc/__msvc_threads_core.hpp @@ -16,12 +16,6 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -namespace Concurrency { - namespace details { - class stl_condition_variable_win7; - } // namespace details -} // namespace Concurrency - extern "C" { using _Thrd_id_t = unsigned int; struct _Thrd_t { // thread identifier for Win32 From 6b07b199e96e4e881f459dac64c5522050a1bab4 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:11:38 +0200 Subject: [PATCH 03/14] format --- stl/inc/header-units.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/header-units.json b/stl/inc/header-units.json index 125d94f600..52cd5bf081 100644 --- a/stl/inc/header-units.json +++ b/stl/inc/header-units.json @@ -17,7 +17,7 @@ "__msvc_print.hpp", "__msvc_sanitizer_annotate_container.hpp", "__msvc_system_error_abi.hpp", - "__msvc_threads_core.hpp", + "__msvc_threads_core.hpp", "__msvc_tzdb.hpp", "__msvc_xlocinfo_types.hpp", "algorithm", From f7a14a399930b202080f5c79788438f43e6ebb10 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:18:06 +0200 Subject: [PATCH 04/14] include order --- stl/src/mutex.cpp | 2 +- stl/src/primitives.hpp | 1 + stl/src/sharedmutex.cpp | 5 ++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/src/mutex.cpp b/stl/src/mutex.cpp index 7c046515ec..0d8c4fa387 100644 --- a/stl/src/mutex.cpp +++ b/stl/src/mutex.cpp @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index d0df23c3af..95ac051c58 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -4,6 +4,7 @@ #pragma once #include + #include namespace Concurrency { diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index e80bf2fb19..230a75ae48 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -41,8 +41,7 @@ void __stdcall _Thrd_sleep_for(const unsigned long ms) noexcept { // suspend cur Sleep(ms); } -_Thrd_result __stdcall _Cnd_timedwait_for( - const _Cnd_t cond, const _Mtx_t mtx, const unsigned target) noexcept { +_Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, const unsigned target) noexcept { _Thrd_result res = _Thrd_result::_Success; const auto cs = &mtx->_Critical_section; const auto start = GetTickCount64(); @@ -55,7 +54,7 @@ _Thrd_result __stdcall _Cnd_timedwait_for( // TRANSITION: replace with _Mtx_reset_owner(mtx); mtx->_Thread_id = static_cast(GetCurrentThreadId()); ++mtx->_Count; - + return res; } From 3e53aab90c6f4d50e56faf8026d3a0a07e54dd45 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:21:15 +0200 Subject: [PATCH 05/14] who needs that --- stl/inc/__msvc_chrono.hpp | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/stl/inc/__msvc_chrono.hpp b/stl/inc/__msvc_chrono.hpp index 8da26708e5..c29e3459ea 100644 --- a/stl/inc/__msvc_chrono.hpp +++ b/stl/inc/__msvc_chrono.hpp @@ -715,30 +715,6 @@ namespace chrono { _EXPORT_STD using high_resolution_clock = steady_clock; } // namespace chrono -template -_NODISCARD bool _To_timespec64_sys_10_day_clamped( - _timespec64& _Ts64, const _CHRONO duration<_Rep, _Period>& _Rel_time) noexcept(is_arithmetic_v<_Rep>) { - // Convert duration to _timespec64 representing system time, maximum 10 days from now, returns whether clamping - // occurred. If clamped, timeouts will be transformed into spurious non-timeout wakes, due to ABI restrictions where - // the other side of the DLL boundary overflows int32_t milliseconds. - // Every function calling this one is TRANSITION, ABI - constexpr _CHRONO nanoseconds _Ten_days{_CHRONO hours{24} * 10}; - constexpr _CHRONO duration _Ten_days_d{_Ten_days}; - _CHRONO nanoseconds _Tx0 = _CHRONO system_clock::duration{_Xtime_get_ticks()}; - const bool _Clamped = _Ten_days_d < _Rel_time; - if (_Clamped) { - _Tx0 += _Ten_days; - } else { - _Tx0 += _CHRONO duration_cast<_CHRONO nanoseconds>(_Rel_time); - } - - const auto _Whole_seconds = _CHRONO duration_cast<_CHRONO seconds>(_Tx0); - _Ts64.tv_sec = _Whole_seconds.count(); - _Tx0 -= _Whole_seconds; - _Ts64.tv_nsec = static_cast(_Tx0.count()); - return _Clamped; -} - inline namespace literals { inline namespace chrono_literals { _EXPORT_STD _NODISCARD constexpr _CHRONO hours operator""h(unsigned long long _Val) noexcept From d5310c755a4d9c1e99722fa3c1e1269b5b3f6b80 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:28:03 +0200 Subject: [PATCH 06/14] lock it --- stl/src/sharedmutex.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 230a75ae48..2c1b22cd76 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -45,6 +45,11 @@ _Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, c _Thrd_result res = _Thrd_result::_Success; const auto cs = &mtx->_Critical_section; const auto start = GetTickCount64(); + + // TRANSITION: replace with _Mtx_clear_owner(mtx); + mtx->_Thread_id = -1; + --mtx->_Count; + if (!cond->_get_cv()->wait_for(cs, target)) { // report timeout const auto end = GetTickCount64(); if ((end - start) >= target) { From a8327f782c0b2232e47390a702f1e305613329c4 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 8 Mar 2024 21:33:40 +0200 Subject: [PATCH 07/14] format --- stl/src/sharedmutex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 2c1b22cd76..26337b6e26 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -47,7 +47,7 @@ _Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, c const auto start = GetTickCount64(); // TRANSITION: replace with _Mtx_clear_owner(mtx); - mtx->_Thread_id = -1; + mtx->_Thread_id = -1; --mtx->_Count; if (!cond->_get_cv()->wait_for(cs, target)) { // report timeout From 8fcb46de18be78b6cb0adb9cfbadd9edf2968358 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 05:26:08 -0700 Subject: [PATCH 08/14] `unsigned` => `unsigned int` --- stl/inc/condition_variable | 2 +- stl/inc/xthreads.h | 2 +- stl/src/sharedmutex.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/condition_variable b/stl/inc/condition_variable index 92d88368c1..9878204252 100644 --- a/stl/inc/condition_variable +++ b/stl/inc/condition_variable @@ -227,7 +227,7 @@ private: } template - cv_status _Wait_for_ms_count(_Lock& _Lck, const unsigned _Rel_ms_count) { + cv_status _Wait_for_ms_count(_Lock& _Lck, const unsigned int _Rel_ms_count) { // wait for signal with timeout const shared_ptr _Ptr = _Myptr; // for immunity to *this destruction unique_lock _Guard{*_Ptr}; diff --git a/stl/inc/xthreads.h b/stl/inc/xthreads.h index 99f53797cd..8681f40d08 100644 --- a/stl/inc/xthreads.h +++ b/stl/inc/xthreads.h @@ -67,7 +67,7 @@ _CRTIMP2_PURE _Thrd_result __cdecl _Cnd_signal(_Cnd_t) noexcept; // TRANSITION, _CRTIMP2_PURE void __cdecl _Cnd_register_at_thread_exit(_Cnd_t, _Mtx_t, int*) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_unregister_at_thread_exit(_Mtx_t) noexcept; _CRTIMP2_PURE void __cdecl _Cnd_do_broadcast_at_thread_exit() noexcept; -_Thrd_result __stdcall _Cnd_timedwait_for(_Cnd_t, _Mtx_t, unsigned) noexcept; +_Thrd_result __stdcall _Cnd_timedwait_for(_Cnd_t, _Mtx_t, unsigned int) noexcept; } // extern "C" _STD_BEGIN diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 26337b6e26..2846c5154b 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -41,7 +41,7 @@ void __stdcall _Thrd_sleep_for(const unsigned long ms) noexcept { // suspend cur Sleep(ms); } -_Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, const unsigned target) noexcept { +_Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, const unsigned int target) noexcept { _Thrd_result res = _Thrd_result::_Success; const auto cs = &mtx->_Critical_section; const auto start = GetTickCount64(); From 46d21e9ebe1a3e3f1eb3ed94a016004e652590fc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 05:26:51 -0700 Subject: [PATCH 09/14] Remove unnecessary parentheses. --- stl/src/sharedmutex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 2846c5154b..0b1c7a6cd5 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -52,7 +52,7 @@ _Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, c if (!cond->_get_cv()->wait_for(cs, target)) { // report timeout const auto end = GetTickCount64(); - if ((end - start) >= target) { + if (end - start >= target) { res = _Thrd_result::_Timedout; } } From d7b83f922043c0fa3c8d8311dd1fba145b6038d9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 05:28:41 -0700 Subject: [PATCH 10/14] Define `struct _Cnd_internal_imp_t` within `extern "C"`. --- stl/src/primitives.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index 95ac051c58..770ee0d0c1 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -45,6 +45,8 @@ namespace Concurrency { } // namespace details } // namespace Concurrency +extern "C" { + struct _Cnd_internal_imp_t { typename std::_Aligned_storage<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment>::type cv; @@ -53,3 +55,5 @@ struct _Cnd_internal_imp_t { return reinterpret_cast(&cv); } }; + +} // extern "C" From 07c74be7a2f6d589fa9727b7aba4c4c0b53215b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 06:00:00 -0700 Subject: [PATCH 11/14] Test `<__msvc_threads_core.hpp>` in `GH_001411_core_headers`. --- tests/std/tests/GH_001411_core_headers/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/GH_001411_core_headers/test.cpp b/tests/std/tests/GH_001411_core_headers/test.cpp index 6f962ddcd0..3e7a01bd52 100644 --- a/tests/std/tests/GH_001411_core_headers/test.cpp +++ b/tests/std/tests/GH_001411_core_headers/test.cpp @@ -9,6 +9,7 @@ // Also test GH-3103 ": Investigate making this a core header" and other internal core headers #include <__msvc_int128.hpp> #include <__msvc_system_error_abi.hpp> +#include <__msvc_threads_core.hpp> #include <__msvc_xlocinfo_types.hpp> #include #include From 721c67f991848a24ab7be84e6f6e2c0d2e62f41b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 06:49:16 -0700 Subject: [PATCH 12/14] Include ``, use the `_Aligned_storage_t` alias. --- stl/src/primitives.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/src/primitives.hpp b/stl/src/primitives.hpp index 770ee0d0c1..cd888ab514 100644 --- a/stl/src/primitives.hpp +++ b/stl/src/primitives.hpp @@ -4,6 +4,7 @@ #pragma once #include +#include #include @@ -48,7 +49,7 @@ namespace Concurrency { extern "C" { struct _Cnd_internal_imp_t { - typename std::_Aligned_storage<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment>::type cv; + std::_Aligned_storage_t<_Cnd_internal_imp_size, _Cnd_internal_imp_alignment> cv; [[nodiscard]] Concurrency::details::stl_condition_variable_win7* _get_cv() noexcept { // get pointer to implementation From 1d96f7104464d6882ccffba8b9862397e9eeda00 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 07:11:48 -0700 Subject: [PATCH 13/14] Use a strict test for clamping. --- stl/inc/thread | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/thread b/stl/inc/thread index 2bf8534423..323aa266f8 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -189,7 +189,7 @@ _NODISCARD _Clamped_rel_time_ms_count_result _Clamped_rel_time_ms_count(const _D // _Clamp must be less than 2^32 - 1 (INFINITE) milliseconds, but is otherwise arbitrary. constexpr chrono::milliseconds _Clamp{chrono::hours{24}}; - if (_Rel >= _Clamp) { + if (_Rel > _Clamp) { return {static_cast(_Clamp.count()), true}; } else { const auto _Rel_ms = chrono::ceil(_Rel); From 20c9409d16e36eb6e3f84ecdb5d14c5610194659 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 13 Mar 2024 07:18:39 -0700 Subject: [PATCH 14/14] Tag millisecond variables with `_ms`. --- stl/src/sharedmutex.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stl/src/sharedmutex.cpp b/stl/src/sharedmutex.cpp index 0b1c7a6cd5..73dbf6b288 100644 --- a/stl/src/sharedmutex.cpp +++ b/stl/src/sharedmutex.cpp @@ -41,18 +41,18 @@ void __stdcall _Thrd_sleep_for(const unsigned long ms) noexcept { // suspend cur Sleep(ms); } -_Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, const unsigned int target) noexcept { - _Thrd_result res = _Thrd_result::_Success; - const auto cs = &mtx->_Critical_section; - const auto start = GetTickCount64(); +_Thrd_result __stdcall _Cnd_timedwait_for(const _Cnd_t cond, const _Mtx_t mtx, const unsigned int target_ms) noexcept { + _Thrd_result res = _Thrd_result::_Success; + const auto cs = &mtx->_Critical_section; + const auto start_ms = GetTickCount64(); // TRANSITION: replace with _Mtx_clear_owner(mtx); mtx->_Thread_id = -1; --mtx->_Count; - if (!cond->_get_cv()->wait_for(cs, target)) { // report timeout - const auto end = GetTickCount64(); - if (end - start >= target) { + if (!cond->_get_cv()->wait_for(cs, target_ms)) { // report timeout + const auto end_ms = GetTickCount64(); + if (end_ms - start_ms >= target_ms) { res = _Thrd_result::_Timedout; } }