llvm/compiler-rt/lib/xray/xray_profiling.cpp

//===-- xray_profiling.cpp --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of XRay, a dynamic runtime instrumentation system.
//
// This is the implementation of a profiling handler.
//
//===----------------------------------------------------------------------===//
#include <memory>
#include <time.h>

#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "xray/xray_interface.h"
#include "xray/xray_log_interface.h"
#include "xray_buffer_queue.h"
#include "xray_flags.h"
#include "xray_profile_collector.h"
#include "xray_profiling_flags.h"
#include "xray_recursion_guard.h"
#include "xray_tsc.h"
#include "xray_utils.h"
#include <pthread.h>

namespace __xray {

namespace {

static atomic_sint32_t ProfilerLogFlushStatus =;

static atomic_sint32_t ProfilerLogStatus =;

static SpinMutex ProfilerOptionsMutex;

struct ProfilingData {};

static pthread_key_t ProfilingKey;

// We use a global buffer queue, which gets initialized once at initialisation
// time, and gets reset when profiling is "done".
alignas(BufferQueue) static std::byte BufferQueueStorage[sizeof(BufferQueue)];
static BufferQueue *BQ =;

thread_local FunctionCallTrie::Allocators::Buffers ThreadBuffers;
alignas(FunctionCallTrie::Allocators) thread_local std::byte
    AllocatorsStorage[sizeof(FunctionCallTrie::Allocators)];
alignas(FunctionCallTrie) thread_local std::byte
    FunctionCallTrieStorage[sizeof(FunctionCallTrie)];
thread_local ProfilingData TLD{};
thread_local atomic_uint8_t ReentranceGuard{};

// We use a separate guard for ensuring that for this thread, if we're already
// cleaning up, that any signal handlers don't attempt to cleanup nor
// initialise.
thread_local atomic_uint8_t TLDInitGuard{};

// We also use a separate latch to signal that the thread is exiting, and
// non-essential work should be ignored (things like recording events, etc.).
thread_local atomic_uint8_t ThreadExitingLatch{};

static ProfilingData *getThreadLocalData() XRAY_NEVER_INSTRUMENT {}

static void cleanupTLD() XRAY_NEVER_INSTRUMENT {}

static void postCurrentThreadFCT(ProfilingData &T) XRAY_NEVER_INSTRUMENT {}

} // namespace

const char *profilingCompilerDefinedFlags() XRAY_NEVER_INSTRUMENT {}

XRayLogFlushStatus profilingFlush() XRAY_NEVER_INSTRUMENT {}

void profilingHandleArg0(int32_t FuncId,
                         XRayEntryType Entry) XRAY_NEVER_INSTRUMENT {}

void profilingHandleArg1(int32_t FuncId, XRayEntryType Entry,
                         uint64_t) XRAY_NEVER_INSTRUMENT {}

XRayLogInitStatus profilingFinalize() XRAY_NEVER_INSTRUMENT {}

XRayLogInitStatus
profilingLoggingInit(size_t, size_t, void *Options,
                     size_t OptionsSize) XRAY_NEVER_INSTRUMENT {}

bool profilingDynamicInitializer() XRAY_NEVER_INSTRUMENT {}

} // namespace __xray

static auto UNUSED Unused =;