From 53b197dd5382c469cfec25cac717ddf075d90579 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 20:10:55 +0300 Subject: [PATCH 01/38] Implement #606 --- stl/CMakeLists.txt | 1 + stl/inc/future | 14 ++++++++++ stl/inc/mutex | 65 ++++++++++++++------------------------------ stl/inc/xcall_once.h | 2 ++ stl/src/xonce2.cpp | 28 +++++++++++++++++++ 5 files changed, 65 insertions(+), 45 deletions(-) create mode 100644 stl/src/xonce2.cpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 5bd82bd3373..d5599826d75 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -244,6 +244,7 @@ set(IMPLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/sharedmutex.cpp ${CMAKE_CURRENT_LIST_DIR}/src/syserror_import_lib.cpp ${CMAKE_CURRENT_LIST_DIR}/src/vector_algorithms.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/xonce2.cpp ) # The following files are linked in msvcp140[d][_clr].dll. diff --git a/stl/inc/future b/stl/inc/future index d50eb653751..980c03c2fc5 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -1431,6 +1431,20 @@ void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept { _Left.swap(_Right); } +// FUNCTION TEMPLATE _Invoke_stored_explicit +template +auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( + _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering + return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); +} + +// FUNCTION TEMPLATE _Invoke_stored +template +auto _Invoke_stored(tuple<_Types...>&& _Tuple) + -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple + return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); +} + // FUNCTION TEMPLATE async template class _Fake_no_copy_callable_adapter { diff --git a/stl/inc/mutex b/stl/inc/mutex index 4ad583fc954..c37d9849a1b 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -14,6 +14,7 @@ #endif // _M_CEE_PURE #include +#include #include #include #include @@ -508,59 +509,33 @@ public: }; #endif // _HAS_CXX17 -// FUNCTION TEMPLATE _Invoke_stored_explicit -template -auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( - _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering - return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); -} - -// FUNCTION TEMPLATE _Invoke_stored -template -auto _Invoke_stored(tuple<_Types...>&& _Tuple) - -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple - return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); -} - // FUNCTION TEMPLATE call_once [[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _XGetLastError(); -template -int __stdcall _Callback_once(void*, void* _Pv, void**) { // adapt call_once() to callback API - _Tuple* _Ptup = static_cast<_Tuple*>(_Pv); - - _TRY_BEGIN - // Note explicit _Seq() selects every element from *_Ptup except the last, - // which contains call_once's exception_ptr. - _Invoke_stored_explicit(_STD move(*_Ptup), _Seq()); - _CATCH_ALL - auto& _Ref = _STD get<_Idx>(*_Ptup); - _Ref = _STD current_exception(); - return 0; - _CATCH_END - - return 1; -} - template void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once - using _Tuple = tuple<_Fn&&, _Args&&..., exception_ptr&>; - using _Seq = make_index_sequence<1 + sizeof...(_Args)>; - - exception_ptr _Exc; - _Tuple _Tup(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)..., _Exc); - - _Execute_once_fp_t _Fp = &_Callback_once<_Tuple, _Seq, 1 + sizeof...(_Args)>; - - if (_Execute_once(_Flag, _Fp, _STD addressof(_Tup)) != 0) { - return; + int pending; + if (!__std_execute_once_begin(_Flag, pending)) { + _XGetLastError(); } - - if (_Exc) { - _STD rethrow_exception(_Exc); + if (!pending) { + return; // already initialized (won the race otherwise) } - _XGetLastError(); + struct _Execute_once_scope_t { + ~_Execute_once_scope_t() { + if (!__std_execute_once_complete(_Once_flag, _Flags)) + terminate(); // Cannot strongly-exception-safely throw, + // callback already executed (and might have thrown itself) + } + + once_flag& _Once_flag; + unsigned long _Flags; + } _Execute_once_scope = {_Flag, 0x4 /*INIT_ONCE_INIT_FAILED*/}; + + _STD forward<_Fn>(_Fx)(_STD forward<_Args>(_Ax)...); + + _Execute_once_scope._Flags = 0; // succeeded } // condition_variable, timed_mutex, and recursive_timed_mutex are not supported under /clr diff --git a/stl/inc/xcall_once.h b/stl/inc/xcall_once.h index 9a8066ac3bd..8bba5f58d50 100644 --- a/stl/inc/xcall_once.h +++ b/stl/inc/xcall_once.h @@ -31,6 +31,8 @@ using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**); _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept; +int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept; +int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete(once_flag& _Once_flag, unsigned long _Flags) noexcept; template union _Immortalizer_impl { // constructs _Ty, never destroys diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp new file mode 100644 index 00000000000..78b9b00ba9d --- /dev/null +++ b/stl/src/xonce2.cpp @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// __std_execute_once_begin & __std_execute_once_end functions + +#include +#include + +// This must be as small as possible, because its contents are +// injected into the msvcprt.lib and msvcprtd.lib import libraries. +// Do not include or define anything else here. +// In particular, basic_string must not be included here. + +// these declarations must be in sync with those in xcall_once.h + +_STD_BEGIN +int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() + static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); + + return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); +} + +int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete(once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() + static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); + + return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); +} +_STD_END From c9c82923a429122585792fb40e777c520227f234 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 20:15:16 +0300 Subject: [PATCH 02/38] clang format --- stl/inc/mutex | 2 +- stl/src/xonce2.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index c37d9849a1b..8a0944d305c 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -532,7 +532,7 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. once_flag& _Once_flag; unsigned long _Flags; } _Execute_once_scope = {_Flag, 0x4 /*INIT_ONCE_INIT_FAILED*/}; - + _STD forward<_Fn>(_Fx)(_STD forward<_Args>(_Ax)...); _Execute_once_scope._Flags = 0; // succeeded diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 78b9b00ba9d..f1d92220722 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -14,13 +14,15 @@ // these declarations must be in sync with those in xcall_once.h _STD_BEGIN -int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() +int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( + once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); } -int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete(once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() +int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( + once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); From 8daed26bdff71e5ffe1014df9ab273c0aa599115 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 20:23:49 +0300 Subject: [PATCH 03/38] avoid to avoid risk of bloating import lib --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index f1d92220722..38e6456464b 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -3,8 +3,8 @@ // __std_execute_once_begin & __std_execute_once_end functions -#include #include +#include "xcall_once.h" // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. From 1d21bef596d69de0d5a3cc312b477f7c362670df Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 20:26:36 +0300 Subject: [PATCH 04/38] clang format wants the other order --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 38e6456464b..c238364b1c3 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -3,8 +3,8 @@ // __std_execute_once_begin & __std_execute_once_end functions -#include #include "xcall_once.h" +#include // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. From c029e70691f25eab3eb4f803d56a1029623816f9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 20:43:15 +0300 Subject: [PATCH 05/38] control flow brace --- stl/inc/mutex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 8a0944d305c..45dd8fbaefc 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -524,9 +524,10 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. struct _Execute_once_scope_t { ~_Execute_once_scope_t() { - if (!__std_execute_once_complete(_Once_flag, _Flags)) + if (!__std_execute_once_complete(_Once_flag, _Flags)) { terminate(); // Cannot strongly-exception-safely throw, - // callback already executed (and might have thrown itself) + // callback already executed (and might have thrown itself) + } } once_flag& _Once_flag; From 85b2ba7ac824519c4f80bb700d7912f544996716 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 21:59:07 +0300 Subject: [PATCH 06/38] dynamic API --- stl/inc/future | 14 ---------- stl/inc/mutex | 51 ++++++++++++++++++++++++++++++++++- stl/inc/xcall_once.h | 2 +- stl/src/xonce2.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 113 insertions(+), 17 deletions(-) diff --git a/stl/inc/future b/stl/inc/future index 980c03c2fc5..d50eb653751 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -1431,20 +1431,6 @@ void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept { _Left.swap(_Right); } -// FUNCTION TEMPLATE _Invoke_stored_explicit -template -auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( - _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering - return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); -} - -// FUNCTION TEMPLATE _Invoke_stored -template -auto _Invoke_stored(tuple<_Types...>&& _Tuple) - -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple - return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); -} - // FUNCTION TEMPLATE async template class _Fake_no_copy_callable_adapter { diff --git a/stl/inc/mutex b/stl/inc/mutex index 45dd8fbaefc..e11204eb860 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -509,13 +509,62 @@ public: }; #endif // _HAS_CXX17 +// FUNCTION TEMPLATE _Invoke_stored_explicit +template +auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( + _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering + return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); +} + +// FUNCTION TEMPLATE _Invoke_stored +template +auto _Invoke_stored(tuple<_Types...>&& _Tuple) + -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple + return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); +} + // FUNCTION TEMPLATE call_once [[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _XGetLastError(); +template +int __stdcall _Callback_once(void*, void* _Pv, void**) { // adapt call_once() to callback API + _Tuple* _Ptup = static_cast<_Tuple*>(_Pv); + + _TRY_BEGIN + // Note explicit _Seq() selects every element from *_Ptup except the last, + // which contains call_once's exception_ptr. + _Invoke_stored_explicit(_STD move(*_Ptup), _Seq()); + _CATCH_ALL + auto& _Ref = _STD get<_Idx>(*_Ptup); + _Ref = _STD current_exception(); + return 0; + _CATCH_END + + return 1; +} + template void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once int pending; - if (!__std_execute_once_begin(_Flag, pending)) { + bool fallback = false; + if (!__std_execute_once_begin(_Flag, pending, fallback)) { + if (fallback) { + using _Tuple = tuple<_Fn&&, _Args&&..., exception_ptr&>; + using _Seq = make_index_sequence<1 + sizeof...(_Args)>; + + exception_ptr _Exc; + _Tuple _Tup(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)..., _Exc); + + _Execute_once_fp_t _Fp = &_Callback_once<_Tuple, _Seq, 1 + sizeof...(_Args)>; + + if (_Execute_once(_Flag, _Fp, _STD addressof(_Tup)) != 0) { + return; + } + + if (_Exc) { + _STD rethrow_exception(_Exc); + } + } _XGetLastError(); } if (!pending) { diff --git a/stl/inc/xcall_once.h b/stl/inc/xcall_once.h index 8bba5f58d50..f2e9adda86d 100644 --- a/stl/inc/xcall_once.h +++ b/stl/inc/xcall_once.h @@ -31,7 +31,7 @@ using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**); _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept; -int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept; +int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept; int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete(once_flag& _Once_flag, unsigned long _Flags) noexcept; template diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index c238364b1c3..5b10ee742ff 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -4,6 +4,8 @@ // __std_execute_once_begin & __std_execute_once_end functions #include "xcall_once.h" +#include +#include #include // This must be as small as possible, because its contents are @@ -13,9 +15,11 @@ // these declarations must be in sync with those in xcall_once.h +#if _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA + _STD_BEGIN int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( - once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() + once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); @@ -28,3 +32,60 @@ int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); } _STD_END + +#else // ^^^ _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA / _STL_WIN32_WINNT < _WIN32_WINNT_VISTA vvv + +namespace +{ + struct _Init_once_vista_functions_t { + std::atomic _Pfn_InitOnceBeginInitialize{}; + std::atomic _Pfn_InitOnceComplete{}; + std::atomic _Initialized{}; + }; + + _Init_once_vista_functions_t& _Get_init_once_vista_functions() { + static _Init_once_vista_functions_t functions; + if (!functions._Initialized.load(std::memory_order_acquire)) { + HMODULE kernel_module = ::GetModuleHandleW(L"Kernel32.dll"); + FARPROC init_once_begin_initialize = ::GetProcAddress(kernel_module, "InitOnceBeginInitialize"); + FARPROC init_once_complete = ::GetProcAddress(kernel_module, "InitOnceComplete"); + if (init_once_begin_initialize != nullptr && init_once_complete != nullptr) { + functions._Pfn_InitOnceBeginInitialize.store( + reinterpret_cast(init_once_begin_initialize), + std::memory_order_relaxed); + functions._Pfn_InitOnceComplete.store( + reinterpret_cast(init_once_complete), + std::memory_order_relaxed); + } + functions._Initialized.store(true, std::memory_order_release); + } + return functions; + } + +} // unnamed namespace + +_STD_BEGIN +int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( + once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() + static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); + const auto init_once_begin_initialize = + _Get_init_once_vista_functions()._Pfn_InitOnceBeginInitialize.load(std::memory_order_relaxed); + if (init_once_begin_initialize == nullptr) { + fallback = true; + return false; + } + return init_once_begin_initialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); +} + +int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( + once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() + static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); + const auto init_once_complete = + _Get_init_once_vista_functions()._Pfn_InitOnceComplete.load(std::memory_order_relaxed); + return init_once_complete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); +} +_STD_END + +#endif // _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA + + From eb9cb4ce871b3a3e12870224158be6dc536ba011 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 22:08:29 +0300 Subject: [PATCH 07/38] use INVOKE --- stl/inc/mutex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index e11204eb860..31ca7508ebe 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -583,7 +583,7 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. unsigned long _Flags; } _Execute_once_scope = {_Flag, 0x4 /*INIT_ONCE_INIT_FAILED*/}; - _STD forward<_Fn>(_Fx)(_STD forward<_Args>(_Ax)...); + _STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); _Execute_once_scope._Flags = 0; // succeeded } From 735b5cd9ca7d949ccf7213cafbece5658369d45c Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 22:17:27 +0300 Subject: [PATCH 08/38] unused parameter --- stl/src/xonce2.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 5b10ee742ff..4906075199f 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -21,7 +21,7 @@ _STD_BEGIN int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); - + (void) fallback; return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); } @@ -35,8 +35,7 @@ _STD_END #else // ^^^ _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA / _STL_WIN32_WINNT < _WIN32_WINNT_VISTA vvv -namespace -{ +namespace { struct _Init_once_vista_functions_t { std::atomic _Pfn_InitOnceBeginInitialize{}; std::atomic _Pfn_InitOnceComplete{}; @@ -54,8 +53,7 @@ namespace reinterpret_cast(init_once_begin_initialize), std::memory_order_relaxed); functions._Pfn_InitOnceComplete.store( - reinterpret_cast(init_once_complete), - std::memory_order_relaxed); + reinterpret_cast(init_once_complete), std::memory_order_relaxed); } functions._Initialized.store(true, std::memory_order_release); } @@ -87,5 +85,3 @@ int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( _STD_END #endif // _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA - - From 739cf2cc3304e53e5d8eb54f2f96b9dd995f673b Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 6 Apr 2020 22:36:02 +0300 Subject: [PATCH 09/38] msbuild update #689 --- stl/msbuild/stl_base/stl.files.settings.targets | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/msbuild/stl_base/stl.files.settings.targets b/stl/msbuild/stl_base/stl.files.settings.targets index c4126d80a13..f8dec7d76d6 100644 --- a/stl/msbuild/stl_base/stl.files.settings.targets +++ b/stl/msbuild/stl_base/stl.files.settings.targets @@ -174,6 +174,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtRoot)\github\stl\src\sharedmutex.cpp; $(CrtRoot)\github\stl\src\syserror_import_lib.cpp; $(CrtRoot)\github\stl\src\vector_algorithms.cpp; + $(CrtRoot)\github\stl\src\xonce2.cpp; "> nativecpp false From 344027d17f48dd09d7ed041c5040fc7a78d2b424 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 06:21:04 +0300 Subject: [PATCH 10/38] Update stl/inc/mutex Co-Authored-By: Stephan T. Lavavej --- stl/inc/mutex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 31ca7508ebe..8e77f62060a 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -574,7 +574,7 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. struct _Execute_once_scope_t { ~_Execute_once_scope_t() { if (!__std_execute_once_complete(_Once_flag, _Flags)) { - terminate(); // Cannot strongly-exception-safely throw, + _STD terminate(); // Cannot strongly-exception-safely throw, // callback already executed (and might have thrown itself) } } From 709ab31d8616564a9b3cee6e8adac638c0987aad Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 06:21:41 +0300 Subject: [PATCH 11/38] Update stl/src/xonce2.cpp Co-Authored-By: Stephan T. Lavavej --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 4906075199f..c7e235b3ae7 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// __std_execute_once_begin & __std_execute_once_end functions +// __std_execute_once_begin and __std_execute_once_complete functions #include "xcall_once.h" #include From 63cb2e57b90b7d4f7378b6043d5eaab52ec042ce Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 06:22:12 +0300 Subject: [PATCH 12/38] Update stl/src/xonce2.cpp Co-Authored-By: Stephan T. Lavavej --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index c7e235b3ae7..386d6dff6f8 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -26,7 +26,7 @@ int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( } int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( - once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() + once_flag& _Once_flag, const unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); From 8e67703e797f9f6a587f5d6c1623f2307a102922 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 06:24:10 +0300 Subject: [PATCH 13/38] Update stl/src/xonce2.cpp Co-Authored-By: Stephan T. Lavavej --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 386d6dff6f8..ad2318accf9 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -76,7 +76,7 @@ int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( } int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( - once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() + once_flag& _Once_flag, const unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); const auto init_once_complete = _Get_init_once_vista_functions()._Pfn_InitOnceComplete.load(std::memory_order_relaxed); From b7629f8a79c13daa7499e026df13610a9640c54d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 07:05:31 +0300 Subject: [PATCH 14/38] address review changes: names, formatting, etc --- stl/inc/mutex | 29 +++++++++++++++-------------- stl/inc/xcall_once.h | 4 ++-- stl/src/xonce2.cpp | 33 +++++++++++++++------------------ 3 files changed, 32 insertions(+), 34 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 31ca7508ebe..c836aab8605 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -544,11 +544,11 @@ int __stdcall _Callback_once(void*, void* _Pv, void**) { // adapt call_once() to } template -void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once - int pending; - bool fallback = false; - if (!__std_execute_once_begin(_Flag, pending, fallback)) { - if (fallback) { +void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once + int _Pending; + bool _Fallback = false; + if (_Execute_once_begin(_Once, _Pending, _Fallback) == 0) { + if (_Fallback) { using _Tuple = tuple<_Fn&&, _Args&&..., exception_ptr&>; using _Seq = make_index_sequence<1 + sizeof...(_Args)>; @@ -557,7 +557,7 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. _Execute_once_fp_t _Fp = &_Callback_once<_Tuple, _Seq, 1 + sizeof...(_Args)>; - if (_Execute_once(_Flag, _Fp, _STD addressof(_Tup)) != 0) { + if (_Execute_once(_Once, _Fp, _STD addressof(_Tup)) != 0) { return; } @@ -567,25 +567,26 @@ void(call_once)(once_flag& _Flag, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. } _XGetLastError(); } - if (!pending) { + + if (_Pending == 0) { return; // already initialized (won the race otherwise) } struct _Execute_once_scope_t { ~_Execute_once_scope_t() { - if (!__std_execute_once_complete(_Once_flag, _Flags)) { - terminate(); // Cannot strongly-exception-safely throw, - // callback already executed (and might have thrown itself) + if (!_Execute_once_complete(_Once, _Succeeded)) { + terminate(); // Cannot strongly-exception-safely throw, even if moved out of + // destructor, since callback already executed (and might have thrown itself) } } - once_flag& _Once_flag; - unsigned long _Flags; - } _Execute_once_scope = {_Flag, 0x4 /*INIT_ONCE_INIT_FAILED*/}; + once_flag& _Once; + bool _Succeeded; + } _Execute_once_scope = {_Once, false}; _STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); - _Execute_once_scope._Flags = 0; // succeeded + _Execute_once_scope._Succeeded = true; } // condition_variable, timed_mutex, and recursive_timed_mutex are not supported under /clr diff --git a/stl/inc/xcall_once.h b/stl/inc/xcall_once.h index f2e9adda86d..49e19ee34ff 100644 --- a/stl/inc/xcall_once.h +++ b/stl/inc/xcall_once.h @@ -31,8 +31,8 @@ using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**); _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept; -int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin(once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept; -int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete(once_flag& _Once_flag, unsigned long _Flags) noexcept; +int __CLRCALL_PURE_OR_CDECL _Execute_once_begin(once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept; +int __CLRCALL_PURE_OR_CDECL _Execute_once_complete(once_flag& _Once_flag, bool _Succeeded) noexcept; template union _Immortalizer_impl { // constructs _Ty, never destroys diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 4906075199f..a8da2001482 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -3,33 +3,32 @@ // __std_execute_once_begin & __std_execute_once_end functions -#include "xcall_once.h" #include #include #include +#include // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. // Do not include or define anything else here. // In particular, basic_string must not be included here. +static_assert(sizeof(std::once_flag::_Opaque) == sizeof(INIT_ONCE), "invalid size"); + // these declarations must be in sync with those in xcall_once.h #if _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA _STD_BEGIN int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( - once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() - static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); - (void) fallback; + once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() + (void) _Fallback; return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); } int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( - once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() - static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); - - return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); + once_flag& _Once_flag, unsigned long _Completion_flags) noexcept { // wrap Win32 InitOnceComplete() + return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Completion_flags, nullptr); } _STD_END @@ -42,7 +41,7 @@ namespace { std::atomic _Initialized{}; }; - _Init_once_vista_functions_t& _Get_init_once_vista_functions() { + const _Init_once_vista_functions_t& _Get_init_once_vista_functions() noexcept { static _Init_once_vista_functions_t functions; if (!functions._Initialized.load(std::memory_order_acquire)) { HMODULE kernel_module = ::GetModuleHandleW(L"Kernel32.dll"); @@ -59,28 +58,26 @@ namespace { } return functions; } - } // unnamed namespace _STD_BEGIN -int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( - once_flag& _Once_flag, int& _Pending, bool& fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() - static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); +int __CLRCALL_PURE_OR_CDECL _Execute_once_begin( + once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() const auto init_once_begin_initialize = _Get_init_once_vista_functions()._Pfn_InitOnceBeginInitialize.load(std::memory_order_relaxed); if (init_once_begin_initialize == nullptr) { - fallback = true; + _Fallback = true; return false; } return init_once_begin_initialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); } -int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( - once_flag& _Once_flag, unsigned long _Flags) noexcept { // wrap Win32 InitOnceComplete() - static_assert(sizeof(_Once_flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); +int __CLRCALL_PURE_OR_CDECL _Execute_once_complete( + once_flag& _Once_flag, bool _Succeeded) noexcept { // wrap Win32 InitOnceComplete() const auto init_once_complete = _Get_init_once_vista_functions()._Pfn_InitOnceComplete.load(std::memory_order_relaxed); - return init_once_complete(reinterpret_cast(&_Once_flag._Opaque), _Flags, nullptr); + return init_once_complete( + reinterpret_cast(&_Once_flag._Opaque), _Succeeded ? 0 : INIT_ONCE_INIT_FAILED, nullptr); } _STD_END From b28b93fee3f0c0f49e0d4421759421b19c1d4ba8 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 7 Apr 2020 07:18:04 +0300 Subject: [PATCH 15/38] More precise terminate comment --- stl/inc/mutex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 4f37a4f9c97..f0c8d59e81e 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -575,8 +575,8 @@ void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax.. struct _Execute_once_scope_t { ~_Execute_once_scope_t() { if (!_Execute_once_complete(_Once_flag, _Succeeded)) { - _STD terminate(); // Cannot strongly-exception-safely throw, - // callback already executed (and might have thrown itself) + _STD terminate(); // Cannot throw, even if moved out of destructor. + // call_once is permited to throw if some condition prevented from calling the callback. } } From 21a99f34a42374a8b1cfa6daa2eaf157c6f30514 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 9 Apr 2020 08:00:44 +0300 Subject: [PATCH 16/38] explain parentheses --- stl/inc/mutex | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/mutex b/stl/inc/mutex index f0c8d59e81e..8e43f685313 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -545,6 +545,7 @@ int __stdcall _Callback_once(void*, void* _Pv, void**) { // adapt call_once() to template void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once + // parentheses against common "#define call_once(flag,func) pthread_once(flag,func)" int _Pending; bool _Fallback = false; if (_Execute_once_begin(_Once, _Pending, _Fallback) == 0) { From b8568781a7bc29ed48dc4e4a60e1a0fa727ab423 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 09:21:38 +0300 Subject: [PATCH 17/38] Still move out XP callback, dup spinning from #593 --- stl/inc/future | 14 ++++++++ stl/inc/mutex | 52 +----------------------------- stl/inc/xcall_once.h | 2 +- stl/src/xonce2.cpp | 76 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 88 insertions(+), 56 deletions(-) diff --git a/stl/inc/future b/stl/inc/future index d50eb653751..980c03c2fc5 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -1431,6 +1431,20 @@ void swap(packaged_task<_Ty>& _Left, packaged_task<_Ty>& _Right) noexcept { _Left.swap(_Right); } +// FUNCTION TEMPLATE _Invoke_stored_explicit +template +auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( + _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering + return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); +} + +// FUNCTION TEMPLATE _Invoke_stored +template +auto _Invoke_stored(tuple<_Types...>&& _Tuple) + -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple + return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); +} + // FUNCTION TEMPLATE async template class _Fake_no_copy_callable_adapter { diff --git a/stl/inc/mutex b/stl/inc/mutex index 8e43f685313..b4258bc97b1 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -509,63 +508,14 @@ public: }; #endif // _HAS_CXX17 -// FUNCTION TEMPLATE _Invoke_stored_explicit -template -auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices...>) -> decltype( - _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...)) { // invoke() a tuple with explicit parameter ordering - return _STD invoke(_STD get<_Indices>(_STD move(_Tuple))...); -} - -// FUNCTION TEMPLATE _Invoke_stored -template -auto _Invoke_stored(tuple<_Types...>&& _Tuple) - -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple - return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); -} - // FUNCTION TEMPLATE call_once [[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _XGetLastError(); -template -int __stdcall _Callback_once(void*, void* _Pv, void**) { // adapt call_once() to callback API - _Tuple* _Ptup = static_cast<_Tuple*>(_Pv); - - _TRY_BEGIN - // Note explicit _Seq() selects every element from *_Ptup except the last, - // which contains call_once's exception_ptr. - _Invoke_stored_explicit(_STD move(*_Ptup), _Seq()); - _CATCH_ALL - auto& _Ref = _STD get<_Idx>(*_Ptup); - _Ref = _STD current_exception(); - return 0; - _CATCH_END - - return 1; -} - template void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once // parentheses against common "#define call_once(flag,func) pthread_once(flag,func)" int _Pending; - bool _Fallback = false; - if (_Execute_once_begin(_Once, _Pending, _Fallback) == 0) { - if (_Fallback) { - using _Tuple = tuple<_Fn&&, _Args&&..., exception_ptr&>; - using _Seq = make_index_sequence<1 + sizeof...(_Args)>; - - exception_ptr _Exc; - _Tuple _Tup(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)..., _Exc); - - _Execute_once_fp_t _Fp = &_Callback_once<_Tuple, _Seq, 1 + sizeof...(_Args)>; - - if (_Execute_once(_Once, _Fp, _STD addressof(_Tup)) != 0) { - return; - } - - if (_Exc) { - _STD rethrow_exception(_Exc); - } - } + if (_Execute_once_begin(_Once, _Pending) == 0) { _XGetLastError(); } diff --git a/stl/inc/xcall_once.h b/stl/inc/xcall_once.h index 49e19ee34ff..0e4c8afa9bc 100644 --- a/stl/inc/xcall_once.h +++ b/stl/inc/xcall_once.h @@ -31,7 +31,7 @@ using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**); _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept; -int __CLRCALL_PURE_OR_CDECL _Execute_once_begin(once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept; +int __CLRCALL_PURE_OR_CDECL _Execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept; int __CLRCALL_PURE_OR_CDECL _Execute_once_complete(once_flag& _Once_flag, bool _Succeeded) noexcept; template diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 9e4bf91049e..81deb29fa0d 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -5,9 +5,10 @@ #include #include -#include #include +#include + // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. // Do not include or define anything else here. @@ -58,16 +59,80 @@ namespace { } return functions; } + + // XP fallback values must use the same values as in __crtInitOnceExecuteOnce from winapisupp.cpp + void* const PV_INITIAL = reinterpret_cast(static_cast(0)); + void* const PV_WORKING = reinterpret_cast(static_cast(1)); + void* const PV_SUCCESS = reinterpret_cast(static_cast(2)); + + int _InitOnceBeginInitializeXpFallback(void** const flag, int& pending) { + enum { Spin, Yield, Sleep } wait_phase = Spin; + int spin_count = 10'000; + int sleep_value = 2; + + for (;;) { + void* const previous = _InterlockedCompareExchangePointer(flag, PV_WORKING, PV_INITIAL); + + if (previous == PV_SUCCESS) { + pending = FALSE; + return TRUE; + } else if (previous == PV_INITIAL) { + pending = TRUE; + return TRUE; + } else if (previous == PV_WORKING) { + switch (wait_phase) { + case Spin: + if (spin_count != 0) { + spin_count--; + _YIELD_PROCESSOR(); + continue; + } + spin_count = 4; + wait_phase = Yield; + [[fallthrough]]; + + case Yield: + if (spin_count != 0) { + spin_count--; + ::SwitchToThread(); + continue; + } + wait_phase = Sleep; + [[fallthrough]]; + + case Sleep: + ::Sleep(sleep_value); + sleep_value = min(sleep_value + sleep_value / 2, 4000); + continue; + } + } else { + pending = FALSE; + ::SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + } + } + + int _InitOnceInitOnceCompleteXpFallback(void** const flag, bool suceeded) { + for (;;) { + if (_InterlockedExchangePointer(flag, suceeded ? PV_SUCCESS : PV_INITIAL) == PV_WORKING) { + return TRUE; + } else { + SetLastError(ERROR_INVALID_DATA); + return FALSE; + } + } + } + } // unnamed namespace _STD_BEGIN int __CLRCALL_PURE_OR_CDECL _Execute_once_begin( - once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() + once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() const auto init_once_begin_initialize = _Get_init_once_vista_functions()._Pfn_InitOnceBeginInitialize.load(std::memory_order_relaxed); if (init_once_begin_initialize == nullptr) { - _Fallback = true; - return false; + return _InitOnceInitOnceCompleteXpFallback(&_Once_flag._Opaque, _Pending); } return init_once_begin_initialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); } @@ -76,6 +141,9 @@ int __CLRCALL_PURE_OR_CDECL _Execute_once_complete( once_flag& _Once_flag, const bool _Succeeded) noexcept { // wrap Win32 InitOnceComplete() const auto init_once_complete = _Get_init_once_vista_functions()._Pfn_InitOnceComplete.load(std::memory_order_relaxed); + if (init_once_complete == nullptr) { + return _InitOnceInitOnceCompleteXpFallback(&_Once_flag._Opaque, _Succeeded); + } return init_once_complete( reinterpret_cast(&_Once_flag._Opaque), _Succeeded ? 0 : INIT_ONCE_INIT_FAILED, nullptr); } From 84876de81447ee782b9e8c562ad9ce40508158b1 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 09:39:10 +0300 Subject: [PATCH 18/38] clang format --- stl/src/xonce2.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 81deb29fa0d..b8d04343f2c 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -67,8 +67,8 @@ namespace { int _InitOnceBeginInitializeXpFallback(void** const flag, int& pending) { enum { Spin, Yield, Sleep } wait_phase = Spin; - int spin_count = 10'000; - int sleep_value = 2; + int spin_count = 10'000; + int sleep_value = 2; for (;;) { void* const previous = _InterlockedCompareExchangePointer(flag, PV_WORKING, PV_INITIAL); @@ -90,14 +90,14 @@ namespace { spin_count = 4; wait_phase = Yield; [[fallthrough]]; - + case Yield: if (spin_count != 0) { spin_count--; ::SwitchToThread(); continue; } - wait_phase = Sleep; + wait_phase = Sleep; [[fallthrough]]; case Sleep: From 4f501d6ea7f22436d695f25d761b7d27af952432 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 12:23:47 +0300 Subject: [PATCH 19/38] x86 build --- stl/src/xonce2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index b8d04343f2c..5e0803d4446 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include From 0e37c3c57a052c6c75ad5ad3cb32637b6153f69f Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 12:35:40 +0300 Subject: [PATCH 20/38] clang format --- stl/src/xonce2.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 5e0803d4446..99873068d09 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -4,12 +4,10 @@ // __std_execute_once_begin and __std_execute_once_complete functions #include -#include #include +#include #include -#include - // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. // Do not include or define anything else here. From 6f6b244b658ce55989f3c74891589d593f91c1cc Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 21:13:33 +0300 Subject: [PATCH 21/38] Warrant constants by constexpr --- stl/src/xonce2.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 99873068d09..ef10d48e197 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -60,9 +60,12 @@ namespace { } // XP fallback values must use the same values as in __crtInitOnceExecuteOnce from winapisupp.cpp - void* const PV_INITIAL = reinterpret_cast(static_cast(0)); - void* const PV_WORKING = reinterpret_cast(static_cast(1)); - void* const PV_SUCCESS = reinterpret_cast(static_cast(2)); + constexpr uintptr_t PV_INITIAL = 0; + constexpr uintptr_t PV_WORKING = 1; + constexpr uintptr_t PV_SUCCESS = 2; + + //uintptr_t _InterlockedCompareExchangePtrDestUintValues + int _InitOnceBeginInitializeXpFallback(void** const flag, int& pending) { enum { Spin, Yield, Sleep } wait_phase = Spin; @@ -70,7 +73,8 @@ namespace { int sleep_value = 2; for (;;) { - void* const previous = _InterlockedCompareExchangePointer(flag, PV_WORKING, PV_INITIAL); + const auto previous = reinterpret_cast( + __crt_interlocked_compare_exchange_pointer(flag, PV_WORKING, PV_INITIAL)); if (previous == PV_SUCCESS) { pending = FALSE; @@ -114,7 +118,10 @@ namespace { int _InitOnceInitOnceCompleteXpFallback(void** const flag, bool suceeded) { for (;;) { - if (_InterlockedExchangePointer(flag, suceeded ? PV_SUCCESS : PV_INITIAL) == PV_WORKING) { + const auto previous = reinterpret_cast( + __crt_interlocked_exchange_pointer(flag, suceeded ? PV_SUCCESS : PV_INITIAL)); + + if (previous == PV_WORKING) { return TRUE; } else { SetLastError(ERROR_INVALID_DATA); From 7e5dd6295e5b3729bd93872c96088689618560c7 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Fri, 24 Apr 2020 21:15:40 +0300 Subject: [PATCH 22/38] remove accidentally left comment --- stl/src/xonce2.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index ef10d48e197..2ac9cbc3d0e 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -64,9 +64,6 @@ namespace { constexpr uintptr_t PV_WORKING = 1; constexpr uintptr_t PV_SUCCESS = 2; - //uintptr_t _InterlockedCompareExchangePtrDestUintValues - - int _InitOnceBeginInitializeXpFallback(void** const flag, int& pending) { enum { Spin, Yield, Sleep } wait_phase = Spin; int spin_count = 10'000; From c646d9c8e521d65a97f4ed44340226f37ee7df15 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 2 May 2020 19:55:43 +0300 Subject: [PATCH 23/38] braces fix --- stl/inc/future | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/future b/stl/inc/future index 0a9c5ce9e48..99c0f93032b 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -1439,8 +1439,8 @@ auto _Invoke_stored_explicit(tuple<_Types...>&& _Tuple, index_sequence<_Indices. // FUNCTION TEMPLATE _Invoke_stored template auto _Invoke_stored(tuple<_Types...>&& _Tuple) - -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>())) { // invoke() a tuple - return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>()); + -> decltype(_Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>{})) { // invoke() a tuple + return _Invoke_stored_explicit(_STD move(_Tuple), index_sequence_for<_Types...>{}); } // FUNCTION TEMPLATE async From 101128348864f93681d143099cf61eeebd6b532b Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 4 May 2020 21:25:59 -0700 Subject: [PATCH 24/38] Due to complete dropping of XP support with the import libraries, use aliasobj to call InitOnceBeginInitialize and InitOnceComplete directly from the header. --- stl/CMakeLists.txt | 3 +- .../amd64/std_init_once_begin_initialize.obj | Bin 0 -> 223 bytes stl/aliases/amd64/std_init_once_complete.obj | Bin 0 -> 208 bytes .../arm/std_init_once_begin_initialize.obj | Bin 0 -> 223 bytes stl/aliases/arm/std_init_once_complete.obj | Bin 0 -> 208 bytes .../arm64/std_init_once_begin_initialize.obj | Bin 0 -> 223 bytes stl/aliases/arm64/std_init_once_complete.obj | Bin 0 -> 208 bytes stl/aliases/generate.cmd | 47 ++++++ .../i386/std_init_once_begin_initialize.obj | Bin 0 -> 231 bytes stl/aliases/i386/std_init_once_complete.obj | Bin 0 -> 216 bytes stl/inc/mutex | 67 +++++--- stl/inc/xcall_once.h | 2 - .../stl_base/stl.files.settings.targets | 1 - .../stl_post/msvcp_post.settings.targets | 2 + stl/src/ppltasks.cpp | 12 +- stl/src/xonce.cpp | 1 + stl/src/xonce2.cpp | 155 ------------------ 17 files changed, 104 insertions(+), 186 deletions(-) create mode 100644 stl/aliases/amd64/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/amd64/std_init_once_complete.obj create mode 100644 stl/aliases/arm/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/arm/std_init_once_complete.obj create mode 100644 stl/aliases/arm64/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/arm64/std_init_once_complete.obj create mode 100644 stl/aliases/generate.cmd create mode 100644 stl/aliases/i386/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/i386/std_init_once_complete.obj delete mode 100644 stl/src/xonce2.cpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index d5599826d75..5a521d55680 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -244,7 +244,8 @@ set(IMPLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/sharedmutex.cpp ${CMAKE_CURRENT_LIST_DIR}/src/syserror_import_lib.cpp ${CMAKE_CURRENT_LIST_DIR}/src/vector_algorithms.cpp - ${CMAKE_CURRENT_LIST_DIR}/src/xonce2.cpp + ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_begin_initialize.obj + ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_complete.obj ) # The following files are linked in msvcp140[d][_clr].dll. diff --git a/stl/aliases/amd64/std_init_once_begin_initialize.obj b/stl/aliases/amd64/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..452313ab3f70f8cc4702766a98646cdff8f1f252 GIT binary patch literal 223 zcmZQzU}V_$c|)8H0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTM0=dlMy7wj3mOq;0ff#$7kji#CzstmiXr-r#hvk lXXb%8nTa`>RjE+f`1sOTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTN+6ulMy7wj3mOqUV7nh{OX96YT^MSJQAeVrp0nwl))&Kwi literal 0 HcmV?d00001 diff --git a/stl/aliases/arm/std_init_once_begin_initialize.obj b/stl/aliases/arm/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..452313ab3f70f8cc4702766a98646cdff8f1f252 GIT binary patch literal 223 zcmZQzU}V_$c|)8H0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTM0=dlMy7wj3mOq;0ff#$7kji#CzstmiXr-r#hvk lXXb%8nTa`>RjE+f`1sOTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTN+6ulMy7wj3mOqUV7nh{OX96YT^MSJQAeVrp0nwl))&Kwi literal 0 HcmV?d00001 diff --git a/stl/aliases/arm64/std_init_once_begin_initialize.obj b/stl/aliases/arm64/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..452313ab3f70f8cc4702766a98646cdff8f1f252 GIT binary patch literal 223 zcmZQzU}V_$c|)8H0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTM0=dlMy7wj3mOq;0ff#$7kji#CzstmiXr-r#hvk lXXb%8nTa`>RjE+f`1sOTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTN+6ulMy7wj3mOqUV7nh{OX96YT^MSJQAeVrp0nwl))&Kwi literal 0 HcmV?d00001 diff --git a/stl/aliases/generate.cmd b/stl/aliases/generate.cmd new file mode 100644 index 00000000000..44a0ebaeafd --- /dev/null +++ b/stl/aliases/generate.cmd @@ -0,0 +1,47 @@ +:: Copyright (c) Microsoft Corporation. +:: SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +:: +:: Generates aliases for Windows API functions called by headers. +:: TRANSITION, VSO-1116868 "'aliasobj.exe' should be available with Visual Studio" + +cd %~dp0 + +rmdir /s /q i386 +rmdir /s /q amd64 +rmdir /s /q arm +rmdir /s /q arm64 + +mkdir i386 +mkdir amd64 +mkdir arm +mkdir arm64 + +:: __std_init_once_begin_initialize +..\..\..\..\..\tools\x86\aliasobj.exe ^ + __imp____std_init_once_begin_initialize@16 ^ + __imp__InitOnceBeginInitialize@16 ^ + i386\std_init_once_begin_initialize.obj +..\..\..\..\..\tools\amd64\aliasobj.exe ^ + __imp___std_init_once_begin_initialize ^ + __imp_InitOnceBeginInitialize ^ + amd64\std_init_once_begin_initialize.obj +..\..\..\..\..\tools\x86\aliasobj.exe ^ + __imp___std_init_once_begin_initialize ^ + __imp_InitOnceBeginInitialize ^ + arm\std_init_once_begin_initialize.obj +copy amd64\std_init_once_begin_initialize.obj arm64\std_init_once_begin_initialize.obj + +:: __std_init_once_complete +..\..\..\..\..\tools\x86\aliasobj.exe ^ + __imp____std_init_once_complete@12 ^ + __imp__InitOnceComplete@12 ^ + i386\std_init_once_complete.obj +..\..\..\..\..\tools\amd64\aliasobj.exe ^ + __imp___std_init_once_complete ^ + __imp_InitOnceComplete ^ + amd64\std_init_once_complete.obj +..\..\..\..\..\tools\x86\aliasobj.exe ^ + __imp___std_init_once_complete ^ + __imp_InitOnceComplete ^ + arm\std_init_once_complete.obj +copy amd64\std_init_once_complete.obj arm64\std_init_once_complete.obj diff --git a/stl/aliases/i386/std_init_once_begin_initialize.obj b/stl/aliases/i386/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..46243a4db69336cef5f64949cf479298bb456e41 GIT binary patch literal 231 zcmZQzU}V_$c|)8H0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTMbDhlMy7wj3mOq5D4VO$7kji#K(K)WtRBoC8s*2 prf24XIGKq#nN_I{hGsAo@$tnaDe;*=srY=L!uTYRN-!Ux6acYjF8=@k literal 0 HcmV?d00001 diff --git a/stl/aliases/i386/std_init_once_complete.obj b/stl/aliases/i386/std_init_once_complete.obj new file mode 100644 index 0000000000000000000000000000000000000000..59a56df805262b6b6a15bb9e5311e8c7db18b29b GIT binary patch literal 216 zcmZQzU}V_$c|)8H0|Nsq5QBhTN>OTZNm(j{hlAu|U~ovz&n?i)Ofii4%kcj{0|PUI zLt1KLiJpOhAW#!T1f-h<$p|JeTOLUylMy7wj3mOq-~{Bw$7kji#K(K)WtRBoC8s(A h?aE0lNp&zZf=R{47nh{OX95+(=L1#5gPa3X0ssWEDCPhF literal 0 HcmV?d00001 diff --git a/stl/inc/mutex b/stl/inc/mutex index 364e5be4284..4a584b6607e 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -13,8 +13,8 @@ #error is not supported when compiling with /clr:pure. #endif // _M_CEE_PURE +#include #include -#include #include #include #include @@ -509,35 +509,56 @@ public: #endif // _HAS_CXX17 // FUNCTION TEMPLATE call_once -[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _XGetLastError(); +// WINBASEAPI +// BOOL +// WINAPI +// InitOnceBeginInitialize( +// _Inout_ LPINIT_ONCE lpInitOnce, +// _In_ DWORD dwFlags, +// _Out_ PBOOL fPending, +// _Outptr_opt_result_maybenull_ LPVOID* lpContext +// ); +extern "C" int __declspec(dllimport) __stdcall __std_init_once_begin_initialize( + void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept; +// WINBASEAPI +// BOOL +// WINAPI +// InitOnceComplete( +// _Inout_ LPINIT_ONCE lpInitOnce, +// _In_ DWORD dwFlags, +// _In_opt_ LPVOID lpContext +// ); +extern "C" int __declspec(dllimport) __stdcall __std_init_once_complete( + void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept; +// #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL +// #define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED +_INLINE_VAR constexpr unsigned long _Init_once_init_failed = 0x4UL; +struct _Init_once_completer { + once_flag& _Once; + unsigned long _DwFlags; + ~_Init_once_completer() { + if (__std_init_once_complete(&_Once._Opaque, _DwFlags, nullptr) == 0) { + _CSTD abort(); + } + } +}; template -void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) { // call _Fx(_Ax...) once +void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) noexcept( + noexcept(_STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...))) // Strengthened +{ + // call _Fx(_Ax...) once // parentheses against common "#define call_once(flag,func) pthread_once(flag,func)" int _Pending; - if (_Execute_once_begin(_Once, _Pending) == 0) { - _XGetLastError(); + if (__std_init_once_begin_initialize(&_Once._Opaque, 0, &_Pending, nullptr) == 0) { + _CSTD abort(); } - if (_Pending == 0) { - return; // already initialized (won the race otherwise) + if (_Pending) { + _Init_once_completer _Op{_Once, _Init_once_init_failed}; + _STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); + _Op._DwFlags = 0; } - - struct _Execute_once_scope_t { - ~_Execute_once_scope_t() { - if (!_Execute_once_complete(_Once_flag, _Succeeded)) { - _STD terminate(); // Cannot throw, even if moved out of destructor. - // call_once is permited to throw if some condition prevented from calling the callback. - } - } - - once_flag& _Once_flag; - bool _Succeeded; - } _Execute_once_scope = {_Once, false}; - - _STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); - - _Execute_once_scope._Succeeded = true; } // condition_variable, timed_mutex, and recursive_timed_mutex are not supported under /clr diff --git a/stl/inc/xcall_once.h b/stl/inc/xcall_once.h index 0e4c8afa9bc..9a8066ac3bd 100644 --- a/stl/inc/xcall_once.h +++ b/stl/inc/xcall_once.h @@ -31,8 +31,6 @@ using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**); _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept; -int __CLRCALL_PURE_OR_CDECL _Execute_once_begin(once_flag& _Once_flag, int& _Pending) noexcept; -int __CLRCALL_PURE_OR_CDECL _Execute_once_complete(once_flag& _Once_flag, bool _Succeeded) noexcept; template union _Immortalizer_impl { // constructs _Ty, never destroys diff --git a/stl/msbuild/stl_base/stl.files.settings.targets b/stl/msbuild/stl_base/stl.files.settings.targets index f8dec7d76d6..c4126d80a13 100644 --- a/stl/msbuild/stl_base/stl.files.settings.targets +++ b/stl/msbuild/stl_base/stl.files.settings.targets @@ -174,7 +174,6 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtRoot)\github\stl\src\sharedmutex.cpp; $(CrtRoot)\github\stl\src\syserror_import_lib.cpp; $(CrtRoot)\github\stl\src\vector_algorithms.cpp; - $(CrtRoot)\github\stl\src\xonce2.cpp; "> nativecpp false diff --git a/stl/msbuild/stl_post/msvcp_post.settings.targets b/stl/msbuild/stl_post/msvcp_post.settings.targets index 6325ec4f978..6d09f6244f5 100644 --- a/stl/msbuild/stl_post/msvcp_post.settings.targets +++ b/stl/msbuild/stl_post/msvcp_post.settings.targets @@ -54,6 +54,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + diff --git a/stl/src/ppltasks.cpp b/stl/src/ppltasks.cpp index d09ea267903..52a5aff5625 100644 --- a/stl/src/ppltasks.cpp +++ b/stl/src/ppltasks.cpp @@ -114,15 +114,19 @@ namespace Concurrency { } bool isCausalitySupported() { - std::call_once(m_stateFlag, [this] { + // TRANSITION, ABI + _Execute_once(m_stateFlag, [](void*, void* _This_raw, void**) -> int { + const auto _This = static_cast(_This_raw); ComPtr causalityAPIs; if (SUCCEEDED(GetActivationFactory( HStringReference(RuntimeClass_Windows_Foundation_Diagnostics_AsyncCausalityTracer).Get(), &causalityAPIs))) { - m_causalityAPIs = causalityAPIs.Detach(); - m_isSupported = true; + _This->m_causalityAPIs = causalityAPIs.Detach(); + _This->m_isSupported = true; } - }); + + return 1; + }, this); return m_isSupported; } } asyncCausalityTracer; diff --git a/stl/src/xonce.cpp b/stl/src/xonce.cpp index f6310f02f62..a7cbfd974c2 100644 --- a/stl/src/xonce.cpp +++ b/stl/src/xonce.cpp @@ -7,6 +7,7 @@ #include _STD_BEGIN +// TRANSITION, ABI _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once( once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept { // wrap Win32 InitOnceExecuteOnce() static_assert(sizeof(_Flag._Opaque) == sizeof(INIT_ONCE), "invalid size"); diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp deleted file mode 100644 index 2ac9cbc3d0e..00000000000 --- a/stl/src/xonce2.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -// __std_execute_once_begin and __std_execute_once_complete functions - -#include -#include -#include -#include - -// This must be as small as possible, because its contents are -// injected into the msvcprt.lib and msvcprtd.lib import libraries. -// Do not include or define anything else here. -// In particular, basic_string must not be included here. - -static_assert(sizeof(std::once_flag::_Opaque) == sizeof(INIT_ONCE), "invalid size"); - -// these declarations must be in sync with those in xcall_once.h - -#if _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA - -_STD_BEGIN -int __CLRCALL_PURE_OR_CDECL __std_execute_once_begin( - once_flag& _Once_flag, int& _Pending, bool& _Fallback) noexcept { // wrap Win32 InitOnceBeginInitialize() - (void) _Fallback; - return ::InitOnceBeginInitialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); -} - -int __CLRCALL_PURE_OR_CDECL __std_execute_once_complete( - once_flag& _Once_flag, const unsigned long _Completion_flags) noexcept { // wrap Win32 InitOnceComplete() - return ::InitOnceComplete(reinterpret_cast(&_Once_flag._Opaque), _Completion_flags, nullptr); -} -_STD_END - -#else // ^^^ _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA / _STL_WIN32_WINNT < _WIN32_WINNT_VISTA vvv - -namespace { - struct _Init_once_vista_functions_t { - std::atomic _Pfn_InitOnceBeginInitialize{}; - std::atomic _Pfn_InitOnceComplete{}; - std::atomic _Initialized{}; - }; - - const _Init_once_vista_functions_t& _Get_init_once_vista_functions() noexcept { - static _Init_once_vista_functions_t functions; - if (!functions._Initialized.load(std::memory_order_acquire)) { - HMODULE kernel_module = ::GetModuleHandleW(L"Kernel32.dll"); - FARPROC init_once_begin_initialize = ::GetProcAddress(kernel_module, "InitOnceBeginInitialize"); - FARPROC init_once_complete = ::GetProcAddress(kernel_module, "InitOnceComplete"); - if (init_once_begin_initialize != nullptr && init_once_complete != nullptr) { - functions._Pfn_InitOnceBeginInitialize.store( - reinterpret_cast(init_once_begin_initialize), - std::memory_order_relaxed); - functions._Pfn_InitOnceComplete.store( - reinterpret_cast(init_once_complete), std::memory_order_relaxed); - } - functions._Initialized.store(true, std::memory_order_release); - } - return functions; - } - - // XP fallback values must use the same values as in __crtInitOnceExecuteOnce from winapisupp.cpp - constexpr uintptr_t PV_INITIAL = 0; - constexpr uintptr_t PV_WORKING = 1; - constexpr uintptr_t PV_SUCCESS = 2; - - int _InitOnceBeginInitializeXpFallback(void** const flag, int& pending) { - enum { Spin, Yield, Sleep } wait_phase = Spin; - int spin_count = 10'000; - int sleep_value = 2; - - for (;;) { - const auto previous = reinterpret_cast( - __crt_interlocked_compare_exchange_pointer(flag, PV_WORKING, PV_INITIAL)); - - if (previous == PV_SUCCESS) { - pending = FALSE; - return TRUE; - } else if (previous == PV_INITIAL) { - pending = TRUE; - return TRUE; - } else if (previous == PV_WORKING) { - switch (wait_phase) { - case Spin: - if (spin_count != 0) { - spin_count--; - _YIELD_PROCESSOR(); - continue; - } - spin_count = 4; - wait_phase = Yield; - [[fallthrough]]; - - case Yield: - if (spin_count != 0) { - spin_count--; - ::SwitchToThread(); - continue; - } - wait_phase = Sleep; - [[fallthrough]]; - - case Sleep: - ::Sleep(sleep_value); - sleep_value = min(sleep_value + sleep_value / 2, 4000); - continue; - } - } else { - pending = FALSE; - ::SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - } - } - - int _InitOnceInitOnceCompleteXpFallback(void** const flag, bool suceeded) { - for (;;) { - const auto previous = reinterpret_cast( - __crt_interlocked_exchange_pointer(flag, suceeded ? PV_SUCCESS : PV_INITIAL)); - - if (previous == PV_WORKING) { - return TRUE; - } else { - SetLastError(ERROR_INVALID_DATA); - return FALSE; - } - } - } - -} // unnamed namespace - -_STD_BEGIN -int __CLRCALL_PURE_OR_CDECL _Execute_once_begin( - once_flag& _Once_flag, int& _Pending) noexcept { // wrap Win32 InitOnceBeginInitialize() - const auto init_once_begin_initialize = - _Get_init_once_vista_functions()._Pfn_InitOnceBeginInitialize.load(std::memory_order_relaxed); - if (init_once_begin_initialize == nullptr) { - return _InitOnceInitOnceCompleteXpFallback(&_Once_flag._Opaque, _Pending); - } - return init_once_begin_initialize(reinterpret_cast(&_Once_flag._Opaque), 0, &_Pending, nullptr); -} - -int __CLRCALL_PURE_OR_CDECL _Execute_once_complete( - once_flag& _Once_flag, const bool _Succeeded) noexcept { // wrap Win32 InitOnceComplete() - const auto init_once_complete = - _Get_init_once_vista_functions()._Pfn_InitOnceComplete.load(std::memory_order_relaxed); - if (init_once_complete == nullptr) { - return _InitOnceInitOnceCompleteXpFallback(&_Once_flag._Opaque, _Succeeded); - } - return init_once_complete( - reinterpret_cast(&_Once_flag._Opaque), _Succeeded ? 0 : INIT_ONCE_INIT_FAILED, nullptr); -} -_STD_END - -#endif // _STL_WIN32_WINNT >= _WIN32_WINNT_VISTA From 0cefdea9c4964536645ce46857b0c77fcbf1f9b6 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 4 May 2020 23:14:52 -0700 Subject: [PATCH 25/38] clang-format --- stl/inc/mutex | 2 +- stl/src/ppltasks.cpp | 28 ++++++++++++++++------------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 4a584b6607e..8d79ca8c55a 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -13,8 +13,8 @@ #error is not supported when compiling with /clr:pure. #endif // _M_CEE_PURE -#include #include +#include #include #include #include diff --git a/stl/src/ppltasks.cpp b/stl/src/ppltasks.cpp index 52a5aff5625..95a5a011dbe 100644 --- a/stl/src/ppltasks.cpp +++ b/stl/src/ppltasks.cpp @@ -115,18 +115,22 @@ namespace Concurrency { bool isCausalitySupported() { // TRANSITION, ABI - _Execute_once(m_stateFlag, [](void*, void* _This_raw, void**) -> int { - const auto _This = static_cast(_This_raw); - ComPtr causalityAPIs; - if (SUCCEEDED(GetActivationFactory( - HStringReference(RuntimeClass_Windows_Foundation_Diagnostics_AsyncCausalityTracer).Get(), - &causalityAPIs))) { - _This->m_causalityAPIs = causalityAPIs.Detach(); - _This->m_isSupported = true; - } - - return 1; - }, this); + _Execute_once( + m_stateFlag, + [](void*, void* _This_raw, void**) -> int { + const auto _This = static_cast(_This_raw); + ComPtr causalityAPIs; + if (SUCCEEDED(GetActivationFactory( + HStringReference(RuntimeClass_Windows_Foundation_Diagnostics_AsyncCausalityTracer) + .Get(), + &causalityAPIs))) { + _This->m_causalityAPIs = causalityAPIs.Detach(); + _This->m_isSupported = true; + } + + return 1; + }, + this); return m_isSupported; } } asyncCausalityTracer; From 0ac263153f6355c7719fb5734b822d89d56b0e72 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 5 May 2020 00:07:10 -0700 Subject: [PATCH 26/38] Fix static linking in the old build system. --- stl/msbuild/stl_base/stl.files.settings.targets | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stl/msbuild/stl_base/stl.files.settings.targets b/stl/msbuild/stl_base/stl.files.settings.targets index c4126d80a13..532c558b1b7 100644 --- a/stl/msbuild/stl_base/stl.files.settings.targets +++ b/stl/msbuild/stl_base/stl.files.settings.targets @@ -191,6 +191,11 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + + + + + From 09492d926910859ab4b186e70465ab457daa63e8 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 5 May 2020 21:36:57 -0700 Subject: [PATCH 27/38] Attempt to fix clr and the CMakeLists.txt. --- stl/CMakeLists.txt | 9 ++++--- stl/inc/mutex | 19 ++++++++++--- .../stl_base/stl.files.settings.targets | 1 + stl/src/xonce2.cpp | 27 +++++++++++++++++++ 4 files changed, 49 insertions(+), 7 deletions(-) create mode 100644 stl/src/xonce2.cpp diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index 5a521d55680..db3253babcf 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -244,6 +244,9 @@ set(IMPLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/sharedmutex.cpp ${CMAKE_CURRENT_LIST_DIR}/src/syserror_import_lib.cpp ${CMAKE_CURRENT_LIST_DIR}/src/vector_algorithms.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/xonce2.cpp +) +set (IMPLIB_SOURCE_OBJECTS ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_begin_initialize.obj ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_complete.obj ) @@ -448,7 +451,7 @@ function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIO target_link_libraries(msvcp_2${D_SUFFIX}_objects PRIVATE Boost::headers Boost::disable_autolinking) add_library(msvcp_2${D_SUFFIX} SHARED) - target_link_libraries(msvcp_2${D_SUFFIX} PRIVATE msvcp_2${D_SUFFIX}_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") + target_link_libraries(msvcp_2${D_SUFFIX} PRIVATE msvcp_2${D_SUFFIX}_objects msvcp${D_SUFFIX}_implib_objects ${IMPLIB_SOURCE_OBJECTS} "msvcp${D_SUFFIX}" "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_NAME "msvcp140_2${D_SUFFIX}${VCLIBS_SUFFIX}") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES OUTPUT_NAME "msvcp140_2${D_SUFFIX}${VCLIBS_SUFFIX}") @@ -468,7 +471,7 @@ function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIO # import library add_library(msvcp${D_SUFFIX}_implib STATIC ${HEADERS}) - target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects) + target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects ${IMPLIB_SOURCE_OBJECTS}) add_dependencies(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX} msvcp_1${D_SUFFIX} msvcp_2${D_SUFFIX} msvcp${D_SUFFIX}_codecvt_ids) set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES STATIC_LIBRARY_OPTIONS "/NOLOGO;/NODEFAULTLIB;/IGNORE:4006;$;$;$;$") set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES ARCHIVE_OUTPUT_NAME "msvcprt${D_SUFFIX}") @@ -485,7 +488,7 @@ function(add_stl_statics FLAVOR_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPI add_library(libcpmt${FLAVOR_SUFFIX} STATIC ${HEADERS} ${IMPLIB_SOURCES} ${SOURCES} ${STATIC_SOURCES}) target_compile_definitions(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_DEFINITIONS}") target_compile_options(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_COMPILE_OPTIONS};/EHsc") - target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha) + target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha ${IMPLIB_SOURCE_OBJECTS}) endfunction() add_stl_statics("" "_ITERATOR_DEBUG_LEVEL=0" "${VCLIBS_RELEASE_OPTIONS}") diff --git a/stl/inc/mutex b/stl/inc/mutex index 8d79ca8c55a..47a6ed70af6 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -509,6 +509,14 @@ public: #endif // _HAS_CXX17 // FUNCTION TEMPLATE call_once +#ifdef _M_CEE +#define _WINDOWS_API __stdcall +#define _RENAME_WINDOWS_API(_Api) _Api##_clr +#else // ^^^ _M_CEE // !_M_CEE vvv +#define _WINDOWS_API __declspec(dllimport) __stdcall +#define _RENAME_WINDOWS_API(_Api) _Api +#endif // _M_CEE + // WINBASEAPI // BOOL // WINAPI @@ -518,7 +526,7 @@ public: // _Out_ PBOOL fPending, // _Outptr_opt_result_maybenull_ LPVOID* lpContext // ); -extern "C" int __declspec(dllimport) __stdcall __std_init_once_begin_initialize( +extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize)( void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept; // WINBASEAPI // BOOL @@ -528,7 +536,7 @@ extern "C" int __declspec(dllimport) __stdcall __std_init_once_begin_initialize( // _In_ DWORD dwFlags, // _In_opt_ LPVOID lpContext // ); -extern "C" int __declspec(dllimport) __stdcall __std_init_once_complete( +extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_complete)( void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept; // #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL // #define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED @@ -537,7 +545,7 @@ struct _Init_once_completer { once_flag& _Once; unsigned long _DwFlags; ~_Init_once_completer() { - if (__std_init_once_complete(&_Once._Opaque, _DwFlags, nullptr) == 0) { + if (_RENAME_WINDOWS_API(__std_init_once_complete)(&_Once._Opaque, _DwFlags, nullptr) == 0) { _CSTD abort(); } } @@ -550,7 +558,7 @@ void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) noexcept( // call _Fx(_Ax...) once // parentheses against common "#define call_once(flag,func) pthread_once(flag,func)" int _Pending; - if (__std_init_once_begin_initialize(&_Once._Opaque, 0, &_Pending, nullptr) == 0) { + if (_RENAME_WINDOWS_API(__std_init_once_begin_initialize)(&_Once._Opaque, 0, &_Pending, nullptr) == 0) { _CSTD abort(); } @@ -561,6 +569,9 @@ void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) noexcept( } } +#undef _WINDOWS_API +#undef _RENAME_WINDOWS_API + // condition_variable, timed_mutex, and recursive_timed_mutex are not supported under /clr #ifndef _M_CEE enum class cv_status { // names for wait returns diff --git a/stl/msbuild/stl_base/stl.files.settings.targets b/stl/msbuild/stl_base/stl.files.settings.targets index 532c558b1b7..4c371170a5f 100644 --- a/stl/msbuild/stl_base/stl.files.settings.targets +++ b/stl/msbuild/stl_base/stl.files.settings.targets @@ -174,6 +174,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtRoot)\github\stl\src\sharedmutex.cpp; $(CrtRoot)\github\stl\src\syserror_import_lib.cpp; $(CrtRoot)\github\stl\src\vector_algorithms.cpp; + $(CrtRoot)\github\stl\src\xonce2.cpp; "> nativecpp false diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp new file mode 100644 index 00000000000..47621dab246 --- /dev/null +++ b/stl/src/xonce2.cpp @@ -0,0 +1,27 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include + +#include + +// This must be as small as possible, because its contents are +// injected into the msvcprt.lib and msvcprtd.lib import libraries. +// Do not include or define anything else here. +// In particular, basic_string must not be included here. + +// Provides forwarders for InitOnceBeginInitialize and InitOnceComplete for +// environments that can't use aliasobj, like /clr. + +_EXTERN_C + +int __stdcall __std_init_once_begin_initialize_clr( + void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept { + return InitOnceBeginInitialize(reinterpret_cast(_LpInitOnce), _DwFlags, _FPending, _LpContext); +} + +int __stdcall __std_init_once_complete_clr(void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept { + return InitOnceComplete(reinterpret_cast(_LpInitOnce), _DwFlags, _LpContext); +} + +_END_EXTERN_C From 9b35e10205b40316c4470f9904927e123cad05df Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Tue, 5 May 2020 21:53:58 -0700 Subject: [PATCH 28/38] Use "s for awint.h. --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 47621dab246..5c703c922cd 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -3,7 +3,7 @@ #include -#include +#include "awint.h" // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. From 4834dbff607d6ec0dca5fc30810778780f7cd2e4 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 09:56:14 +0300 Subject: [PATCH 29/38] Update stl/inc/mutex Co-authored-by: Stephan T. Lavavej --- stl/inc/mutex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 47a6ed70af6..9b40f357f52 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -562,7 +562,7 @@ void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) noexcept( _CSTD abort(); } - if (_Pending) { + if (_Pending != 0) { _Init_once_completer _Op{_Once, _Init_once_init_failed}; _STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); _Op._DwFlags = 0; From f708bb4f59ba2d19c02281cab232cbafa9cd1291 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 09:56:46 +0300 Subject: [PATCH 30/38] Update stl/inc/mutex Co-authored-by: Stephan T. Lavavej --- stl/inc/mutex | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 9b40f357f52..46df7b9c483 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -553,8 +553,7 @@ struct _Init_once_completer { template void(call_once)(once_flag& _Once, _Fn&& _Fx, _Args&&... _Ax) noexcept( - noexcept(_STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...))) // Strengthened -{ + noexcept(_STD invoke(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...))) /* strengthened */ { // call _Fx(_Ax...) once // parentheses against common "#define call_once(flag,func) pthread_once(flag,func)" int _Pending; From da1ab546fbf22e84d4e648056461615902a64c79 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 17:37:39 +0300 Subject: [PATCH 31/38] Update stl/inc/mutex Co-authored-by: Casey Carter --- stl/inc/mutex | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/mutex b/stl/inc/mutex index 46df7b9c483..3be7e3cc250 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -541,6 +541,7 @@ extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_complete)( // #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL // #define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED _INLINE_VAR constexpr unsigned long _Init_once_init_failed = 0x4UL; + struct _Init_once_completer { once_flag& _Once; unsigned long _DwFlags; From c11d81ad7c5d3621080eeb83a7f28e5e1c008147 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 17:42:07 +0300 Subject: [PATCH 32/38] Update stl/inc/mutex Co-authored-by: Casey Carter --- stl/inc/mutex | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/mutex b/stl/inc/mutex index 3be7e3cc250..501d8530844 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -538,6 +538,7 @@ extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize // ); extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_complete)( void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept; + // #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL // #define INIT_ONCE_INIT_FAILED RTL_RUN_ONCE_INIT_FAILED _INLINE_VAR constexpr unsigned long _Init_once_init_failed = 0x4UL; From 0f792a09f2b3b51ded3a29e119d85ae83d809da7 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 17:42:34 +0300 Subject: [PATCH 33/38] Update stl/inc/mutex Co-authored-by: Casey Carter --- stl/inc/mutex | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/mutex b/stl/inc/mutex index 501d8530844..1b356f918fe 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -528,6 +528,7 @@ public: // ); extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize)( void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept; + // WINBASEAPI // BOOL // WINAPI From e655060a9db25085abac7e768da4ac57c3f858a5 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 6 May 2020 09:32:30 -0700 Subject: [PATCH 34/38] Build tweak: IMPLIB_SOURCE_OBJECTS are sourdces, not libraries This should fix the test failrues due to missing symbols for `/MT` and /MTd` compiles. --- stl/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index db3253babcf..d1aba5c679d 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -470,8 +470,8 @@ function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIO target_link_options(msvcp${D_SUFFIX}_codecvt_ids PRIVATE "${THIS_CONFIG_LINK_OPTIONS}") # import library - add_library(msvcp${D_SUFFIX}_implib STATIC ${HEADERS}) - target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects ${IMPLIB_SOURCE_OBJECTS}) + add_library(msvcp${D_SUFFIX}_implib STATIC ${HEADERS} ${IMPLIB_SOURCE_OBJECTS}) + target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects) add_dependencies(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX} msvcp_1${D_SUFFIX} msvcp_2${D_SUFFIX} msvcp${D_SUFFIX}_codecvt_ids) set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES STATIC_LIBRARY_OPTIONS "/NOLOGO;/NODEFAULTLIB;/IGNORE:4006;$;$;$;$") set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES ARCHIVE_OUTPUT_NAME "msvcprt${D_SUFFIX}") @@ -485,10 +485,10 @@ function(add_stl_statics FLAVOR_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPI target_compile_definitions(libcpmt${FLAVOR_SUFFIX}_eha PRIVATE "${THIS_CONFIG_DEFINITIONS}") target_compile_options(libcpmt${FLAVOR_SUFFIX}_eha PRIVATE "${THIS_CONFIG_COMPILE_OPTIONS};/EHa") - add_library(libcpmt${FLAVOR_SUFFIX} STATIC ${HEADERS} ${IMPLIB_SOURCES} ${SOURCES} ${STATIC_SOURCES}) + add_library(libcpmt${FLAVOR_SUFFIX} STATIC ${HEADERS} ${IMPLIB_SOURCES} ${SOURCES} ${STATIC_SOURCES} ${IMPLIB_SOURCE_OBJECTS}) target_compile_definitions(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_DEFINITIONS}") target_compile_options(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_COMPILE_OPTIONS};/EHsc") - target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha ${IMPLIB_SOURCE_OBJECTS}) + target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha) endfunction() add_stl_statics("" "_ITERATOR_DEBUG_LEVEL=0" "${VCLIBS_RELEASE_OPTIONS}") From 3b504fd97ad539234513283b2901a6cfe0448184 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 20:36:53 +0300 Subject: [PATCH 35/38] _NODISCARD --- stl/inc/mutex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 1b356f918fe..ae6cd9d1ed8 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -526,7 +526,7 @@ public: // _Out_ PBOOL fPending, // _Outptr_opt_result_maybenull_ LPVOID* lpContext // ); -extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize)( +extern "C" _NODISCARD int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize)( void** _LpInitOnce, unsigned long _DwFlags, int* _FPending, void** _LpContext) noexcept; // WINBASEAPI @@ -537,7 +537,7 @@ extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_begin_initialize // _In_ DWORD dwFlags, // _In_opt_ LPVOID lpContext // ); -extern "C" int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_complete)( +extern "C" _NODISCARD int _WINDOWS_API _RENAME_WINDOWS_API(__std_init_once_complete)( void** _LpInitOnce, unsigned long _DwFlags, void* _LpContext) noexcept; // #define RTL_RUN_ONCE_INIT_FAILED 0x00000004UL From c1da0c85fac2b909efe935d26bc5fca8795dbf53 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 21:28:14 +0300 Subject: [PATCH 36/38] is enough --- stl/src/xonce2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/xonce2.cpp b/stl/src/xonce2.cpp index 5c703c922cd..77013f2316e 100644 --- a/stl/src/xonce2.cpp +++ b/stl/src/xonce2.cpp @@ -3,7 +3,7 @@ #include -#include "awint.h" +#include // This must be as small as possible, because its contents are // injected into the msvcprt.lib and msvcprtd.lib import libraries. From bbe2f67bea33f427fb3241b57dd223b394e7e397 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 6 May 2020 22:37:17 +0300 Subject: [PATCH 37/38] @cbezault 's patch --- stl/CMakeLists.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index d1aba5c679d..dfb026bd299 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -246,10 +246,6 @@ set(IMPLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/vector_algorithms.cpp ${CMAKE_CURRENT_LIST_DIR}/src/xonce2.cpp ) -set (IMPLIB_SOURCE_OBJECTS - ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_begin_initialize.obj - ${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_complete.obj -) # The following files are linked in msvcp140[d][_clr].dll. set (DLL_SOURCES @@ -402,13 +398,18 @@ set(STATIC_SOURCES ${SOURCES_SATELLITE_CODECVT_IDS} ) +add_library(std_init_once_begin_initialize OBJECT IMPORTED) +add_library(std_init_once_complete OBJECT IMPORTED) +set_target_properties(std_init_once_begin_initialize PROPERTIES IMPORTED_OBJECTS "${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_begin_initialize.obj") +set_target_properties(std_init_once_complete PROPERTIES IMPORTED_OBJECTS "${CMAKE_CURRENT_LIST_DIR}/aliases/${VCLIBS_I386_OR_AMD64}/std_init_once_complete.obj") + add_compile_definitions(_CRTBLD _VCRT_ALLOW_INTERNALS _HAS_OLD_IOSTREAMS_MEMBERS=1 _STL_CONCRT_SUPPORT) include_directories(BEFORE "${CMAKE_CURRENT_LIST_DIR}/inc" "${TOOLSET_ROOT_DIR}/crt/src/concrt" "${TOOLSET_ROOT_DIR}/crt/src/vcruntime" - ) +) function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIONS GL_FLAG THIS_CONFIG_LINK_OPTIONS) # msvcp140.dll @@ -451,7 +452,7 @@ function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIO target_link_libraries(msvcp_2${D_SUFFIX}_objects PRIVATE Boost::headers Boost::disable_autolinking) add_library(msvcp_2${D_SUFFIX} SHARED) - target_link_libraries(msvcp_2${D_SUFFIX} PRIVATE msvcp_2${D_SUFFIX}_objects msvcp${D_SUFFIX}_implib_objects ${IMPLIB_SOURCE_OBJECTS} "msvcp${D_SUFFIX}" "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib") + target_link_libraries(msvcp_2${D_SUFFIX} PRIVATE msvcp_2${D_SUFFIX}_objects msvcp${D_SUFFIX}_implib_objects std_init_once_begin_initialize std_init_once_complete "msvcp${D_SUFFIX}" "${TOOLSET_LIB}/vcruntime${D_SUFFIX}.lib" "${TOOLSET_LIB}/msvcrt${D_SUFFIX}.lib" "ucrt${D_SUFFIX}.lib") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_NAME "msvcp140_2${D_SUFFIX}${VCLIBS_SUFFIX}") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") set_target_properties(msvcp_2${D_SUFFIX} PROPERTIES OUTPUT_NAME "msvcp140_2${D_SUFFIX}${VCLIBS_SUFFIX}") @@ -470,8 +471,8 @@ function(add_stl_dlls D_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPILE_OPTIO target_link_options(msvcp${D_SUFFIX}_codecvt_ids PRIVATE "${THIS_CONFIG_LINK_OPTIONS}") # import library - add_library(msvcp${D_SUFFIX}_implib STATIC ${HEADERS} ${IMPLIB_SOURCE_OBJECTS}) - target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects) + add_library(msvcp${D_SUFFIX}_implib STATIC ${HEADERS}) + target_link_libraries(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX}_implib_objects std_init_once_begin_initialize std_init_once_complete) add_dependencies(msvcp${D_SUFFIX}_implib msvcp${D_SUFFIX} msvcp_1${D_SUFFIX} msvcp_2${D_SUFFIX} msvcp${D_SUFFIX}_codecvt_ids) set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES STATIC_LIBRARY_OPTIONS "/NOLOGO;/NODEFAULTLIB;/IGNORE:4006;$;$;$;$") set_target_properties(msvcp${D_SUFFIX}_implib PROPERTIES ARCHIVE_OUTPUT_NAME "msvcprt${D_SUFFIX}") @@ -485,10 +486,10 @@ function(add_stl_statics FLAVOR_SUFFIX THIS_CONFIG_DEFINITIONS THIS_CONFIG_COMPI target_compile_definitions(libcpmt${FLAVOR_SUFFIX}_eha PRIVATE "${THIS_CONFIG_DEFINITIONS}") target_compile_options(libcpmt${FLAVOR_SUFFIX}_eha PRIVATE "${THIS_CONFIG_COMPILE_OPTIONS};/EHa") - add_library(libcpmt${FLAVOR_SUFFIX} STATIC ${HEADERS} ${IMPLIB_SOURCES} ${SOURCES} ${STATIC_SOURCES} ${IMPLIB_SOURCE_OBJECTS}) + add_library(libcpmt${FLAVOR_SUFFIX} STATIC ${HEADERS} ${IMPLIB_SOURCES} ${SOURCES} ${STATIC_SOURCES}) target_compile_definitions(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_DEFINITIONS}") target_compile_options(libcpmt${FLAVOR_SUFFIX} PRIVATE "${THIS_CONFIG_COMPILE_OPTIONS};/EHsc") - target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha) + target_link_libraries(libcpmt${FLAVOR_SUFFIX} PRIVATE Boost::headers Boost::disable_autolinking libcpmt${FLAVOR_SUFFIX}_eha std_init_once_begin_initialize std_init_once_complete) endfunction() add_stl_statics("" "_ITERATOR_DEBUG_LEVEL=0" "${VCLIBS_RELEASE_OPTIONS}") From ce14a583b603b457ea7638801279ff280d7185dd Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Sun, 10 May 2020 22:04:53 -0700 Subject: [PATCH 38/38] Add CHPE objects. --- .../chpe/std_init_once_begin_initialize.obj | Bin 0 -> 231 bytes stl/aliases/chpe/std_init_once_complete.obj | Bin 0 -> 216 bytes stl/aliases/generate.cmd | 10 ++++++++++ 3 files changed, 10 insertions(+) create mode 100644 stl/aliases/chpe/std_init_once_begin_initialize.obj create mode 100644 stl/aliases/chpe/std_init_once_complete.obj diff --git a/stl/aliases/chpe/std_init_once_begin_initialize.obj b/stl/aliases/chpe/std_init_once_begin_initialize.obj new file mode 100644 index 0000000000000000000000000000000000000000..b82e69585246dbce0595a9c58f7fc2a4ae7b2144 GIT binary patch literal 231 zcmZQzU}TW@+Z1QRz`(!?#2}!TQk0rpQkDwg;UKvf7#x!Ga|`q`Qw(GNGW`F~z`)Gl zkd~TQqGwS@tL^=@yecgnI-;t$*E4M p>6v*TPG(|GW>u<#p&3j?e0*_9N_-|zDn1{mFg^*S63j;^1ps>^EkytT literal 0 HcmV?d00001 diff --git a/stl/aliases/chpe/std_init_once_complete.obj b/stl/aliases/chpe/std_init_once_complete.obj new file mode 100644 index 0000000000000000000000000000000000000000..82b42bedef01f066ad224f2962a212da2272eefc GIT binary patch literal 216 zcmZQzU}TW@+Z1QRz`(!?#2}!TQk0rpQkDwg;UKvf7#x!Ga|`q`Qw(GNGW`F~z`)Gl zkd~TQqGw