diff --git a/targets/app/common/TracyAlloc.cpp b/targets/app/common/TracyAlloc.cpp new file mode 100644 index 000000000..97075d610 --- /dev/null +++ b/targets/app/common/TracyAlloc.cpp @@ -0,0 +1,201 @@ +#include +#include +#include +#include +#ifdef _WIN32 + #include +#endif + +#ifdef TRACY_ENABLE + #include + +namespace { +template +struct TracyMallocAllocator { + using value_type = T; + TracyMallocAllocator() noexcept = default; + template + TracyMallocAllocator(const TracyMallocAllocator&) noexcept {} + T* allocate(std::size_t n) { + return static_cast(std::malloc(n * sizeof(T))); + } + void deallocate(T* p, std::size_t) noexcept { std::free(p); } +}; + +using PtrSet = + std::unordered_set, std::equal_to, + TracyMallocAllocator>; + +inline PtrSet* GetAllocSet() { + static PtrSet* set = []() -> PtrSet* { + void* mem = std::malloc(sizeof(PtrSet)); + return mem ? new (mem) PtrSet() : nullptr; + }(); + return set; +} + +inline std::mutex* GetAllocMutex() { + static std::mutex* mtx = []() -> std::mutex* { + void* mem = std::malloc(sizeof(std::mutex)); + return mem ? new (mem) std::mutex() : nullptr; + }(); + return mtx; +} + +inline void* TracyAlignedAlloc(std::size_t size, std::size_t alignment) { + if (alignment < alignof(void*)) alignment = alignof(void*); +#if defined(_WIN32) + return _aligned_malloc(size, alignment); +#else + void* ptr = nullptr; + if (posix_memalign(&ptr, alignment, size) != 0) { + return nullptr; + } + return ptr; +#endif +} + +inline void TracyAlignedFree(void* ptr) { +#if defined(_WIN32) + _aligned_free(ptr); +#else + free(ptr); +#endif +} + +inline void TracyTrackAlloc(void* ptr, std::size_t size) { + if (!ptr) return; + auto* set = GetAllocSet(); + auto* mtx = GetAllocMutex(); + if (!set || !mtx) return; + std::lock_guard lock(*mtx); + set->insert(ptr); + TracyAlloc(ptr, size); +} + +inline void TracyTrackFree(void* ptr) { + if (!ptr) return; + auto* set = GetAllocSet(); + auto* mtx = GetAllocMutex(); + if (!set || !mtx) return; + std::lock_guard lock(*mtx); + if (set->erase(ptr) != 0) { + TracyFree(ptr); + } +} +} // namespace + +void* operator new(std::size_t count) { + void* ptr = std::malloc(count); + if (!ptr) throw std::bad_alloc(); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void* operator new[](std::size_t count) { + void* ptr = std::malloc(count); + if (!ptr) throw std::bad_alloc(); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void operator delete(void* ptr) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void operator delete[](void* ptr) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void operator delete(void* ptr, std::size_t) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void operator delete[](void* ptr, std::size_t) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void* operator new(std::size_t count, const std::nothrow_t&) noexcept { + void* ptr = std::malloc(count); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void* operator new[](std::size_t count, const std::nothrow_t&) noexcept { + void* ptr = std::malloc(count); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void operator delete(void* ptr, const std::nothrow_t&) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void operator delete[](void* ptr, const std::nothrow_t&) noexcept { + TracyTrackFree(ptr); + std::free(ptr); +} + +void* operator new(std::size_t count, std::align_val_t align) { + void* ptr = TracyAlignedAlloc(count, (std::size_t)align); + if (!ptr) throw std::bad_alloc(); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void* operator new[](std::size_t count, std::align_val_t align) { + void* ptr = TracyAlignedAlloc(count, (std::size_t)align); + if (!ptr) throw std::bad_alloc(); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void* operator new(std::size_t count, std::align_val_t align, + const std::nothrow_t&) noexcept { + void* ptr = TracyAlignedAlloc(count, (std::size_t)align); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void* operator new[](std::size_t count, std::align_val_t align, + const std::nothrow_t&) noexcept { + void* ptr = TracyAlignedAlloc(count, (std::size_t)align); + TracyTrackAlloc(ptr, count); + return ptr; +} + +void operator delete(void* ptr, std::align_val_t) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} + +void operator delete[](void* ptr, std::align_val_t) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} + +void operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} + +void operator delete[](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} + +void operator delete(void* ptr, std::size_t, std::align_val_t) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} + +void operator delete[](void* ptr, std::size_t, std::align_val_t) noexcept { + TracyTrackFree(ptr); + TracyAlignedFree(ptr); +} +#endif \ No newline at end of file