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

//===-- xray_profile_collector.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 implements the interface for the profileCollectorService.
//
//===----------------------------------------------------------------------===//
#include "xray_profile_collector.h"
#include "sanitizer_common/sanitizer_common.h"
#include "xray_allocator.h"
#include "xray_defs.h"
#include "xray_profiling_flags.h"
#include "xray_segmented_array.h"
#include <memory>
#include <pthread.h>
#include <utility>

namespace __xray {
namespace profileCollectorService {

namespace {

SpinMutex GlobalMutex;
struct ThreadTrie {};

struct ProfileBuffer {};

// Current version of the profile format.
constexpr u64 XRayProfilingVersion =;

// Identifier for XRay profiling files 'xrayprof' in hex.
constexpr u64 XRayMagicBytes =;

struct XRayProfilingFileHeader {};

struct BlockHeader {};

struct ThreadData {};

ThreadDataArray;
ThreadDataAllocator;

// We use a separate buffer queue for the backing store for the allocator used
// by the ThreadData array. This lets us host the buffers, allocators, and tries
// associated with a thread by moving the data into the array instead of
// attempting to copy the data to a separately backed set of tries.
alignas(BufferQueue) static std::byte BufferQueueStorage[sizeof(BufferQueue)];
static BufferQueue *BQ =;
static BufferQueue::Buffer Buffer;
alignas(ThreadDataAllocator) static std::byte
    ThreadDataAllocatorStorage[sizeof(ThreadDataAllocator)];
alignas(ThreadDataArray) static std::byte
    ThreadDataArrayStorage[sizeof(ThreadDataArray)];

static ThreadDataAllocator *TDAllocator =;
static ThreadDataArray *TDArray =;

ProfileBufferArray;
ProfileBufferArrayAllocator;

// These need to be global aligned storage to avoid dynamic initialization. We
// need these to be aligned to allow us to placement new objects into the
// storage, and have pointers to those objects be appropriately aligned.
alignas(ProfileBufferArray) static std::byte
    ProfileBuffersStorage[sizeof(ProfileBufferArray)];
alignas(ProfileBufferArrayAllocator) static std::byte
    ProfileBufferArrayAllocatorStorage[sizeof(ProfileBufferArrayAllocator)];

static ProfileBufferArrayAllocator *ProfileBuffersAllocator =;
static ProfileBufferArray *ProfileBuffers =;

// Use a global flag to determine whether the collector implementation has been
// initialized.
static atomic_uint8_t CollectorInitialized{};

} // namespace

void post(BufferQueue *Q, FunctionCallTrie &&T,
          FunctionCallTrie::Allocators &&A,
          FunctionCallTrie::Allocators::Buffers &&B,
          tid_t TId) XRAY_NEVER_INSTRUMENT {}

// A PathArray represents the function id's representing a stack trace. In this
// context a path is almost always represented from the leaf function in a call
// stack to a root of the call trie.
PathArray;

struct ProfileRecord {};

namespace {

ProfileRecordArray;

// Walk a depth-first traversal of each root of the FunctionCallTrie to generate
// the path(s) and the data associated with the path.
static void
populateRecords(ProfileRecordArray &PRs, ProfileRecord::PathAllocator &PA,
                const FunctionCallTrie &Trie) XRAY_NEVER_INSTRUMENT {}

static void serializeRecords(ProfileBuffer *Buffer, const BlockHeader &Header,
                             const ProfileRecordArray &ProfileRecords)
    XRAY_NEVER_INSTRUMENT {}

} // namespace

void serialize() XRAY_NEVER_INSTRUMENT {}

void reset() XRAY_NEVER_INSTRUMENT {}

XRayBuffer nextBuffer(XRayBuffer B) XRAY_NEVER_INSTRUMENT {}

} // namespace profileCollectorService
} // namespace __xray