mirror of
https://github.com/wolfpld/tracy.git
synced 2024-11-26 16:04:34 +00:00
72ad40698b
Initializing structures for callstack processing (building memory map of the process, gathering kernel symbols, etc) takes some time, which in some cases may be significant. Callstack queries are now handled on a separate thread. In such setup it no longer makes sense to block main thread execution with this lengthy init process. All the heavy initialization phase has been now moved to this separate processing thread. Some initial callstack queries may now not produce responses as promptly as before, but this is only because the main thread is able to start working earlier. Some parts of the initialization process may be critical to do in the main thread, for example because the function responsible for gathering callstacks must be loaded first. This is done still on the main thread, in a new function InitCallstackCritical().
137 lines
3.0 KiB
C++
137 lines
3.0 KiB
C++
#ifndef __TRACYCALLSTACK_HPP__
|
|
#define __TRACYCALLSTACK_HPP__
|
|
|
|
#include "../common/TracyApi.h"
|
|
#include "TracyCallstack.h"
|
|
|
|
#if TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
|
# include <unwind.h>
|
|
#elif TRACY_HAS_CALLSTACK >= 3
|
|
# include <execinfo.h>
|
|
#endif
|
|
|
|
|
|
#ifdef TRACY_HAS_CALLSTACK
|
|
|
|
#ifdef TRACY_DEBUGINFOD
|
|
# include <elfutils/debuginfod.h>
|
|
#endif
|
|
|
|
#include <assert.h>
|
|
#include <stdint.h>
|
|
|
|
#include "../common/TracyAlloc.hpp"
|
|
#include "../common/TracyForceInline.hpp"
|
|
|
|
namespace tracy
|
|
{
|
|
|
|
struct CallstackSymbolData
|
|
{
|
|
const char* file;
|
|
uint32_t line;
|
|
bool needFree;
|
|
uint64_t symAddr;
|
|
};
|
|
|
|
struct CallstackEntry
|
|
{
|
|
const char* name;
|
|
const char* file;
|
|
uint32_t line;
|
|
uint32_t symLen;
|
|
uint64_t symAddr;
|
|
};
|
|
|
|
struct CallstackEntryData
|
|
{
|
|
const CallstackEntry* data;
|
|
uint8_t size;
|
|
const char* imageName;
|
|
};
|
|
|
|
CallstackSymbolData DecodeSymbolAddress( uint64_t ptr );
|
|
CallstackSymbolData DecodeCodeAddress( uint64_t ptr );
|
|
const char* DecodeCallstackPtrFast( uint64_t ptr );
|
|
CallstackEntryData DecodeCallstackPtr( uint64_t ptr );
|
|
void InitCallstack();
|
|
void InitCallstackCritical();
|
|
void EndCallstack();
|
|
const char* GetKernelModulePath( uint64_t addr );
|
|
|
|
#ifdef TRACY_DEBUGINFOD
|
|
const uint8_t* GetBuildIdForImage( const char* image, size_t& size );
|
|
debuginfod_client* GetDebuginfodClient();
|
|
#endif
|
|
|
|
#if TRACY_HAS_CALLSTACK == 1
|
|
|
|
extern "C"
|
|
{
|
|
typedef unsigned long (__stdcall *___tracy_t_RtlWalkFrameChain)( void**, unsigned long, unsigned long );
|
|
TRACY_API extern ___tracy_t_RtlWalkFrameChain ___tracy_RtlWalkFrameChain;
|
|
}
|
|
|
|
static tracy_force_inline void* Callstack( int depth )
|
|
{
|
|
assert( depth >= 1 && depth < 63 );
|
|
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
|
|
const auto num = ___tracy_RtlWalkFrameChain( (void**)( trace + 1 ), depth, 0 );
|
|
*trace = num;
|
|
return trace;
|
|
}
|
|
|
|
#elif TRACY_HAS_CALLSTACK == 2 || TRACY_HAS_CALLSTACK == 5
|
|
|
|
struct BacktraceState
|
|
{
|
|
void** current;
|
|
void** end;
|
|
};
|
|
|
|
static _Unwind_Reason_Code tracy_unwind_callback( struct _Unwind_Context* ctx, void* arg )
|
|
{
|
|
auto state = (BacktraceState*)arg;
|
|
uintptr_t pc = _Unwind_GetIP( ctx );
|
|
if( pc )
|
|
{
|
|
if( state->current == state->end ) return _URC_END_OF_STACK;
|
|
*state->current++ = (void*)pc;
|
|
}
|
|
return _URC_NO_REASON;
|
|
}
|
|
|
|
static tracy_force_inline void* Callstack( int depth )
|
|
{
|
|
assert( depth >= 1 && depth < 63 );
|
|
|
|
auto trace = (uintptr_t*)tracy_malloc( ( 1 + depth ) * sizeof( uintptr_t ) );
|
|
BacktraceState state = { (void**)(trace+1), (void**)(trace+1+depth) };
|
|
_Unwind_Backtrace( tracy_unwind_callback, &state );
|
|
|
|
*trace = (uintptr_t*)state.current - trace + 1;
|
|
|
|
return trace;
|
|
}
|
|
|
|
#elif TRACY_HAS_CALLSTACK == 3 || TRACY_HAS_CALLSTACK == 4 || TRACY_HAS_CALLSTACK == 6
|
|
|
|
static tracy_force_inline void* Callstack( int depth )
|
|
{
|
|
assert( depth >= 1 );
|
|
|
|
auto trace = (uintptr_t*)tracy_malloc( ( 1 + (size_t)depth ) * sizeof( uintptr_t ) );
|
|
const auto num = (size_t)backtrace( (void**)(trace+1), depth );
|
|
*trace = num;
|
|
|
|
return trace;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|