Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup _Execute_once() #4087

Merged
merged 13 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions stl/inc/xcall_once.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,6 @@ _EXPORT_STD struct once_flag { // opaque data structure for call_once()
void* _Opaque;
};

#ifdef _CRTBLD
// Returns BOOL, nonzero to indicate success, zero for failure
using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**);

// Returns BOOL, nonzero to indicate success, zero for failure
extern "C++" _CRTIMP2_PURE int __CLRCALL_PURE_OR_CDECL _Execute_once(
once_flag& _Flag, _Execute_once_fp_t _Callback, void* _Pv) noexcept;
#endif // _CRTBLD

template <class _Ty>
union _Immortalizer_impl { // constructs _Ty, never destroys
constexpr _Immortalizer_impl() noexcept : _Storage{} {}
Expand Down
14 changes: 1 addition & 13 deletions stl/src/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,6 @@

#include <Windows.h>

#ifdef _CRT_APP
// free static resource used by causality
extern "C" void __cdecl __crtCleanupCausalityStaticFactories();
#endif // defined(_CRT_APP)

extern "C" BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, [[maybe_unused]] LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_DETACH) {
#ifdef _CRT_APP
if (lpReserved == nullptr) { // only when the process is not terminating
__crtCleanupCausalityStaticFactories();
}
#endif // defined(_CRT_APP)
}
extern "C" BOOL APIENTRY DllMain(HMODULE, DWORD, LPVOID) noexcept {
return TRUE;
}
13 changes: 1 addition & 12 deletions stl/src/excptptr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,11 @@ namespace {
return _Immortalize_impl<_Ty>._Storage;
}
#else // ^^^ !defined(_M_CEE) / defined(_M_CEE), TRANSITION, VSO-1153256 vvv
template <class _Ty>
int __stdcall _Immortalize_impl(void*, void* _Storage_ptr, void**) noexcept {
// adapt True Placement New to _Execute_once
::new (_Storage_ptr) _Ty();
return 1;
}

template <class _Ty>
_Ty& _Immortalize() { // return a reference to an object that will live forever
static once_flag _Flag;
alignas(_Ty) static unsigned char _Storage[sizeof(_Ty)];
if (!_Execute_once(_Flag, _Immortalize_impl<_Ty>, &_Storage)) {
// _Execute_once should never fail if the callback never fails
_CSTD abort();
}

call_once(_Flag, [&_Storage] { ::new (static_cast<void*>(&_Storage)) _Ty(); });
return reinterpret_cast<_Ty&>(_Storage);
}
#endif // ^^^ !defined(_M_CEE_PURE) && defined(_M_CEE), TRANSITION, VSO-1153256 ^^^
Expand Down
131 changes: 0 additions & 131 deletions stl/src/ppltasks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,130 +81,6 @@ namespace Concurrency {

} // namespace platform

#if defined(_CRT_APP)
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Diagnostics;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

class AsyncCausalityTracer {
IAsyncCausalityTracerStatics* m_causalityAPIs;
std::once_flag m_stateFlag;
bool m_isSupported;

public:
IAsyncCausalityTracerStatics* get() const {
return m_causalityAPIs;
}

AsyncCausalityTracer() : m_causalityAPIs(nullptr), m_isSupported(false) {}

void release() {
if (m_causalityAPIs) {
APTTYPE aptType;
APTTYPEQUALIFIER aptTypeQualifier;
if (CoGetApartmentType(&aptType, &aptTypeQualifier) == S_OK) {
// Release causality APIs only if current apartment is still RoInitialized
m_causalityAPIs->Release();
m_causalityAPIs = nullptr;
m_isSupported = false;
}
}
}

bool isCausalitySupported() {
// TRANSITION, ABI
_Execute_once(
m_stateFlag,
[](void*, void* _This_raw, void**) -> int {
const auto _This = static_cast<AsyncCausalityTracer*>(_This_raw);
ComPtr<IAsyncCausalityTracerStatics> 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 asyncCausalityTracer;

// GUID used for identifying causality logs from PPLTask
const GUID PPLTaskCausalityPlatformID = {
0x7A76B220, 0xA758, 0x4E6E, 0xB0, 0xE0, 0xD7, 0xC6, 0xD7, 0x4A, 0x88, 0xFE};

_CRTIMP2 void __thiscall _TaskEventLogger::_LogScheduleTask(bool _IsContinuation) {
if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceOperationCreation(CausalityTraceLevel_Required,
CausalitySource_Library, PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
HStringReference(_IsContinuation ? L"Concurrency::PPLTask::ScheduleContinuationTask"
: L"Concurrency::PPLTask::ScheduleTask")
.Get(),
0);
_M_scheduled = true;
}
}
_CRTIMP2 void __thiscall _TaskEventLogger::_LogTaskCompleted() {
if (_M_scheduled) {
AsyncStatus status;
if (_M_task->_IsCompleted()) {
status = AsyncStatus::Completed;
} else if (_M_task->_HasUserException()) {
status = AsyncStatus::Error;
} else {
status = AsyncStatus::Canceled;
}

if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceOperationCompletion(CausalityTraceLevel_Required,
CausalitySource_Library, PPLTaskCausalityPlatformID,
reinterpret_cast<unsigned long long>(_M_task), status);
}
}
}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogCancelTask() {
if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceOperationRelation(CausalityTraceLevel_Important,
CausalitySource_Library, PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
CausalityRelation_Cancel);
}
}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogTaskExecutionCompleted() {
if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceSynchronousWorkCompletion(CausalityTraceLevel_Required,
CausalitySource_Library, CausalitySynchronousWork_CompletionNotification);
}
}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemStarted() {
if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceSynchronousWorkStart(CausalityTraceLevel_Required,
CausalitySource_Library, PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
CausalitySynchronousWork_Execution);
}
}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemCompleted() {
if (asyncCausalityTracer.isCausalitySupported()) {
asyncCausalityTracer.get()->TraceSynchronousWorkCompletion(
CausalityTraceLevel_Required, CausalitySource_Library, CausalitySynchronousWork_Execution);

asyncCausalityTracer.get()->TraceSynchronousWorkStart(CausalityTraceLevel_Required,
CausalitySource_Library, PPLTaskCausalityPlatformID, reinterpret_cast<unsigned long long>(_M_task),
CausalitySynchronousWork_CompletionNotification);
_M_taskPostEventStarted = true;
}
}

#else // ^^^ defined(_CRT_APP) / !defined(_CRT_APP) vvv
_CRTIMP2 void __thiscall _TaskEventLogger::_LogScheduleTask(bool) {}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogTaskCompleted() {}
Expand All @@ -216,7 +92,6 @@ namespace Concurrency {
_CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemStarted() {}

_CRTIMP2 void __thiscall _TaskEventLogger::_LogWorkItemCompleted() {}
#endif // ^^^ !defined(_CRT_APP) ^^^

#if defined(_CRT_APP) || defined(UNDOCKED_WINDOWS_UCRT)
using namespace ABI::Windows::Foundation;
Expand Down Expand Up @@ -348,9 +223,3 @@ namespace Concurrency {
#endif // ^^^ !defined(_CRT_APP) ^^^

} // namespace Concurrency

#ifdef _CRT_APP
extern "C" void __cdecl __crtCleanupCausalityStaticFactories() {
Concurrency::details::asyncCausalityTracer.release();
}
#endif
26 changes: 4 additions & 22 deletions stl/src/xonce.cpp
Original file line number Diff line number Diff line change
@@ -1,39 +1,21 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

// _Execute_once function

#include <mutex>

#include <Windows.h>

namespace {
struct _Xfg_trampoline_parameter {
void* _Pv;
_STD _Execute_once_fp_t _Callback;
};
} // unnamed namespace

_STD_BEGIN
// Returns BOOL, nonzero to indicate success, zero for failure
using _Execute_once_fp_t = int(__stdcall*)(void*, void*, void**);

// TRANSITION, ABI
// TRANSITION, ABI: _Execute_once() is preserved for binary compatibility
_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");

// _Execute_once_fp_t and PINIT_ONCE_FN differ in type signature, therefore
// we introduce _Xfg_trampoline which has PINIT_ONCE_FN's type signature and
// calls into _Callback as an _Execute_once_fp_t for XFG compatibility.

_Xfg_trampoline_parameter _Trampoline_parameter = {_Pv, _Callback};

PINIT_ONCE_FN _Xfg_trampoline = [](PINIT_ONCE _InitOnce, PVOID _Parameter, PVOID* _Context) {
const auto _Trampoline_parameter = static_cast<_Xfg_trampoline_parameter*>(_Parameter);
return static_cast<BOOL>(_Trampoline_parameter->_Callback(_InitOnce, _Trampoline_parameter->_Pv, _Context));
};

return InitOnceExecuteOnce(
reinterpret_cast<PINIT_ONCE>(&_Flag._Opaque), _Xfg_trampoline, &_Trampoline_parameter, nullptr);
reinterpret_cast<PINIT_ONCE>(&_Flag._Opaque), reinterpret_cast<PINIT_ONCE_FN>(_Callback), _Pv, nullptr);
}

[[noreturn]] _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL
Expand Down