Skip to content

Commit

Permalink
Cleanup _Execute_once() (#4087)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanTLavavej authored Oct 25, 2023
1 parent adea8d5 commit 2e9c8a8
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 187 deletions.
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

0 comments on commit 2e9c8a8

Please sign in to comment.