tracy/common/TracyAlloc.hpp
Bartosz Taudul b0fc0d5dcc
Check if rpmalloc has to be initialized before each operation.
The C++11 spec states in [basic.stc.thread] thread storage duration:

2. A variable with thread storage duration shall be initialized before its
   first odr-use (3.2) and, if constructed, shall be destroyed on thread exit.

Previously Tracy relied on the TLS data being initialized:
- During thread creation (MSVC).
- Or during first use in a thread, but the initialization was performed for
  the whole TLS block.

It seems that new compilers are more granular with how they perform the
initialization, hence rpmalloc init has to be checked before each allocation,
as it cannot be "folded" into, for example, initialization of the profiler
itself.
2021-05-31 02:31:42 +02:00

77 lines
1.5 KiB
C++

#ifndef __TRACYALLOC_HPP__
#define __TRACYALLOC_HPP__
#include <stdlib.h>
#ifdef TRACY_ENABLE
# include <atomic>
# include "TracyForceInline.hpp"
# include "TracyYield.hpp"
# include "../client/tracy_rpmalloc.hpp"
#endif
namespace tracy
{
#ifdef TRACY_ENABLE
extern std::atomic<int> RpInitDone;
extern std::atomic<int> RpInitLock;
namespace
{
static inline void InitRpmallocPlumbing()
{
int expected = 0;
while( !RpInitLock.compare_exchange_weak( expected, 1, std::memory_order_release, std::memory_order_relaxed ) ) { expected = 0; YieldThread(); }
const auto done = RpInitDone.load( std::memory_order_acquire );
if( !done )
{
rpmalloc_initialize();
RpInitDone.store( 1, std::memory_order_release );
}
RpInitLock.store( 0, std::memory_order_release );
}
static tracy_force_inline void InitRpmalloc()
{
const auto done = RpInitDone.load( std::memory_order_acquire );
if( !done ) InitRpmallocPlumbing();
rpmalloc_thread_initialize();
}
}
#endif
static inline void* tracy_malloc( size_t size )
{
#ifdef TRACY_ENABLE
InitRpmalloc();
return rpmalloc( size );
#else
return malloc( size );
#endif
}
static inline void tracy_free( void* ptr )
{
#ifdef TRACY_ENABLE
InitRpmalloc();
rpfree( ptr );
#else
free( ptr );
#endif
}
static inline void* tracy_realloc( void* ptr, size_t size )
{
#ifdef TRACY_ENABLE
InitRpmalloc();
return rprealloc( ptr, size );
#else
return realloc( ptr, size );
#endif
}
}
#endif