From 918e9f2ba0aa8ac4c1419873bd8dda1ad880b763 Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Mon, 28 Jun 2021 22:10:50 +0000 Subject: Implement _malloc_usable_size --- vespamalloc/src/tests/test1/new_test.cpp | 32 ++++++++ vespamalloc/src/vespamalloc/malloc/globalpool.h | 1 + vespamalloc/src/vespamalloc/malloc/globalpool.hpp | 8 +- vespamalloc/src/vespamalloc/malloc/malloc.cpp | 7 ++ vespamalloc/src/vespamalloc/malloc/malloc.h | 3 + vespamalloc/src/vespamalloc/malloc/mallocd.cpp | 7 ++ vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp | 6 ++ .../src/vespamalloc/malloc/mallocdst16_nl.cpp | 7 ++ vespamalloc/src/vespamalloc/malloc/memblock.h | 3 + .../src/vespamalloc/malloc/memblockboundscheck.h | 3 + vespamalloc/src/vespamalloc/malloc/overload.h | 91 ++-------------------- vespamalloc/src/vespamalloc/malloc/threadlist.h | 4 +- vespamalloc/src/vespamalloc/malloc/threadpool.h | 2 +- vespamalloc/src/vespamalloc/malloc/threadpool.hpp | 6 +- 14 files changed, 87 insertions(+), 93 deletions(-) (limited to 'vespamalloc/src') diff --git a/vespamalloc/src/tests/test1/new_test.cpp b/vespamalloc/src/tests/test1/new_test.cpp index a8392363f6f..9c291b3842e 100644 --- a/vespamalloc/src/tests/test1/new_test.cpp +++ b/vespamalloc/src/tests/test1/new_test.cpp @@ -1,6 +1,8 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include #include +#include +#include LOG_SETUP("new_test"); @@ -105,5 +107,35 @@ TEST("verify new with alignment = 64 with single element") { LOG(info, "&s=%p", s.get()); } +void verify_vespamalloc_usable_size() { + struct AllocInfo { size_t requested; size_t usable;}; + AllocInfo allocInfo[] = {{0x7, 0x20}, {0x27, 0x40}, {0x47, 0x80}, {0x87, 0x100}, {0x107, 0x200}, {0x207, 0x400}, + {0x407, 0x800}, {0x807, 0x1000}, {0x1007, 0x2000}, {0x2007, 0x4000}, {0x4007, 0x8000}, + {0x8007, 0x10000}, {0x10007, 0x20000}, {0x20007, 0x40000}, {0x40007, 0x80000}, {0x80007, 0x100000}, + {0x100007, 0x200000}, {0x200007, 0x400000}, {0x400007, 0x600000}}; + for (const AllocInfo & info : allocInfo) { + std::unique_ptr buf = std::make_unique(info.requested); + size_t usable_size = malloc_usable_size(buf.get()); + EXPECT_EQUAL(info.usable, usable_size); + } +} + +TEST("verify malloc_usable_size is sane") { + constexpr size_t SZ = 33; + std::unique_ptr buf = std::make_unique(SZ); + size_t usable_size = malloc_usable_size(buf.get()); + if (dlsym(RTLD_NEXT, "is_vespamallocd") != nullptr) { + // Debug variants will never have more memory available as there is pre/postamble for error detection. + EXPECT_EQUAL(SZ, usable_size); + } else if (dlsym(RTLD_NEXT, "is_vespamalloc") != nullptr) { + // Normal production vespamalloc will round up + EXPECT_EQUAL(64u, usable_size); + verify_vespamalloc_usable_size(); + } else { + // Non vespamalloc implementations we can not say anything about + EXPECT_GREATER_EQUAL(usable_size, SZ); + } +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespamalloc/src/vespamalloc/malloc/globalpool.h b/vespamalloc/src/vespamalloc/malloc/globalpool.h index bc13231bb85..872fd9b936e 100644 --- a/vespamalloc/src/vespamalloc/malloc/globalpool.h +++ b/vespamalloc/src/vespamalloc/malloc/globalpool.h @@ -28,6 +28,7 @@ public: void enableThreadSupport() __attribute__((noinline)); static void setParams(size_t alwaysReuseLimit, size_t threadCacheLimit); + static size_t computeExactSize(size_t sz); void info(FILE * os, size_t level=0) __attribute__((noinline)); private: diff --git a/vespamalloc/src/vespamalloc/malloc/globalpool.hpp b/vespamalloc/src/vespamalloc/malloc/globalpool.hpp index a3930c7cca1..69f2a2cf820 100644 --- a/vespamalloc/src/vespamalloc/malloc/globalpool.hpp +++ b/vespamalloc/src/vespamalloc/malloc/globalpool.hpp @@ -121,12 +121,18 @@ AllocPoolT::exchangeAlloc(SizeClassT sc, typename AllocPoolT +size_t +AllocPoolT::computeExactSize(size_t sz) { + return (((sz + (_alwaysReuseLimit - 1)) / _alwaysReuseLimit) * _alwaysReuseLimit); +} + template typename AllocPoolT::ChunkSList * AllocPoolT::exactAlloc(size_t exactSize, SizeClassT sc, typename AllocPoolT::ChunkSList * csl) { - size_t adjustedSize((( exactSize + (_alwaysReuseLimit - 1))/_alwaysReuseLimit)*_alwaysReuseLimit); + size_t adjustedSize = computeExactSize(exactSize); void *exactBlock = _dataSegment.getBlock(adjustedSize, sc); MemBlockPtrT mem(exactBlock, MemBlockPtrT::unAdjustSize(adjustedSize)); csl->add(mem); diff --git a/vespamalloc/src/vespamalloc/malloc/malloc.cpp b/vespamalloc/src/vespamalloc/malloc/malloc.cpp index 4a810c1ac5f..8efff973fa1 100644 --- a/vespamalloc/src/vespamalloc/malloc/malloc.cpp +++ b/vespamalloc/src/vespamalloc/malloc/malloc.cpp @@ -31,4 +31,11 @@ dumpInfo(size_t level) } +extern "C" { + +int is_vespamalloc() __attribute__((visibility ("default"))); +int is_vespamalloc() { return 1; } + +} + #include diff --git a/vespamalloc/src/vespamalloc/malloc/malloc.h b/vespamalloc/src/vespamalloc/malloc/malloc.h index 49a7b765cc8..51efe28eafc 100644 --- a/vespamalloc/src/vespamalloc/malloc/malloc.h +++ b/vespamalloc/src/vespamalloc/malloc/malloc.h @@ -39,6 +39,9 @@ public: } size_t getMinSizeForAlignment(size_t align, size_t sz) const { return MemBlockPtrT::getMinSizeForAlignment(align, sz); } size_t sizeClass(const void *ptr) const { return _segment.sizeClass(ptr); } + size_t usable_size(void *ptr) const { + return MemBlockPtrT::usable_size(ptr, _segment.getMaxSize(ptr)); + } void *calloc(size_t nelm, size_t esz) { void * ptr = malloc(nelm * esz); diff --git a/vespamalloc/src/vespamalloc/malloc/mallocd.cpp b/vespamalloc/src/vespamalloc/malloc/mallocd.cpp index 47c12b4f186..038715e4231 100644 --- a/vespamalloc/src/vespamalloc/malloc/mallocd.cpp +++ b/vespamalloc/src/vespamalloc/malloc/mallocd.cpp @@ -29,4 +29,11 @@ template void MemBlockBoundsCheckBaseT<20, 0>::dumpInfo(size_t); } +extern "C" { + +int is_vespamallocd() __attribute__((visibility ("default"))); +int is_vespamallocd() { return 1; } + +} + #include diff --git a/vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp b/vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp index 0946f51d75b..67d3869ed34 100644 --- a/vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp +++ b/vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp @@ -29,4 +29,10 @@ template void MemBlockBoundsCheckBaseT<20, 16>::dumpInfo(size_t); } +extern "C" { + +int is_vespamallocdst16() __attribute__((visibility ("default"))); +int is_vespamallocdst16() { return 1; } + +} #include diff --git a/vespamalloc/src/vespamalloc/malloc/mallocdst16_nl.cpp b/vespamalloc/src/vespamalloc/malloc/mallocdst16_nl.cpp index df009f3737b..e1bd28cac48 100644 --- a/vespamalloc/src/vespamalloc/malloc/mallocdst16_nl.cpp +++ b/vespamalloc/src/vespamalloc/malloc/mallocdst16_nl.cpp @@ -15,4 +15,11 @@ template void MemBlockBoundsCheckBaseT<20, 16>::dumpInfo(size_t); } +extern "C" { + +int is_vespamallocdst16_nl() __attribute__((visibility ("default"))); +int is_vespamallocdst16_nl() { return 1; } + +} + #include diff --git a/vespamalloc/src/vespamalloc/malloc/memblock.h b/vespamalloc/src/vespamalloc/malloc/memblock.h index 3f55e33b23e..8ad56921b37 100644 --- a/vespamalloc/src/vespamalloc/malloc/memblock.h +++ b/vespamalloc/src/vespamalloc/malloc/memblock.h @@ -34,6 +34,9 @@ public: void setThreadId(uint32_t ) { } void free() { } size_t size() const { return 0; } + static size_t usable_size(void *, size_t classSize) { + return classSize; + } bool allocated() const { return false; } uint32_t threadId() const { return 0; } void info(FILE *, unsigned level=0) const { (void) level; } diff --git a/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h b/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h index 90445666063..7ffac7c2108 100644 --- a/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h +++ b/vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h @@ -103,6 +103,9 @@ public: && ((p[3] == ALLOC_MAGIC) || (p[3] == FREE_MAGIC)) && *(reinterpret_cast ((const char*)_ptr + size() + alignment() + StackTraceLen*sizeof(void *))) == TAIL_MAGIC; } + static size_t usable_size(void *ptr, size_t ) { + return MemBlockBoundsCheckBaseT(ptr).size(); + } bool validAlloc1() const { unsigned *p((unsigned*)_ptr); return validCommon() && (p[3] == ALLOC_MAGIC); diff --git a/vespamalloc/src/vespamalloc/malloc/overload.h b/vespamalloc/src/vespamalloc/malloc/overload.h index ca3a76b705b..1ec37c37aa1 100644 --- a/vespamalloc/src/vespamalloc/malloc/overload.h +++ b/vespamalloc/src/vespamalloc/malloc/overload.h @@ -178,6 +178,11 @@ void free(void * ptr) { if (ptr) { vespamalloc::_GmemP->free(ptr); } } +size_t malloc_usable_size(void *) __THROW __attribute__((visibility ("default"))); +size_t malloc_usable_size (void * ptr) __THROW { + return (ptr) ? vespamalloc::_GmemP->usable_size(ptr) : 0; +} + #define ALIAS(x) __attribute__ ((weak, alias (x), visibility ("default"))) #ifdef __clang__ void* __libc_malloc(size_t sz) __THROW __attribute__((malloc, alloc_size(1))) ALIAS("malloc"); @@ -198,93 +203,9 @@ void __libc_free(void* ptr) __THROW __attribute__((leaf void __libc_cfree(void* ptr) __THROW __attribute__((leaf)) ALIAS("cfree"); #endif struct mallinfo __libc_mallinfo() __THROW ALIAS("mallinfo"); +size_t __libc_malloc_usable_size(void *ptr) __THROW ALIAS("malloc_usable_size"); void* __libc_memalign(size_t align, size_t s) __THROW __attribute__((leaf, malloc, alloc_size(2))) ALIAS("memalign"); int __posix_memalign(void** r, size_t a, size_t s) __THROW __nonnull((1)) ALIAS("posix_memalign"); #undef ALIAS -#if 0 -#include - -typedef void * (*dlopen_function) (const char *filename, int flag); - -extern "C" VESPA_DLL_EXPORT void * local_dlopen(const char *filename, int flag) __asm__("dlopen"); - -VESPA_DLL_EXPORT void * local_dlopen(const char *filename, int flag) -{ - // A pointer to the library version of dlopen. - static dlopen_function real_dlopen = nullptr; - - const char * dlopenName = "dlopen"; - - if (real_dlopen == nullptr) { - real_dlopen = (dlopen_function) dlsym (RTLD_NEXT, dlopenName); - if (real_dlopen == nullptr) { - fprintf (stderr, "Could not find the dlopen function!\n"); - abort(); - } - } - //flag = (flag & ~RTLD_DEEPBIND & ~RTLD_NOW) | RTLD_LAZY; - //fprintf(stderr, "modified dlopen('%s', %0x)\n", filename, flag); - void * handle = real_dlopen(filename, flag); - fprintf(stderr, "dlopen('%s', %0x) = %p\n", filename, flag, handle); - return handle; -} - -typedef int (*dlclose_function) (void * handle); -extern "C" VESPA_DLL_EXPORT int local_dlclose(void * handle) __asm__("dlclose"); -VESPA_DLL_EXPORT int local_dlclose(void * handle) -{ - // A pointer to the library version of dlclose. - static dlclose_function real_dlclose = nullptr; - - const char * dlcloseName = "dlclose"; - - if (real_dlclose == nullptr) { - real_dlclose = (dlclose_function) dlsym (RTLD_NEXT, dlcloseName); - if (real_dlclose == nullptr) { - fprintf (stderr, "Could not find the dlclose function!\n"); - abort(); - } - } - int retval = real_dlclose(handle); - fprintf(stderr, "dlclose(%p) = %d\n", handle, retval); - return retval; -} - -typedef void * (*dlsym_function) (void * handle, const char * symbol); -extern "C" VESPA_DLL_EXPORT void * local_dlsym(void * handle, const char * symbol) __asm__("dlsym"); -VESPA_DLL_EXPORT void * local_dlsym(void * handle, const char * symbol) -{ - // A pointer to the library version of dlsym. - static dlsym_function real_dlsym = nullptr; - - const char * dlsymName = "dlsym"; - - if (real_dlsym == nullptr) { - real_dlsym = (dlsym_function) dlvsym (RTLD_NEXT, dlsymName, "GLIBC_2.2.5"); - if (real_dlsym == nullptr) { - fprintf (stderr, "Could not find the dlsym function!\n"); - abort(); - } - } - if (handle == RTLD_NEXT) { - fprintf(stderr, "dlsym(RTLD_NEXT, %s)\n", symbol); - } else if (handle == RTLD_DEFAULT) { - fprintf(stderr, "dlsym(RTLD_DEFAULT, %s)\n", symbol); - } else { - fprintf(stderr, "dlsym(%p, %s)\n", handle, symbol); - } - void * retval = real_dlsym(handle, symbol); - if (handle == RTLD_NEXT) { - fprintf(stderr, "dlsym(RTLD_NEXT, %s) = %p\n", symbol, retval); - } else if (handle == RTLD_DEFAULT) { - fprintf(stderr, "dlsym(RTLD_DEFAULT, %s) = %p\n", symbol, retval); - } else { - fprintf(stderr, "dlsym(%p, %s) = %p\n", handle, symbol, retval); - } - return retval; -} - -#endif - } diff --git a/vespamalloc/src/vespamalloc/malloc/threadlist.h b/vespamalloc/src/vespamalloc/malloc/threadlist.h index 95ff072d035..9edf086ca96 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadlist.h +++ b/vespamalloc/src/vespamalloc/malloc/threadlist.h @@ -15,8 +15,8 @@ template class ThreadListT { public: - typedef ThreadPoolT ThreadPool; - typedef AllocPoolT AllocPool; + using ThreadPool = ThreadPoolT; + using AllocPool = AllocPoolT; ThreadListT(AllocPool & pool); ~ThreadListT(); void setParams(size_t alwayReuseLimit, size_t threadCacheLimit) { diff --git a/vespamalloc/src/vespamalloc/malloc/threadpool.h b/vespamalloc/src/vespamalloc/malloc/threadpool.h index 1846bbdab4d..d4a754532ff 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadpool.h +++ b/vespamalloc/src/vespamalloc/malloc/threadpool.h @@ -62,7 +62,7 @@ private: ChunkSList *_freeTo; }; void mallocHelper(size_t exactSize, SizeClassT sc, AllocFree & af, MemBlockPtrT & mem) __attribute__ ((noinline)); - bool alwaysReuse(SizeClassT sc) { return sc > _alwaysReuseSCLimit; } + static bool alwaysReuse(SizeClassT sc) { return sc > _alwaysReuseSCLimit; } AllocPool * _allocPool; AllocFree _memList[NUM_SIZE_CLASSES]; diff --git a/vespamalloc/src/vespamalloc/malloc/threadpool.hpp b/vespamalloc/src/vespamalloc/malloc/threadpool.hpp index 4b5277a6396..b28aa144c34 100644 --- a/vespamalloc/src/vespamalloc/malloc/threadpool.hpp +++ b/vespamalloc/src/vespamalloc/malloc/threadpool.hpp @@ -62,7 +62,7 @@ mallocHelper(size_t exactSize, af._allocFrom->sub(mem); PARANOID_CHECK2( if (!mem.ptr()) { *(int *)0 = 0; } ); } else { - if ( ! this->alwaysReuse(sc) ) { + if ( ! alwaysReuse(sc) ) { af._allocFrom = _allocPool->exchangeAlloc(sc, af._allocFrom); _stat[sc].incExchangeAlloc(); if (af._allocFrom) { @@ -93,9 +93,7 @@ ThreadPoolT::ThreadPoolT() : } template -ThreadPoolT::~ThreadPoolT() -{ -} +ThreadPoolT::~ThreadPoolT() = default; template void ThreadPoolT::malloc(size_t sz, MemBlockPtrT & mem) -- cgit v1.2.3