aboutsummaryrefslogtreecommitdiffstats
path: root/vespamalloc
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2021-06-29 10:38:12 +0200
committerGitHub <noreply@github.com>2021-06-29 10:38:12 +0200
commit905b03c0e30156c8fcd73998e9ce7fba3880aeba (patch)
treed6c26c40919e75d689be05799a9bcf4b9e12e3ee /vespamalloc
parente928ee61e47fe9c1cd15585df6dc553eaffa4370 (diff)
parent918e9f2ba0aa8ac4c1419873bd8dda1ad880b763 (diff)
Merge pull request #18438 from vespa-engine/balder/implement_malloc_usable_size
Implement _malloc_usable_size
Diffstat (limited to 'vespamalloc')
-rw-r--r--vespamalloc/src/tests/test1/new_test.cpp32
-rw-r--r--vespamalloc/src/vespamalloc/malloc/globalpool.h1
-rw-r--r--vespamalloc/src/vespamalloc/malloc/globalpool.hpp8
-rw-r--r--vespamalloc/src/vespamalloc/malloc/malloc.cpp7
-rw-r--r--vespamalloc/src/vespamalloc/malloc/malloc.h3
-rw-r--r--vespamalloc/src/vespamalloc/malloc/mallocd.cpp7
-rw-r--r--vespamalloc/src/vespamalloc/malloc/mallocdst16.cpp6
-rw-r--r--vespamalloc/src/vespamalloc/malloc/mallocdst16_nl.cpp7
-rw-r--r--vespamalloc/src/vespamalloc/malloc/memblock.h3
-rw-r--r--vespamalloc/src/vespamalloc/malloc/memblockboundscheck.h3
-rw-r--r--vespamalloc/src/vespamalloc/malloc/overload.h91
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadlist.h4
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadpool.h2
-rw-r--r--vespamalloc/src/vespamalloc/malloc/threadpool.hpp6
14 files changed, 87 insertions, 93 deletions
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 <vespa/vespalib/testkit/testapp.h>
#include <vespa/log/log.h>
+#include <malloc.h>
+#include <dlfcn.h>
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<char[]> buf = std::make_unique<char[]>(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<char[]> buf = std::make_unique<char[]>(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
@@ -122,11 +122,17 @@ AllocPoolT<MemBlockPtrT>::exchangeAlloc(SizeClassT sc, typename AllocPoolT<MemBl
}
template <typename MemBlockPtrT>
+size_t
+AllocPoolT<MemBlockPtrT>::computeExactSize(size_t sz) {
+ return (((sz + (_alwaysReuseLimit - 1)) / _alwaysReuseLimit) * _alwaysReuseLimit);
+}
+
+template <typename MemBlockPtrT>
typename AllocPoolT<MemBlockPtrT>::ChunkSList *
AllocPoolT<MemBlockPtrT>::exactAlloc(size_t exactSize, SizeClassT sc,
typename AllocPoolT<MemBlockPtrT>::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 <vespamalloc/malloc/overload.h>
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 <vespamalloc/malloc/overload.h>
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 <vespamalloc/malloc/overload.h>
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 <vespamalloc/malloc/overload.h>
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 unsigned *> ((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 <dlfcn.h>
-
-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 <typename MemBlockPtrT, typename ThreadStatT>
class ThreadListT
{
public:
- typedef ThreadPoolT<MemBlockPtrT, ThreadStatT > ThreadPool;
- typedef AllocPoolT<MemBlockPtrT> AllocPool;
+ using ThreadPool = ThreadPoolT<MemBlockPtrT, ThreadStatT >;
+ using AllocPool = AllocPoolT<MemBlockPtrT>;
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<MemBlockPtrT, ThreadStatT>::ThreadPoolT() :
}
template <typename MemBlockPtrT, typename ThreadStatT >
-ThreadPoolT<MemBlockPtrT, ThreadStatT>::~ThreadPoolT()
-{
-}
+ThreadPoolT<MemBlockPtrT, ThreadStatT>::~ThreadPoolT() = default;
template <typename MemBlockPtrT, typename ThreadStatT >
void ThreadPoolT<MemBlockPtrT, ThreadStatT>::malloc(size_t sz, MemBlockPtrT & mem)