Skip to content

Commit

Permalink
[XRay][compiler-rt] Remove uses of internal allocator in profiling mode
Browse files Browse the repository at this point in the history
Summary:
This change removes further cases where the profiling mode
implementation relied on dynamic memory allocation. We're using
thread-local aligned (uninitialized) memory instead, which we initialize
appropriately with placement new.

Addresses llvm.org/PR38577.

Reviewers: eizan, kpw

Subscribers: jfb, llvm-commits

Differential Revision: https://reviews.llvm.org/D51278

llvm-svn: 340814
  • Loading branch information
deanberris committed Aug 28, 2018
1 parent af98587 commit 6b1e125
Showing 1 changed file with 30 additions and 24 deletions.
54 changes: 30 additions & 24 deletions compiler-rt/lib/xray/xray_profiling.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,51 +40,56 @@ atomic_sint32_t ProfilerLogStatus = {XRayLogInitStatus::XRAY_LOG_UNINITIALIZED};
SpinMutex ProfilerOptionsMutex;

struct alignas(64) ProfilingData {
FunctionCallTrie::Allocators *Allocators = nullptr;
FunctionCallTrie *FCT = nullptr;
FunctionCallTrie::Allocators *Allocators;
FunctionCallTrie *FCT;
};

static pthread_key_t ProfilingKey;

thread_local std::aligned_storage<sizeof(FunctionCallTrie::Allocators)>::type
AllocatorsStorage;
thread_local std::aligned_storage<sizeof(FunctionCallTrie)>::type
FunctionCallTrieStorage;
thread_local std::aligned_storage<sizeof(ProfilingData)>::type ThreadStorage{};

static ProfilingData &getThreadLocalData() XRAY_NEVER_INSTRUMENT {
thread_local auto ThreadOnce = [] {
new (&ThreadStorage) ProfilingData{};
auto *Allocators =
reinterpret_cast<FunctionCallTrie::Allocators *>(&AllocatorsStorage);
new (Allocators) FunctionCallTrie::Allocators();
*Allocators = FunctionCallTrie::InitAllocators();
auto *FCT = reinterpret_cast<FunctionCallTrie *>(&FunctionCallTrieStorage);
new (FCT) FunctionCallTrie(*Allocators);
auto &TLD = *reinterpret_cast<ProfilingData *>(&ThreadStorage);
TLD.Allocators = Allocators;
TLD.FCT = FCT;
pthread_setspecific(ProfilingKey, &ThreadStorage);
return false;
}();
(void)ThreadOnce;

auto &TLD = *reinterpret_cast<ProfilingData *>(&ThreadStorage);

// We need to check whether the global flag to finalizing/finalized has been
// switched. If it is, then we ought to not actually initialise the data.
auto Status = atomic_load(&ProfilerLogStatus, memory_order_acquire);
if (Status == XRayLogInitStatus::XRAY_LOG_FINALIZING ||
Status == XRayLogInitStatus::XRAY_LOG_FINALIZED)
return TLD;

// If we're live, then we re-initialize TLD if the pointers are not null.
if (UNLIKELY(TLD.Allocators == nullptr && TLD.FCT == nullptr)) {
TLD.Allocators = reinterpret_cast<FunctionCallTrie::Allocators *>(
InternalAlloc(sizeof(FunctionCallTrie::Allocators)));
new (TLD.Allocators) FunctionCallTrie::Allocators();
*TLD.Allocators = FunctionCallTrie::InitAllocators();
TLD.FCT = reinterpret_cast<FunctionCallTrie *>(
InternalAlloc(sizeof(FunctionCallTrie)));
new (TLD.FCT) FunctionCallTrie(*TLD.Allocators);
auto &TLD = *reinterpret_cast<ProfilingData*>(&ThreadStorage);

if (UNLIKELY(TLD.Allocators == nullptr || TLD.FCT == nullptr)) {
auto *Allocators =
reinterpret_cast<FunctionCallTrie::Allocators *>(&AllocatorsStorage);
new (Allocators) FunctionCallTrie::Allocators();
*Allocators = FunctionCallTrie::InitAllocators();
auto *FCT = reinterpret_cast<FunctionCallTrie *>(&FunctionCallTrieStorage);
new (FCT) FunctionCallTrie(*Allocators);
TLD.Allocators = Allocators;
TLD.FCT = FCT;
}

return TLD;
return *reinterpret_cast<ProfilingData *>(&ThreadStorage);
}

static void cleanupTLD() XRAY_NEVER_INSTRUMENT {
auto &TLD = *reinterpret_cast<ProfilingData *>(&ThreadStorage);
if (TLD.Allocators != nullptr && TLD.FCT != nullptr) {
TLD.FCT->~FunctionCallTrie();
TLD.Allocators->~Allocators();
InternalFree(TLD.FCT);
InternalFree(TLD.Allocators);
TLD.FCT = nullptr;
TLD.Allocators = nullptr;
}
Expand Down Expand Up @@ -181,13 +186,14 @@ void profilingHandleArg0(int32_t FuncId,
return;

auto Status = atomic_load(&ProfilerLogStatus, memory_order_acquire);
auto &TLD = getThreadLocalData();
if (UNLIKELY(Status == XRayLogInitStatus::XRAY_LOG_FINALIZED ||
Status == XRayLogInitStatus::XRAY_LOG_FINALIZING)) {
auto &TLD = getThreadLocalData();
postCurrentThreadFCT(TLD);
return;
}

auto &TLD = getThreadLocalData();
switch (Entry) {
case XRayEntryType::ENTRY:
case XRayEntryType::LOG_ARGS_ENTRY:
Expand Down

0 comments on commit 6b1e125

Please sign in to comment.