From b8e75ae6fe7659ac98d488de3c138f7c9dcacd46 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Thu, 7 Dec 2023 14:10:51 +0100 Subject: [PATCH] Add mallinfo2 function --- CMakeLists.txt | 7 +++++++ Makefile.am | 2 +- cmake/config.h.in | 3 +++ cmake/tcmalloc.h.in | 5 ++++- configure.ac | 7 +++++++ src/debugallocation.cc | 10 +++++++-- src/gperftools/tcmalloc.h.in | 5 ++++- src/libc_override_aix.h | 3 +++ src/libc_override_gcc_and_weak.h | 3 +++ src/libc_override_redefine.h | 3 +++ src/tcmalloc.cc | 36 ++++++++++++++++++++++++++++++++ src/windows/config.h | 3 +++ 12 files changed, 82 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed6165a..6c50708 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -168,6 +168,7 @@ check_c_source_compiles("#include set(CMAKE_EXTRA_INCLUDE_FILES "malloc.h") check_type_size("struct mallinfo" STRUCT_MALLINFO LANGUAGE CXX) +check_type_size("struct mallinfo2" STRUCT_MALLINFO2 LANGUAGE CXX) set(CMAKE_EXTRA_INCLUDE_FILES "elf.h") check_type_size("Elf32_Versym" ELF32_VERSYM LANGUAGE CXX) # for vdso_support.h set(CMAKE_EXTRA_INCLUDE_FILES) @@ -214,6 +215,12 @@ else() set(HAVE_STRUCT_MALLINFO 0) endif() +if(HAVE_STRUCT_MALLINFO2) + set(HAVE_STRUCT_MALLINFO2 1) +else() + set(HAVE_STRUCT_MALLINFO2 0) +endif() + # We hardcode HAVE_MMAP to 1. There are no interesting systems anymore # without functional mmap. And our windows (except mingw) builds # aren't using autoconf. So we keep HAVE_MMAP define, but only to diff --git a/Makefile.am b/Makefile.am index f66e9bf..238e8be 100644 --- a/Makefile.am +++ b/Makefile.am @@ -68,7 +68,7 @@ if HAVE_OBJCOPY_WEAKEN WEAKEN = $(OBJCOPY) -W malloc -W free -W realloc -W calloc -W cfree \ -W memalign -W posix_memalign -W valloc -W pvalloc \ -W aligned_alloc \ - -W malloc_stats -W mallopt -W mallinfo -W nallocx \ + -W malloc_stats -W mallopt -W mallinfo -W mallinfo2 -W nallocx \ -W _Znwm -W _ZnwmRKSt9nothrow_t -W _Znam -W _ZnamRKSt9nothrow_t \ -W _ZdlPv -W _ZdaPv \ -W __Znwm -W __ZnwmRKSt9nothrow_t -W __Znam -W __ZnamRKSt9nothrow_t \ diff --git a/cmake/config.h.in b/cmake/config.h.in index 4bdbbb4..9c6a206 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -128,6 +128,9 @@ /* Define to 1 if the system has the type `struct mallinfo'. */ #cmakedefine HAVE_STRUCT_MALLINFO +/* Define to 1 if the system has the type `struct mallinfo2'. */ +#cmakedefine HAVE_STRUCT_MALLINFO2 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_SYS_CDEFS_H diff --git a/cmake/tcmalloc.h.in b/cmake/tcmalloc.h.in index 1d265a0..5eab3dd 100644 --- a/cmake/tcmalloc.h.in +++ b/cmake/tcmalloc.h.in @@ -48,7 +48,7 @@ #define TC_VERSION_STRING "gperftools @PROJECT_VERSION@" /* For struct mallinfo, if it's defined. */ -#if @HAVE_STRUCT_MALLINFO@ +#if @HAVE_STRUCT_MALLINFO@ || @HAVE_STRUCT_MALLINFO2@ # include #endif @@ -107,6 +107,9 @@ extern "C" { #if @HAVE_STRUCT_MALLINFO@ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW; #endif +#if @HAVE_STRUCT_MALLINFO2@ + PERFTOOLS_DLL_DECL struct mallinfo2 tc_mallinfo2(void) PERFTOOLS_NOTHROW; +#endif /* * This is an alias for MallocExtension::instance()->GetAllocatedSize(). diff --git a/configure.ac b/configure.ac index d464757..3d2e5d9 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,7 @@ AC_MSG_RESULT($ac_cv___attribute__aligned_fn) # TODO(csilvers): we could remove a lot when WITH_CPU_PROFILER etc is "no". AC_CHECK_TYPES([struct mallinfo],,, [#include ]) +AC_CHECK_TYPES([struct mallinfo2],,, [#include ]) AC_CHECK_TYPES([Elf32_Versym],,, [#include ]) # for vdso_support.h AC_CHECK_FUNCS(sbrk) # for tcmalloc to get memory AC_CHECK_FUNCS(__sbrk) # for tcmalloc to get memory @@ -297,6 +298,12 @@ else AC_SUBST(ac_cv_have_struct_mallinfo, 0) fi +if test "$ac_cv_type_struct_mallinfo2" = yes; then + AC_SUBST(ac_cv_have_struct_mallinfo2, 1) # gperftools/tcmalloc.h needs this +else + AC_SUBST(ac_cv_have_struct_mallinfo2, 0) +fi + # We hardcode HAVE_MMAP to 1. There are no interesting systems anymore # without functional mmap. And our windows (except mingw) builds # aren't using autoconf. So we keep HAVE_MMAP define, but only to diff --git a/src/debugallocation.cc b/src/debugallocation.cc index b48c11d..a1126bf 100644 --- a/src/debugallocation.cc +++ b/src/debugallocation.cc @@ -37,8 +37,8 @@ #include #endif #include -// We only need malloc.h for struct mallinfo. -#ifdef HAVE_STRUCT_MALLINFO +// We only need malloc.h for structs mallinfo and mallinfo2. +#if defined(HAVE_STRUCT_MALLINFO) || defined(HAVE_STRUCT_MALLINFO2) // Malloc can be in several places on older versions of OS X. # if defined(HAVE_MALLOC_H) # include @@ -1577,6 +1577,12 @@ extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHRO } #endif +#ifdef HAVE_STRUCT_MALLINFO2 +extern "C" PERFTOOLS_DLL_DECL struct mallinfo2 tc_mallinfo2(void) PERFTOOLS_NOTHROW { + return do_mallinfo2(); +} +#endif + extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW { return MallocExtension::instance()->GetAllocatedSize(ptr); } diff --git a/src/gperftools/tcmalloc.h.in b/src/gperftools/tcmalloc.h.in index 0c8a3dd..dbbf821 100644 --- a/src/gperftools/tcmalloc.h.in +++ b/src/gperftools/tcmalloc.h.in @@ -48,7 +48,7 @@ #define TC_VERSION_STRING "gperftools @TC_VERSION_MAJOR@.@TC_VERSION_MINOR@@TC_VERSION_PATCH@" /* For struct mallinfo, if it's defined. */ -#if @ac_cv_have_struct_mallinfo@ +#if @ac_cv_have_struct_mallinfo@ || @ac_cv_have_struct_mallinfo2@ # include #endif @@ -107,6 +107,9 @@ extern "C" { #if @ac_cv_have_struct_mallinfo@ PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW; #endif +#if @ac_cv_have_struct_mallinfo2@ + PERFTOOLS_DLL_DECL struct mallinfo2 tc_mallinfo2(void) PERFTOOLS_NOTHROW; +#endif /* * This is an alias for MallocExtension::instance()->GetAllocatedSize(). diff --git a/src/libc_override_aix.h b/src/libc_override_aix.h index c84ca38..93e3467 100644 --- a/src/libc_override_aix.h +++ b/src/libc_override_aix.h @@ -50,6 +50,9 @@ extern "C" { int __mallopt__(int cmd, int value) __THROW ALIAS(tc_mallopt); #ifdef HAVE_STRUCT_MALLINFO struct mallinfo __mallinfo__(void) __THROW ALIAS(tc_mallinfo); +#endif +#ifdef HAVE_STRUCT_MALLINFO2 + struct mallinfo2 __mallinfo2__(void) __THROW ALIAS(tc_mallinfo2); #endif void __malloc_init__(void) { tc_free(tc_malloc(1));} void* __malloc_prefork_lock__(void) { /* nothing to lock */ } diff --git a/src/libc_override_gcc_and_weak.h b/src/libc_override_gcc_and_weak.h index 80ac4b7..87cea6f 100644 --- a/src/libc_override_gcc_and_weak.h +++ b/src/libc_override_gcc_and_weak.h @@ -234,6 +234,9 @@ extern "C" { #endif #ifdef HAVE_STRUCT_MALLINFO struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo); +#endif +#ifdef HAVE_STRUCT_MALLINFO2 + struct mallinfo2 mallinfo2(void) __THROW ALIAS(tc_mallinfo2); #endif size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size); #if defined(__ANDROID__) diff --git a/src/libc_override_redefine.h b/src/libc_override_redefine.h index 4d61b25..f2fab40 100644 --- a/src/libc_override_redefine.h +++ b/src/libc_override_redefine.h @@ -119,6 +119,9 @@ extern "C" { int mallopt(int cmd, int v) { return tc_mallopt(cmd, v); } #ifdef HAVE_STRUCT_MALLINFO struct mallinfo mallinfo(void) { return tc_mallinfo(); } +#endif +#ifdef HAVE_STRUCT_MALLINFO2 + struct mallinfo2 mallinfo2(void) { return tc_mallinfo2(); } #endif size_t malloc_size(void* p) { return tc_malloc_size(p); } size_t malloc_usable_size(void* p) { return tc_malloc_size(p); } diff --git a/src/tcmalloc.cc b/src/tcmalloc.cc index 47c6a61..fd5284a 100644 --- a/src/tcmalloc.cc +++ b/src/tcmalloc.cc @@ -217,6 +217,10 @@ extern "C" { struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHROW ATTRIBUTE_SECTION(google_malloc); #endif +#ifdef HAVE_STRUCT_MALLINFO2 + struct mallinfo2 tc_mallinfo2(void) PERFTOOLS_NOTHROW + ATTRIBUTE_SECTION(google_malloc); +#endif void* tc_new(size_t size) ATTRIBUTE_SECTION(google_malloc); @@ -1697,6 +1701,32 @@ inline struct mallinfo do_mallinfo() { } #endif // HAVE_STRUCT_MALLINFO +#ifdef HAVE_STRUCT_MALLINFO2 +inline struct mallinfo2 do_mallinfo2() { + TCMallocStats stats; + ExtractStats(&stats, NULL, NULL, NULL); + + // Just some of the fields are filled in. + struct mallinfo2 info; + memset(&info, 0, sizeof(info)); + + info.arena = static_cast(stats.pageheap.system_bytes); + info.fsmblks = static_cast(stats.thread_bytes + + stats.central_bytes + + stats.transfer_bytes); + info.fordblks = static_cast(stats.pageheap.free_bytes + + stats.pageheap.unmapped_bytes); + info.uordblks = static_cast(stats.pageheap.system_bytes + - stats.thread_bytes + - stats.central_bytes + - stats.transfer_bytes + - stats.pageheap.free_bytes + - stats.pageheap.unmapped_bytes); + + return info; +} +#endif // HAVE_STRUCT_MALLINFO2 + } // end unnamed namespace // As promised, the definition of this function, declared above. @@ -2215,6 +2245,12 @@ extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) PERFTOOLS_NOTHRO } #endif +#ifdef HAVE_STRUCT_MALLINFO2 +extern "C" PERFTOOLS_DLL_DECL struct mallinfo2 tc_mallinfo2(void) PERFTOOLS_NOTHROW { + return do_mallinfo2(); +} +#endif + extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) PERFTOOLS_NOTHROW { return MallocExtension::instance()->GetAllocatedSize(ptr); } diff --git a/src/windows/config.h b/src/windows/config.h index 96cd35f..b0d85c4 100644 --- a/src/windows/config.h +++ b/src/windows/config.h @@ -145,6 +145,9 @@ /* Define to 1 if the system has the type `struct mallinfo'. */ /* #undef HAVE_STRUCT_MALLINFO */ +/* Define to 1 if the system has the type `struct mallinfo2'. */ +/* #undef HAVE_STRUCT_MALLINFO2 */ + /* Define to 1 if you have the header file. */ /* #undef HAVE_SYS_CDEFS_H */