diff --git a/src/Makefile.am b/src/Makefile.am index dd72838..f974109 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,6 +9,7 @@ libflexmalloc_la_SOURCES = \ allocator.cxx allocator.hxx \ allocator-posix.cxx allocator-posix.hxx \ allocator-statistics.cxx allocator-statistics.hxx \ + statistics-recorder-allocator.hxx \ cache-callstack.cxx cache-callstack.hxx \ flex-malloc.cxx flex-malloc.hxx \ malloc-interposer.cxx diff --git a/src/allocator-memkind-hbwmalloc.cxx b/src/allocator-memkind-hbwmalloc.cxx index 667ef69..931f7c1 100644 --- a/src/allocator-memkind-hbwmalloc.cxx +++ b/src/allocator-memkind-hbwmalloc.cxx @@ -15,7 +15,7 @@ #define ALLOCATOR_NAME "memkind/hbwmalloc" AllocatorMemkindHBWMalloc::AllocatorMemkindHBWMalloc (allocation_functions_t &af) - : Allocator (af) + : StatisticsRecorderAllocator (af) { hbw_set_policy (HBW_POLICY_PREFERRED); } @@ -38,7 +38,7 @@ void * AllocatorMemkindHBWMalloc::malloc (size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats.record_malloc (size); + record_malloc (size); } return res; @@ -59,7 +59,7 @@ void * AllocatorMemkindHBWMalloc::calloc (size_t nmemb, size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats.record_calloc (nmemb * size); + record_calloc (nmemb * size); } return res; @@ -82,7 +82,7 @@ int AllocatorMemkindHBWMalloc::posix_memalign (void **ptr, size_t align, size_t // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); - _stats.record_aligned_malloc (size + align); + record_aligned_malloc (size + align); *ptr = res; return 0; @@ -98,7 +98,7 @@ void AllocatorMemkindHBWMalloc::free (void *ptr) // When freeing the memory, need to free the base pointe VERBOSE_MSG(3, ALLOCATOR_NAME": Freeing up pointer %p (hdr %p) w/ size - %lu (base pointer located in %p)\n", ptr, hdr, hdr->size, hdr->base_ptr); - _stats.record_free (hdr->size); + record_free (hdr->size); hbw_free (hdr->base_ptr); } @@ -129,7 +129,7 @@ void * AllocatorMemkindHBWMalloc::realloc (void *ptr, size_t size) DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p)\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this); } - _stats.record_realloc (size, prev_size); + record_realloc (size, prev_size); return res; } @@ -142,7 +142,7 @@ void * AllocatorMemkindHBWMalloc::realloc (void *ptr, size_t size) else { VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); - _stats.record_realloc_forward_malloc(); + record_realloc_forward_malloc(); return this->malloc (size); } @@ -218,12 +218,3 @@ const char * AllocatorMemkindHBWMalloc::description (void) const return "Allocator based on hbwmalloc on top of memkind"; } -void AllocatorMemkindHBWMalloc::show_statistics (void) const -{ - _stats.show_statistics (ALLOCATOR_NAME, true); -} - -bool AllocatorMemkindHBWMalloc::fits (size_t s) const -{ - return _stats.water_mark() + s <= this->size(); -} diff --git a/src/allocator-memkind-hbwmalloc.hxx b/src/allocator-memkind-hbwmalloc.hxx index 2d40ce6..3b164b7 100644 --- a/src/allocator-memkind-hbwmalloc.hxx +++ b/src/allocator-memkind-hbwmalloc.hxx @@ -4,13 +4,10 @@ #pragma once -#include "allocator.hxx" +#include "statistics-recorder-allocator.hxx" -class AllocatorMemkindHBWMalloc final : public Allocator +class AllocatorMemkindHBWMalloc final : public StatisticsRecorderAllocator { - private: - AllocatorStatistics _stats; - public: AllocatorMemkindHBWMalloc (allocation_functions_t &); ~AllocatorMemkindHBWMalloc(); @@ -25,30 +22,4 @@ class AllocatorMemkindHBWMalloc final : public Allocator void configure (const char *); const char * name (void) const; const char * description (void) const; - void show_statistics (void) const; - - void *memcpy (void *dest, const void *src, size_t n) - { return ::memcpy (dest, src, n); } - - bool fits (size_t s) const; - size_t hwm (void) const - { return _stats.water_mark(); } - void record_unfitted_malloc (size_t s) - { _stats.record_unfitted_malloc (s); } ; - void record_unfitted_calloc (size_t s) - { _stats.record_unfitted_calloc (s); } ; - void record_unfitted_aligned_malloc (size_t s) - { _stats.record_unfitted_aligned_malloc (s); } ; - void record_unfitted_realloc (size_t s) - { _stats.record_unfitted_realloc (s); } ; - - void record_source_realloc (size_t s) - { _stats.record_source_realloc (s); }; - void record_target_realloc (size_t s) - { _stats.record_target_realloc (s); }; - void record_self_realloc (size_t s) - { _stats.record_self_realloc (s); }; - - void record_realloc_forward_malloc (void) - { _stats.record_realloc_forward_malloc (); } }; diff --git a/src/allocator-memkind-pmem.cxx b/src/allocator-memkind-pmem.cxx index 5c1f91f..b55f59b 100644 --- a/src/allocator-memkind-pmem.cxx +++ b/src/allocator-memkind-pmem.cxx @@ -47,6 +47,9 @@ AllocatorMemkindPMEM::AllocatorMemkindPMEM (allocation_functions_t &af) AllocatorMemkindPMEM::~AllocatorMemkindPMEM () { + // Explicitely call the deallocator as the new was done on pre-allocated memory + for (int i = 0; _num_NUMA_nodes > i; ++i) + _stats[i].~AllocatorStatistics(); _af.free (_stats); _af.free (_kind); _af.free (_cpu_2_NUMA); @@ -54,11 +57,9 @@ AllocatorMemkindPMEM::~AllocatorMemkindPMEM () void * AllocatorMemkindPMEM::malloc (size_t size) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; - assert (0 <= n && n < _num_NUMA_nodes); + const short n = get_local_numa (); - DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); + DBG("Running on CPU %d - NUMA node %hd\n", get_current_cpu (), n); // Forward memory request to real malloc and reserve some space for the header void * baseptr = memkind_malloc (_kind[n], Allocator::getTotalSize (size)); @@ -73,7 +74,7 @@ void * AllocatorMemkindPMEM::malloc (size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats[n].record_malloc (size); + record_malloc (size, n); } return res; @@ -81,11 +82,9 @@ void * AllocatorMemkindPMEM::malloc (size_t size) void * AllocatorMemkindPMEM::calloc (size_t nmemb, size_t size) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; - assert (0 <= n && n < _num_NUMA_nodes); + const short n = get_local_numa (); - DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); + DBG("Running on CPU %d - NUMA node %hd\n", get_current_cpu (), n); // Forward memory request to real malloc and request additional space to store // the allocator and the basepointer @@ -101,7 +100,7 @@ void * AllocatorMemkindPMEM::calloc (size_t nmemb, size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats[n].record_calloc (nmemb * size); + record_calloc (nmemb * size, n); } return res; @@ -111,11 +110,9 @@ int AllocatorMemkindPMEM::posix_memalign (void **ptr, size_t align, size_t size) { assert (ptr != nullptr); - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; - assert (0 <= n && n < _num_NUMA_nodes); + const short n = get_local_numa (); - DBG("Running on CPU %d - NUMA node %ld\n", cpu, n); + DBG("Running on CPU %d - NUMA node %hd\n", get_current_cpu (), n); // Forward memory request to real malloc and request additional space to // store the allocator and the basepointer @@ -131,7 +128,7 @@ int AllocatorMemkindPMEM::posix_memalign (void **ptr, size_t align, size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); - _stats[n].record_aligned_malloc (size + align); + record_aligned_malloc (size + align, n); *ptr = res; return 0; @@ -153,7 +150,7 @@ void AllocatorMemkindPMEM::free (void *ptr) assert (gotnode); assert (0 <= n && n < _num_NUMA_nodes); - _stats[n].record_free (hdr->size); + record_free (hdr->size, n); memkind_free (_kind[n], hdr->base_ptr); } @@ -190,7 +187,7 @@ void * AllocatorMemkindPMEM::realloc (void *ptr, size_t size) DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p) on node %d\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this, n); } - _stats[n].record_realloc (size, prev_size); + record_realloc (size, prev_size, n); return res; } @@ -203,9 +200,7 @@ void * AllocatorMemkindPMEM::realloc (void *ptr, size_t size) else { VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; - _stats[n].record_realloc_forward_malloc(); + record_realloc_forward_malloc(); return this->malloc (size); } @@ -341,71 +336,92 @@ void AllocatorMemkindPMEM::show_statistics (void) const } } -bool AllocatorMemkindPMEM::fits (size_t) const +int AllocatorMemkindPMEM::get_current_cpu (void) const +{ + return sched_getcpu (); +} + +short AllocatorMemkindPMEM::get_local_numa (void) const +{ + int cpu = get_current_cpu (); + short n = _cpu_2_NUMA[cpu]; + assert (0 <= n && n < _num_NUMA_nodes); + return n; +} + +bool AllocatorMemkindPMEM::fits (size_t,short) const { return true; } -size_t AllocatorMemkindPMEM::hwm (void) const +size_t AllocatorMemkindPMEM::hwm (short n) const { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; return _stats[n].water_mark (); } -void AllocatorMemkindPMEM::record_unfitted_malloc (size_t s) +void AllocatorMemkindPMEM::record_malloc (size_t s, short n) +{ + _stats[n].record_malloc (s); +} + +void AllocatorMemkindPMEM::record_calloc (size_t s, short n) +{ + _stats[n].record_calloc (s); +} + +void AllocatorMemkindPMEM::record_aligned_malloc (size_t s, short n) +{ + _stats[n].record_aligned_malloc (s); +} + +void AllocatorMemkindPMEM::record_realloc (size_t size, size_t prev_size, short n) +{ + _stats[n].record_realloc (size, prev_size); +} + +void AllocatorMemkindPMEM::record_free (size_t s, short n) +{ + _stats[n].record_free (s); +} + + +void AllocatorMemkindPMEM::record_unfitted_malloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_unfitted_malloc (s); } -void AllocatorMemkindPMEM::record_unfitted_calloc (size_t s) +void AllocatorMemkindPMEM::record_unfitted_calloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_unfitted_calloc (s); } -void AllocatorMemkindPMEM::record_unfitted_aligned_malloc (size_t s) +void AllocatorMemkindPMEM::record_unfitted_aligned_malloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_unfitted_aligned_malloc (s); } -void AllocatorMemkindPMEM::record_unfitted_realloc (size_t s) +void AllocatorMemkindPMEM::record_unfitted_realloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_unfitted_realloc (s); } -void AllocatorMemkindPMEM::record_source_realloc (size_t s) +void AllocatorMemkindPMEM::record_source_realloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_source_realloc (s); } -void AllocatorMemkindPMEM::record_target_realloc (size_t s) +void AllocatorMemkindPMEM::record_target_realloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_target_realloc (s); } -void AllocatorMemkindPMEM::record_self_realloc (size_t s) +void AllocatorMemkindPMEM::record_self_realloc (size_t s, short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_self_realloc (s); } -void AllocatorMemkindPMEM::record_realloc_forward_malloc (void) +void AllocatorMemkindPMEM::record_realloc_forward_malloc (short n) { - int cpu = sched_getcpu(); - long n = _cpu_2_NUMA[cpu]; _stats[n].record_realloc_forward_malloc (); } diff --git a/src/allocator-memkind-pmem.hxx b/src/allocator-memkind-pmem.hxx index 1feb294..c485503 100644 --- a/src/allocator-memkind-pmem.hxx +++ b/src/allocator-memkind-pmem.hxx @@ -1,5 +1,7 @@ // Author: Harald Servat // Date: Feb 10, 2017 +// Author: Clement Foyer +// Date: Jan 18, 2024 // License: To determine #pragma once @@ -36,27 +38,73 @@ class AllocatorMemkindPMEM final : public Allocator void configure (const char *); const char * name (void) const; const char * description (void) const; - void show_statistics (void) const; + void show_statistics (void) const override; - void *memcpy (void *dest, const void *src, size_t n) + void *memcpy (void *dest, const void *src, size_t n) override { #if defined(PMDK_SUPPORTED) return ::pmem_memcpy (dest, src, n, 0); #else - return ::memcpy (dest, src, n); + return Allocator::memcpy(dest, src, n); #endif } - bool fits (size_t s) const; - size_t hwm (void) const; - void record_unfitted_malloc (size_t s); - void record_unfitted_calloc (size_t s); - void record_unfitted_aligned_malloc (size_t s); - void record_unfitted_realloc (size_t s); + bool fits (size_t s) const override + { return fits(s, get_local_numa ()); } + size_t hwm (void) const override + { return hwm(get_local_numa ()); } - void record_source_realloc (size_t s); - void record_target_realloc (size_t s); - void record_self_realloc (size_t s); + void record_malloc (size_t s) override + { return record_malloc (s, get_local_numa ()); } + void record_calloc (size_t s) override + { return record_calloc (s, get_local_numa ()); } + void record_aligned_malloc (size_t s) override + { return record_aligned_malloc (s, get_local_numa ()); } + void record_realloc (size_t size, size_t prev_size) override + { return record_realloc (size, prev_size, get_local_numa ()); } + void record_free (size_t s) override + { return record_free (s, get_local_numa ()); } - void record_realloc_forward_malloc (void); + void record_source_realloc (size_t s) override + { return record_source_realloc (s, get_local_numa ()); } + void record_target_realloc (size_t s) override + { return record_target_realloc (s, get_local_numa ()); } + void record_self_realloc (size_t s) override + { return record_self_realloc (s, get_local_numa ()); } + + void record_unfitted_malloc (size_t s) override + { return record_unfitted_malloc (s, get_local_numa ()); } + void record_unfitted_calloc (size_t s) override + { return record_unfitted_calloc (s, get_local_numa ()); } + void record_unfitted_aligned_malloc (size_t s) override + { return record_unfitted_aligned_malloc (s, get_local_numa ()); } + void record_unfitted_realloc (size_t s) override + { return record_unfitted_realloc (s, get_local_numa ()); } + + void record_realloc_forward_malloc (void) override + { return record_realloc_forward_malloc (get_local_numa ()); } + + private: + int get_current_cpu (void) const; + short get_local_numa (void) const; + + bool fits (size_t,short) const; + size_t hwm (short) const; + + void record_malloc (size_t,short); + void record_calloc (size_t,short); + void record_aligned_malloc (size_t,short); + void record_realloc (size_t, size_t,short); + void record_free (size_t,short); + + void record_source_realloc (size_t,short); + void record_target_realloc (size_t,short); + void record_self_realloc (size_t,short); + + void record_unfitted_malloc (size_t,short); + void record_unfitted_calloc (size_t,short); + void record_unfitted_aligned_malloc (size_t,short); + void record_unfitted_realloc (size_t,short); + + void record_realloc_forward_malloc (short); }; diff --git a/src/allocator-posix.cxx b/src/allocator-posix.cxx index 3bb6fe1..977634b 100644 --- a/src/allocator-posix.cxx +++ b/src/allocator-posix.cxx @@ -13,7 +13,7 @@ #define ALLOCATOR_NAME "posix" AllocatorPOSIX::AllocatorPOSIX (allocation_functions_t &af) - : Allocator (af) + : StatisticsRecorderAllocator (af) { } @@ -35,7 +35,7 @@ void * AllocatorPOSIX::malloc (size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base at %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats.record_malloc (size); + record_malloc (size); } return res; @@ -56,7 +56,7 @@ void * AllocatorPOSIX::calloc (size_t nmemb, size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr & base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), name(), this); - _stats.record_calloc (nmemb * size); + record_calloc (nmemb * size); } return res; @@ -78,7 +78,7 @@ int AllocatorPOSIX::posix_memalign (void **ptr, size_t align, size_t size) // Verbosity and emit statistics VERBOSE_MSG(3, ALLOCATOR_NAME": Allocated %lu bytes in %p (hdr %p, base %p) w/ allocator %s (%p)\n", size, res, Allocator::getAllocatorHeader (res), baseptr, name(), this); - _stats.record_aligned_malloc (size + align); + record_aligned_malloc (size + align); *ptr = res; return 0; @@ -93,8 +93,8 @@ void AllocatorPOSIX::free (void *ptr) // When freeing the memory, need to free the base pointe VERBOSE_MSG(3, ALLOCATOR_NAME": Freeing up pointer %p (hdr %p) w/ size - %lu (base pointer located in %p)\n", ptr, hdr, hdr->size, hdr->base_ptr); - - _stats.record_free (hdr->size); + + record_free (hdr->size); _af.free (hdr->base_ptr); } @@ -124,7 +124,7 @@ void * AllocatorPOSIX::realloc (void *ptr, size_t size) DBG("Reallocated (%ld->%ld [extra bytes = %lu]) from %p (base at %p, header at %p) into %p (base at %p, header at %p) w/ allocator %s (%p)\n", prev_size, size, extra_size, ptr, prev_baseptr, prev_hdr, res, new_baseptr, Allocator::getAllocatorHeader (res), name(), this); } - _stats.record_realloc (size, prev_size); + record_realloc (size, prev_size); return res; } @@ -137,7 +137,7 @@ void * AllocatorPOSIX::realloc (void *ptr, size_t size) else { VERBOSE_MSG(3, ALLOCATOR_NAME": realloc (NULL, ...) forwarded to malloc\n"); - _stats.record_realloc_forward_malloc(); + record_realloc_forward_malloc(); return this->malloc (size); } @@ -213,12 +213,3 @@ const char * AllocatorPOSIX::description (void) const return "Fallback allocator based on regular POSIX calls from system's libc"; } -void AllocatorPOSIX::show_statistics (void) const -{ - _stats.show_statistics (ALLOCATOR_NAME, true); -} - -bool AllocatorPOSIX::fits (size_t s) const -{ - return _stats.water_mark() + s <= this->size(); -} diff --git a/src/allocator-posix.hxx b/src/allocator-posix.hxx index ab54f55..16ae30d 100644 --- a/src/allocator-posix.hxx +++ b/src/allocator-posix.hxx @@ -4,14 +4,11 @@ #pragma once -#include "allocator.hxx" +#include "statistics-recorder-allocator.hxx" #include -class AllocatorPOSIX final : public Allocator +class AllocatorPOSIX final : public StatisticsRecorderAllocator { - private: - AllocatorStatistics _stats; - public: AllocatorPOSIX(allocation_functions_t &); ~AllocatorPOSIX(); @@ -26,30 +23,4 @@ class AllocatorPOSIX final : public Allocator void configure (const char *); const char * name (void) const; const char * description (void) const; - void show_statistics (void) const; - - void *memcpy (void *dest, const void *src, size_t n) - { return ::memcpy (dest, src, n); } - - bool fits (size_t s) const; - size_t hwm (void) const - { return _stats.water_mark(); } - void record_unfitted_malloc (size_t s) - { _stats.record_unfitted_malloc (s); } ; - void record_unfitted_calloc (size_t s) - { _stats.record_unfitted_calloc (s); } ; - void record_unfitted_aligned_malloc (size_t s) - { _stats.record_unfitted_aligned_malloc (s); } ; - void record_unfitted_realloc (size_t s) - { _stats.record_unfitted_realloc (s); } ; - - void record_source_realloc (size_t s) - { _stats.record_source_realloc (s); }; - void record_target_realloc (size_t s) - { _stats.record_target_realloc (s); }; - void record_self_realloc (size_t s) - { _stats.record_self_realloc (s); }; - - void record_realloc_forward_malloc (void) - { _stats.record_realloc_forward_malloc (); } }; diff --git a/src/allocator.cxx b/src/allocator.cxx index 4ad2a12..eeb04b6 100644 --- a/src/allocator.cxx +++ b/src/allocator.cxx @@ -21,17 +21,7 @@ Allocator::Header_t * Allocator::getAllocatorHeader (void * ptr) void * Allocator::generateAllocatorHeader (void *ptr, Allocator *a, size_t s) { - // Calculate new storage address - void *res = (void*) (((uintptr_t) ptr) + ALLOCATOR_HEADER_SZ); - - // Record the header contents - Header_t *hdr = getAllocatorHeader (res); - hdr->allocator = a; - hdr->base_ptr = ptr; - hdr->size = s; - hdr->aux.u64[0] = 0; // Reset AUX field - - return res; + return generateAllocatorHeader (ptr, 0, a, s); } void * Allocator::generateAllocatorHeader (void *ptr, size_t extrabytes, Allocator *a, size_t s) @@ -53,20 +43,14 @@ void * Allocator::generateAllocatorHeaderOnAligned (void *ptr, size_t align, All { // Calculate new storage address void * res = (void*) align_to (((uintptr_t) ptr + ALLOCATOR_HEADER_SZ), align); + size_t padded_align = (uintptr_t) res - (uintptr_t) ptr; // Well-aligned given the requested alignment assert ( ( (uintptr_t) res & (align - 1) ) == 0); // Ensure enough space for a header between newptr and baseptr - assert ( ( (uintptr_t) res - (uintptr_t) ptr ) >= ALLOCATOR_HEADER_SZ ); + assert ( padded_align >= ALLOCATOR_HEADER_SZ ); - // Record the header contents - Header_t *hdr = getAllocatorHeader (res); - hdr->allocator = a; - hdr->base_ptr = ptr; - hdr->size = s; - hdr->aux.u64[0] = 0; // Reset AUX field - - return res; + return generateAllocatorHeader(ptr, padded_align - ALLOCATOR_HEADER_SZ, a, s); } Allocator::Allocator (allocation_functions_t &af) diff --git a/src/allocator.hxx b/src/allocator.hxx index 5352398..47f44ea 100644 --- a/src/allocator.hxx +++ b/src/allocator.hxx @@ -5,8 +5,8 @@ #pragma once #include +#include #include "common.hxx" -#include "allocator-statistics.hxx" class Allocator { @@ -68,7 +68,8 @@ class Allocator virtual void* realloc (void *, size_t) = 0; virtual size_t malloc_usable_size (void*) = 0; - virtual void *memcpy (void *dest, const void *src, size_t n) = 0; + virtual void *memcpy (void *dest, const void *src, size_t n) + { return ::memcpy(dest, src, n); } virtual void configure (const char *) = 0; virtual bool is_ready (void) const { return _is_ready; }; @@ -83,15 +84,22 @@ class Allocator virtual bool fits (size_t s) const = 0; virtual size_t hwm (void) const = 0; + + virtual void record_malloc (size_t) = 0; + virtual void record_calloc (size_t) = 0; + virtual void record_aligned_malloc (size_t) = 0; + virtual void record_realloc (size_t size, size_t prev_size) = 0; + virtual void record_free (size_t) = 0; + + virtual void record_source_realloc (size_t s) = 0; + virtual void record_target_realloc (size_t s) = 0; + virtual void record_self_realloc (size_t s) = 0; + virtual void record_unfitted_malloc (size_t) = 0; virtual void record_unfitted_calloc (size_t) = 0; virtual void record_unfitted_aligned_malloc (size_t) = 0; virtual void record_unfitted_realloc (size_t) = 0; - virtual void record_source_realloc (size_t) = 0; - virtual void record_target_realloc (size_t) = 0; - virtual void record_self_realloc (size_t) = 0; - virtual void record_realloc_forward_malloc (void) = 0; }; diff --git a/src/allocators.cxx b/src/allocators.cxx index dfe0ec7..640ef33 100644 --- a/src/allocators.cxx +++ b/src/allocators.cxx @@ -127,7 +127,7 @@ Allocators::Allocators (allocation_functions_t &af, const char *definitions) else { VERBOSE_MSG(0, "Allocator %s is not registered.\n", allocatorname); - exit (0); + exit (2); } } defs = strchr (defs+count+1, '#'); // Search for next # Memory configuration diff --git a/src/code-locations.cxx b/src/code-locations.cxx index b1162f2..7482928 100644 --- a/src/code-locations.cxx +++ b/src/code-locations.cxx @@ -232,10 +232,10 @@ bool CodeLocations::load_memory_mappings_info (memory_maps_t& maps) return true; } -long CodeLocations::file_offset_to_address (const char *lib, unsigned long offset, bool& found) +size_t CodeLocations::file_offset_to_address (const char *lib, size_t offset, bool& found) { - long baseAddress = 0; - unsigned long baseOffset = 0; + size_t baseAddress = 0; + size_t baseOffset = 0; found = false; for (unsigned i = 0; i < _maps_info.num_entries; i++) @@ -276,7 +276,7 @@ long CodeLocations::file_offset_to_address (const char *lib, unsigned long offse } } - DBG("Base address for library (%s) -> %lx\n", lib, baseAddress); + DBG("Base address for library (%s) -> %zx\n", lib, baseAddress); return baseAddress + (offset - baseOffset); } @@ -311,21 +311,21 @@ bool CodeLocations::process_raw_location (char *location_txt, location_t * locat module[module_len] = '\0'; char *endptr; - long offset = strtoul (frame+1, &endptr, 16); - assert (endptr <= frame+1+16); + size_t offset = strtoull (frame+1, &endptr, options.readOffsetBase()); + assert (endptr <= frame+1+options.maxOffsetDigits()); bool found = false; long address = file_offset_to_address (module, offset, found); if (found) { - DBG("Offset %lx in file %s gets relocated to address %lx.\n", + DBG("Offset %zx in file %s gets relocated to address %zx.\n", offset, module, address); location->frames.raw[f].frame = address; } else { - DBG("Could not translate frame: '%s'!%08lx\n", module, offset); + DBG("Could not translate frame: '%s'!%08zx\n", module, offset); location->frames.raw[f].frame = 0; pending_module_t* mm = add_or_get_pending_module (module); @@ -855,6 +855,8 @@ void CodeLocations::show_frames (void) void CodeLocations::show_hmem_visualizer_stats (const char *fallback_allocator_name) { + FILE* const outstream = options.messages_on_stderr() ? stderr : stdout; + if (_nlocations > 0) { VERBOSE_MSG(0, "Locations information:\n"); @@ -876,14 +878,14 @@ void CodeLocations::show_hmem_visualizer_stats (const char *fallback_allocator_n { if (al[u]->has_size() && al[u]->used()) { - fprintf (options.messages_on_stderr()?stderr:stdout, "#vis type=mem, name=%s, capacity=%lu\n", + fprintf (outstream, "#vis type=mem, name=%s, capacity=%lu\n", al[u]->name(), al[u]->size()); } u++; } // Additional information for extra fields - fprintf (options.messages_on_stderr()?stderr:stdout, "#vis extra_field_0 = hatch\n"); + fprintf (outstream, "#vis extra_field_0 = hatch\n"); // Data // callstack;bytes;weight;memtype[;extrafield1;extrafield2;...] @@ -899,26 +901,26 @@ void CodeLocations::show_hmem_visualizer_stats (const char *fallback_allocator_n const raw_frame_t * rf = &(_locations[l].frames.raw[0]); if (options.sourceFrames()) - fprintf (options.messages_on_stderr()?stderr:stdout, "%s:%d", fp->file, fp->line); + fprintf (outstream, "%s:%d", fp->file, fp->line); else - fprintf (options.messages_on_stderr()?stderr:stdout, "%08lx", rf->frame); + fprintf (outstream, "%08lx", rf->frame); for (unsigned f = 1; f < _locations[l].nframes; f++) { fp = &(_locations[l].frames.source[f]); rf = &(_locations[l].frames.raw[f]); if (options.sourceFrames()) - fprintf (options.messages_on_stderr()?stderr:stdout, " > %s:%d", fp->file, fp->line); + fprintf (outstream, " > %s:%d", fp->file, fp->line); else - fprintf (options.messages_on_stderr()?stderr:stdout, " > %08lx", rf->frame); + fprintf (outstream, " > %08lx", rf->frame); } // bytes part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%lu", _locations[l].stats.HWM); + fprintf (outstream, ";%lu", _locations[l].stats.HWM); // weight part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%d", 0); + fprintf (outstream, ";%d", 0); // memtype part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%s", allocator(l)->name()); + fprintf (outstream, ";%s", allocator(l)->name()); // EoL - fprintf (options.messages_on_stderr()?stderr:stdout, "\n"); + fprintf (outstream, "\n"); } // Second -- information on allocations that were served by the fallback allocator @@ -928,28 +930,28 @@ void CodeLocations::show_hmem_visualizer_stats (const char *fallback_allocator_n const source_frame_t * fp = &(_locations[l].frames.source[0]); const raw_frame_t * rf = &(_locations[l].frames.raw[0]); if (options.sourceFrames()) - fprintf (options.messages_on_stderr()?stderr:stdout, "%s:%d", fp->file, fp->line); + fprintf (outstream, "%s:%d", fp->file, fp->line); else - fprintf (options.messages_on_stderr()?stderr:stdout, "%08lx", rf->frame); + fprintf (outstream, "%08lx", rf->frame); for (unsigned f = 1; f < _locations[l].nframes; f++) { fp = &(_locations[l].frames.source[f]); rf = &(_locations[l].frames.raw[f]); if (options.sourceFrames()) - fprintf (options.messages_on_stderr()?stderr:stdout, " > %s:%d", fp->file, fp->line); + fprintf (outstream, " > %s:%d", fp->file, fp->line); else - fprintf (options.messages_on_stderr()?stderr:stdout, " > %08lx", rf->frame); + fprintf (outstream, " > %08lx", rf->frame); } // bytes part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%lu", _locations[l].stats.HWM_fb); + fprintf (outstream, ";%lu", _locations[l].stats.HWM_fb); // weight part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%d", 0); + fprintf (outstream, ";%d", 0); // memtype part - fprintf (options.messages_on_stderr()?stderr:stdout, ";%s", fallback_allocator_name); + fprintf (outstream, ";%s", fallback_allocator_name); // extra field - fprintf (options.messages_on_stderr()?stderr:stdout, ";%d", 1); + fprintf (outstream, ";%d", 1); // EoL - fprintf (options.messages_on_stderr()?stderr:stdout, "\n"); + fprintf (outstream, "\n"); } } VERBOSE_MSG(0, "-- HMEM visualizer results -- (end cut here) --\n"); diff --git a/src/code-locations.hxx b/src/code-locations.hxx index b4ace7a..71602e3 100644 --- a/src/code-locations.hxx +++ b/src/code-locations.hxx @@ -51,8 +51,8 @@ class CodeLocations typedef struct st_pending_raw_frame { pending_module_t* module; - long offset; - unsigned index; + size_t offset; + size_t index; struct st_pending_raw_frame* next; } pending_raw_frame_t; @@ -73,9 +73,9 @@ class CodeLocations #define LINE_SIZE 2048 typedef struct { - unsigned long start; - unsigned long end; - unsigned long offset; + size_t start; + size_t end; + size_t offset; char module[LINE_SIZE+1]; bool perm_read; bool perm_write; @@ -115,7 +115,7 @@ class CodeLocations bool process_raw_location (char *location_txt, location_t * location, const char * fallback_allocator_name); void clean_source_location (location_t * location); void show_frames (void); - long file_offset_to_address (const char *lib, unsigned long address, bool& found); + size_t file_offset_to_address (const char *lib, size_t address, bool& found); void create_fast_indexes_for_frames (void); bool load_memory_mappings_info (memory_maps_t& maps); pending_module_t* get_pending_module(const char* path); diff --git a/src/common.cxx b/src/common.cxx index 7c49db4..4e74b04 100644 --- a/src/common.cxx +++ b/src/common.cxx @@ -5,6 +5,7 @@ #include #include #include +#include #include "common.hxx" Options options; @@ -30,10 +31,11 @@ Options options; #define MATCH_ONLY_ON_MAIN_BINARY_DEFAULT false #define SOURCE_FRAMES_DEFAULT true #define IGNORE_IF_FALLBACK_ALLOCATOR_DEFAULT true +#define READ_OFFSET_BASE_DEFAULT 16 #define PROCESS_ENVVAR(envvar,var,defvalue) \ - { \ - char *s = getenv (envvar); \ + do { \ + const char *s = getenv (envvar); \ if (s != nullptr) \ { \ if (CHECK_ENABLED(s)) \ @@ -45,12 +47,12 @@ Options options; } \ else \ var = defvalue;\ - } + } while (0) Options::Options () : _minSize(0), _max_depth(100) { - char *verbose = getenv(TOOL_VERBOSE); + const char *verbose = getenv(TOOL_VERBOSE); if (verbose != nullptr) { _VerboseLvl = atoi(verbose); @@ -83,17 +85,66 @@ Options::Options () } int msize = 0; - char *msize_threshold = getenv(TOOL_MINSIZE_THRESHOLD); + const char *msize_threshold = getenv(TOOL_MINSIZE_THRESHOLD); if (msize_threshold != nullptr) msize = atoi (msize_threshold); if (msize < 0) { - VERBOSE_MSG(0, "Wrong value for environment variable %s. Setting it to 0.\n", - TOOL_MINSIZE_THRESHOLD); - _minSize = 0; + msize = 0; + VERBOSE_MSG(0, "Wrong value for environment variable %s. Setting it to %d.\n", + TOOL_MINSIZE_THRESHOLD, msize); } - else - _minSize = msize; + _minSize = msize; + + const char *def_file = getenv (TOOL_DEFINITIONS_FILE); + if (def_file == nullptr) + { + VERBOSE_MSG(0, "Did not find " TOOL_DEFINITIONS_FILE " environment variable. Finishing...\n"); + _exit (2); + } + _definitions_filename = def_file; + + const char *loc_file = getenv (TOOL_LOCATIONS_FILE); + if (loc_file == nullptr) + { + VERBOSE_MSG(0, "Did not find " TOOL_LOCATIONS_FILE " environment variable. Finishing...\n"); + _exit (2); + } + _locations_filename = loc_file; + + int offset_base = READ_OFFSET_BASE_DEFAULT; + const char *read_offset_base = getenv(TOOL_READ_OFFSET_BASE); + if (read_offset_base != nullptr) + offset_base = atoi (read_offset_base); + if (offset_base < 0) + { + offset_base = READ_OFFSET_BASE_DEFAULT; + VERBOSE_MSG(0, "Wrong value for environment variable %s. Setting it to %d.\n", + TOOL_READ_OFFSET_BASE, offset_base); + } + _read_offset_base = offset_base; + // At most, we have 16 digits long hexadecimal addresses in /proc//maps entries + _max_offset_digits = static_cast(ceil(std::log(std::pow(16.0,16.0))/std::log(static_cast(offset_base)))); + + // Get fallback allocator, if given from environment. + // If not, we use the regular "posix" allocators as fallback. + const char *fallback_alloc_name = getenv (TOOL_FALLBACK_ALLOCATOR); + if (fallback_alloc_name == nullptr) + { + fallback_alloc_name = "posix"; + VERBOSE_MSG(0, "No fallback allocator's name provided. Using the default one: \"%s\".\n", + fallback_alloc_name); + } + _fallback_allocator_name = fallback_alloc_name; + + const char *small_alloc_fallback_name = getenv (TOOL_MINSIZE_THRESHOLD_ALLOCATOR); + if (small_alloc_fallback_name == nullptr) + { + small_alloc_fallback_name = _fallback_allocator_name; + VERBOSE_MSG(0, "No fallback allocator's name provided for small allocations. Using the default one: \"%s\".\n", + small_alloc_fallback_name); + } + _small_allocation_falback_allocator_name = small_alloc_fallback_name; struct timespec ts; clock_gettime (CLOCK_MONOTONIC, &ts); diff --git a/src/common.hxx b/src/common.hxx index 04cd893..985090b 100644 --- a/src/common.hxx +++ b/src/common.hxx @@ -28,45 +28,63 @@ class Options bool _sourceFrames; bool _sourceFramesSet; bool _ignoreIfFallbackAllocator; - + unsigned _read_offset_base; + size_t _max_offset_digits; + const char* _definitions_filename; + const char* _locations_filename; + const char* _fallback_allocator_name; + const char* _small_allocation_falback_allocator_name; + public: Options (); ~Options (); int verboseLvl (void) const - { return _VerboseLvl; }; + { return _VerboseLvl; } bool compareWholePath (void) const - { return _comparewholepath; }; + { return _comparewholepath; } void minSize (unsigned s) - { _minSize = s; }; + { _minSize = s; } size_t minSize (void) const - { return _minSize; }; + { return _minSize; } bool debug (void) const - { return _debug; }; - bool messages_on_stderr(void) const - { return _messages_on_stderr; }; - unsigned maxDepth (void) const - { return _max_depth; }; - void callstackMinus1(bool b) + { return _debug; } + bool messages_on_stderr (void) const + { return _messages_on_stderr; } + size_t maxDepth (void) const + { return _max_depth; } + void callstackMinus1 (bool b) { _callstack_minus_1 = b; } - bool callstackMinus1(void) const - { return _callstack_minus_1; }; + bool callstackMinus1 (void) const + { return _callstack_minus_1; } void stopAtMain (bool b) - { _stopAtMain = b; }; + { _stopAtMain = b; } bool stopAtMain (void) const - { return _stopAtMain; }; + { return _stopAtMain; } void shortenFrames (bool b) - { _shorten_frames = b; }; + { _shorten_frames = b; } bool shortenFrames (void) const - { return _shorten_frames; }; - uint64_t getTime(void) const; + { return _shorten_frames; } + uint64_t getTime (void) const; bool sourceFrames (void) const - { return _sourceFrames; }; + { return _sourceFrames; } void sourceFrames (bool b) - { _sourceFrames = b; }; + { _sourceFrames = b; } bool sourceFrame_set (void) const - { return _sourceFramesSet; }; + { return _sourceFramesSet; } bool ignoreIfFallbackAllocator (void) const - { return _ignoreIfFallbackAllocator; }; + { return _ignoreIfFallbackAllocator; } + unsigned readOffsetBase (void) const + { return _read_offset_base; } + size_t maxOffsetDigits (void) const + { return _max_offset_digits; } + const char* definitionFileName (void) const + { return _definitions_filename; } + const char* locationsFileName (void) const + { return _locations_filename; } + const char* fallbackAllocatorName (void) const + { return _fallback_allocator_name; } + const char* smallAllocationFallbackAllocatorName (void) const + { return _small_allocation_falback_allocator_name; } }; typedef struct allocation_functions_st @@ -97,22 +115,23 @@ extern Options options; #define TOOL_MATCH_ONLY_ON_MAIN_BINARY TOOL_NAME"_MATCH_ONLY_ON_MAIN_BINARY" #define TOOL_SOURCE_FRAMES TOOL_NAME"_SOURCE_FRAMES" #define TOOL_IGNORE_IF_FALLBACK_ALLOCATOR TOOL_NAME"_IGNORE_LOCATIONS_ON_FALLBACK_ALLOCATOR" +#define TOOL_READ_OFFSET_BASE TOOL_NAME"_READ_OFFSET_BASE" #define VERBOSE_MSG(level,...) \ - { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, TOOL_NAME"|" __VA_ARGS__); } } + do { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, TOOL_NAME"|" __VA_ARGS__); } } while(0) #define VERBOSE_MSG_NOPREFIX(level,...) \ - { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, __VA_ARGS__); } } + do { if (options.verboseLvl() >= level || options.debug()) { fprintf (options.messages_on_stderr() ? stderr : stdout, __VA_ARGS__); } } while(0) #if defined(DEBUG) # define DBG(fmt,...) \ - { \ + do { \ if (options.debug()) \ { \ fprintf (options.messages_on_stderr() ? stderr : stdout, \ TOOL_NAME"|DBG|%s (%s:%d)|%luus: " fmt, __func__, __FILE__, __LINE__, options.getTime()/1000, __VA_ARGS__); \ fflush (options.messages_on_stderr() ? stderr : stdout); \ } \ - } + } while(0) #else # define DBG(fmt,...) #endif diff --git a/src/flex-malloc.cxx b/src/flex-malloc.cxx index 89c6d2a..f74d7e7 100644 --- a/src/flex-malloc.cxx +++ b/src/flex-malloc.cxx @@ -592,7 +592,7 @@ void * FlexMalloc::realloc (unsigned nptrs, void **callstack, void *ptr, size_t if (res == nullptr) { VERBOSE_MSG (0, "Could not allocate space for memcpy operation on default allocator. Exiting...\n"); - _exit (0); + _exit (1); } } else @@ -601,7 +601,7 @@ void * FlexMalloc::realloc (unsigned nptrs, void **callstack, void *ptr, size_t if (res == nullptr) { VERBOSE_MSG (0, "Could not allocate space for memcpy operation on allocator (%s). Exiting...\n", new_allocator->name()); - _exit (0); + _exit (1); } } diff --git a/src/malloc-interposer.cxx b/src/malloc-interposer.cxx index 6d5b9a9..bd016e0 100644 --- a/src/malloc-interposer.cxx +++ b/src/malloc-interposer.cxx @@ -791,7 +791,7 @@ size_t malloc_usable_size (void *ptr) void malloc_interposer_start (void) __attribute__((constructor)); void malloc_interposer_start (void) { - char *env; + const char *env; VERBOSE_MSG(0, "Initializing " TOOL_NAME " " PACKAGE_VERSION "... \n"); @@ -816,46 +816,29 @@ void malloc_interposer_start (void) real_allocation_functions.malloc_usable_size == nullptr) { VERBOSE_MSG(0, "Could not find malloc/calloc/free/realloc/posix_memalign/malloc_usable_size symbols in DSOs."); - _exit (0); + _exit (-1); } // Get memory definitions from environment - if ((env = getenv (TOOL_DEFINITIONS_FILE)) != nullptr) + if ((env = options.definitionFileName ()) != nullptr) { allocators = (Allocators*) real_allocation_functions.malloc (sizeof(Allocators)); assert (allocators != nullptr); - new (allocators) Allocators (real_allocation_functions, getenv(TOOL_DEFINITIONS_FILE)); - } - else - { - VERBOSE_MSG(0, "Did not find " TOOL_DEFINITIONS_FILE " environment variable. Finishing...\n"); - _exit (0); + new (allocators) Allocators (real_allocation_functions, env); } - // Get fallback allocator, if given from environment. - // If not, we use the regular "posix" allocators as fallback. - if ((env = getenv (TOOL_FALLBACK_ALLOCATOR)) != nullptr) + // Get fallback allocator as set in Options + env = options.fallbackAllocatorName (); + fallback = allocators->get (env); + if (!fallback) { - fallback = allocators->get (env); - if (!fallback) - { - VERBOSE_MSG(0, "Did not find allocator \"%s\" to be used as fallback allocator. Exiting!\n", env); - _exit (0); - } - } - else - { - fallback = allocators->get ("posix"); - if (!fallback) - { - VERBOSE_MSG(0, "Did not find allocator \"posix\" to be used as fallback allocator. Exiting!\n"); - _exit (0); - } + VERBOSE_MSG(0, "Did not find allocator \"%s\" to be used as fallback allocator. Exiting!\n", env); + _exit (2); } if (! fallback->is_ready()) { VERBOSE_MSG(0, "The fallback allocator '%s' is not ready. Check if its parameters in the configuration file are correct. Exiting!\n", fallback->name()); - _exit (0); + _exit (2); } VERBOSE_MSG(0, "Fallback allocator set to '%s'\n", fallback->name()); @@ -890,18 +873,18 @@ void malloc_interposer_start (void) // that will handle small allocations if (options.minSize() > 0) { - if ((env = getenv (TOOL_MINSIZE_THRESHOLD_ALLOCATOR)) != nullptr) + if ((env = options.smallAllocationFallbackAllocatorName ()) != nullptr) { fallback_smallAllocation = allocators->get (env); if (!fallback_smallAllocation) { VERBOSE_MSG(0, "Did not find allocator \"%s\" to be used as fallback allocator for small allocations. Exiting!\n", env); - _exit (0); + _exit (2); } if (! fallback_smallAllocation->is_ready()) { VERBOSE_MSG(0, "The fallback allocator for small allocations '%s' is not ready. Check if its parameters in the configuration file are correct.\n", fallback_smallAllocation->name()); - _exit (0); + _exit (2); } } else @@ -914,18 +897,13 @@ void malloc_interposer_start (void) fallback->used(true); // If the user has given a file pointing to callstacks, parse and enable runtime - if ((env = getenv (TOOL_LOCATIONS_FILE)) != nullptr) + if ((env = options.locationsFileName()) != nullptr) { codelocations = (CodeLocations*) real_allocation_functions.malloc (sizeof(CodeLocations)); assert (codelocations != nullptr); new (codelocations) CodeLocations (real_allocation_functions, allocators); codelocations->readfile (env, fallback->name()); } - else - { - VERBOSE_MSG(0, "Did not find " TOOL_LOCATIONS_FILE " environment variable. Finishing...\n"); - _exit (0); - } // Allocate main flexmalloc object flexmalloc = (FlexMalloc*) real_allocation_functions.malloc (sizeof(FlexMalloc)); diff --git a/src/statistics-recorder-allocator.hxx b/src/statistics-recorder-allocator.hxx new file mode 100644 index 0000000..c56473e --- /dev/null +++ b/src/statistics-recorder-allocator.hxx @@ -0,0 +1,57 @@ +// Author: Clément Foyer +// Date: Jul 06, 2023 +// License: To determine + +#pragma once + +#include "allocator.hxx" +#include "allocator-statistics.hxx" + +class StatisticsRecorderAllocator : public Allocator +{ + private: + AllocatorStatistics _stats; + + public: + StatisticsRecorderAllocator (allocation_functions_t &af) + : Allocator(af) {} + ~StatisticsRecorderAllocator() = default; + + void show_statistics (void) const override + { _stats.show_statistics (this->name(), true); } + + size_t hwm (void) const override + { return _stats.water_mark(); } + bool fits (size_t s) const override + { return this->hwm() + s <= this->size(); } + + void record_malloc (size_t s) override + { _stats.record_malloc (s); } + void record_calloc (size_t s) override + { _stats.record_calloc (s); } + void record_aligned_malloc (size_t s) override + { _stats.record_aligned_malloc (s); } + void record_realloc (size_t size, size_t prev_size) override + { _stats.record_realloc (size, prev_size); } + void record_free (size_t s) override + { _stats.record_free (s); } + + void record_source_realloc (size_t s) override + { _stats.record_source_realloc (s); } + void record_target_realloc (size_t s) override + { _stats.record_target_realloc (s); } + void record_self_realloc (size_t s) override + { _stats.record_self_realloc (s); } + + void record_unfitted_malloc (size_t s) override + { _stats.record_unfitted_malloc (s); } + void record_unfitted_calloc (size_t s) override + { _stats.record_unfitted_calloc (s); } + void record_unfitted_aligned_malloc (size_t s) override + { _stats.record_unfitted_aligned_malloc (s); } + void record_unfitted_realloc (size_t s) override + { _stats.record_unfitted_realloc (s); } + + void record_realloc_forward_malloc (void) override + { _stats.record_realloc_forward_malloc (); } +};