0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-24 17:38:54 +02:00

ircd::allocator: Distill out GNU malloc featurette from allocator.cc unit.

This commit is contained in:
Jason Volk 2019-07-03 17:27:58 -07:00
parent ea0a1df3a1
commit 6a6c51d359
4 changed files with 180 additions and 217 deletions

View file

@ -36,7 +36,7 @@ namespace ircd::allocator
profile operator+(const profile &, const profile &); profile operator+(const profile &, const profile &);
profile operator-(const profile &, const profile &); profile operator-(const profile &, const profile &);
bool trim(const size_t &pad = 0); // malloc_trim(3) bool trim(const size_t &pad = 0) noexcept; // malloc_trim(3)
string_view info(const mutable_buffer &); string_view info(const mutable_buffer &);
}; };
@ -111,6 +111,9 @@ struct ircd::allocator::scope
using realloc_closure = std::function<void *(void *const &ptr, const size_t &)>; using realloc_closure = std::function<void *(void *const &ptr, const size_t &)>;
using free_closure = std::function<void (void *const &ptr)>; using free_closure = std::function<void (void *const &ptr)>;
static void hook_init() noexcept;
static void hook_fini() noexcept;
static scope *current; static scope *current;
scope *theirs; scope *theirs;
alloc_closure user_alloc; alloc_closure user_alloc;

View file

@ -116,6 +116,7 @@ libircd_la_SOURCES =#
libircd_la_SOURCES += assert.cc libircd_la_SOURCES += assert.cc
libircd_la_SOURCES += info.cc libircd_la_SOURCES += info.cc
libircd_la_SOURCES += allocator.cc libircd_la_SOURCES += allocator.cc
libircd_la_SOURCES += allocator_gnu.cc
libircd_la_SOURCES += vg.cc libircd_la_SOURCES += vg.cc
libircd_la_SOURCES += exception.cc libircd_la_SOURCES += exception.cc
libircd_la_SOURCES += util.cc libircd_la_SOURCES += util.cc

View file

@ -8,8 +8,6 @@
// copyright notice and this permission notice is present in all copies. The // copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file. // full license for this software is available in the LICENSE file.
#include <RB_INC_MALLOC_H
// Uncomment or -D this #define to enable our own crude but simple ability to // Uncomment or -D this #define to enable our own crude but simple ability to
// profile dynamic memory usage. Global `new` and `delete` will be captured // profile dynamic memory usage. Global `new` and `delete` will be captured
// here by this definition file into thread_local counters accessible via // here by this definition file into thread_local counters accessible via
@ -18,54 +16,20 @@
// //
// #define RB_PROF_ALLOC // #define RB_PROF_ALLOC
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
ircd::string_view
ircd::allocator::info(const mutable_buffer &buf)
{
std::stringstream out;
pubsetbuf(out, buf);
const auto ma
{
::mallinfo()
};
char pbuf[96];
out << "arena: " << pretty(pbuf, iec(ma.arena)) << std::endl
<< "ordblks: " << ma.ordblks << std::endl
<< "smblks: " << ma.smblks << std::endl
<< "hblks: " << ma.hblks << std::endl
<< "hblkhd: " << pretty(pbuf, iec(ma.hblkhd)) << std::endl
<< "usmblks: " << pretty(pbuf, iec(ma.usmblks)) << std::endl
<< "fsmblks: " << pretty(pbuf, iec(ma.fsmblks)) << std::endl
<< "uordblks: " << pretty(pbuf, iec(ma.uordblks)) << std::endl
<< "fordblks: " << pretty(pbuf, iec(ma.fordblks)) << std::endl
<< "keepcost: " << pretty(pbuf, iec(ma.keepcost)) << std::endl
;
return view(out, buf);
}
#else
ircd::string_view ircd::string_view
__attribute__((weak))
ircd::allocator::info(const mutable_buffer &buf) ircd::allocator::info(const mutable_buffer &buf)
{ {
return {}; return {};
} }
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
bool
ircd::allocator::trim(const size_t &pad)
{
return malloc_trim(pad);
}
#else
bool bool
__attribute__((weak))
ircd::allocator::trim(const size_t &pad) ircd::allocator::trim(const size_t &pad)
noexcept
{ {
return false; return false;
} }
#endif
// //
// allocator::state // allocator::state
@ -155,24 +119,6 @@ const
// allocator::scope // allocator::scope
// //
namespace ircd::allocator
{
void *(*their_malloc_hook)(size_t, const void *);
static void *malloc_hook(size_t, const void *);
static void install_malloc_hook();
static void uninstall_malloc_hook();
void *(*their_realloc_hook)(void *, size_t, const void *);
static void *realloc_hook(void *, size_t, const void *);
static void install_realloc_hook();
static void uninstall_realloc_hook();
void (*their_free_hook)(void *, const void *);
static void free_hook(void *, const void *);
static void install_free_hook();
static void uninstall_free_hook();
}
decltype(ircd::allocator::scope::current) decltype(ircd::allocator::scope::current)
ircd::allocator::scope::current; ircd::allocator::scope::current;
@ -201,11 +147,7 @@ ircd::allocator::scope::scope(alloc_closure ac,
// our global hook handlers at the first instance ctor and // our global hook handlers at the first instance ctor and
// uninstall it after that first instance dtors. // uninstall it after that first instance dtors.
if(!current) if(!current)
{ hook_init();
install_malloc_hook();
install_realloc_hook();
install_free_hook();
}
current = this; current = this;
} }
@ -220,169 +162,22 @@ noexcept
// has destructed (the first to have constructed). We know this when // has destructed (the first to have constructed). We know this when
// current becomes null. // current becomes null.
if(!current) if(!current)
{ hook_fini();
uninstall_malloc_hook();
uninstall_realloc_hook();
uninstall_free_hook();
}
} }
void void
ircd::allocator::free_hook(void *const ptr, __attribute__((weak))
const void *const caller) ircd::allocator::scope::hook_init()
noexcept
{ {
// Once we've hooked we put back their hook before calling the user
// so they can passthru to the function without hooking themselves.
uninstall_free_hook();
const unwind rehook_ours
{
install_free_hook
};
assert(scope::current);
if(scope::current->user_free)
scope::current->user_free(ptr);
else
::free(ptr);
} }
void *
ircd::allocator::realloc_hook(void *const ptr,
size_t size,
const void *const caller)
{
// Once we've hooked we put back their hook before calling the user
// so they can passthru to the function without hooking themselves.
uninstall_realloc_hook();
const unwind rehook_ours
{
install_realloc_hook
};
assert(scope::current);
return scope::current->user_realloc?
scope::current->user_realloc(ptr, size):
::realloc(ptr, size);
}
void *
ircd::allocator::malloc_hook(size_t size,
const void *const caller)
{
// Once we've hooked we put back their hook before calling the user
// so they can passthru to the function without hooking themselves.
uninstall_malloc_hook();
const unwind rehook_ours
{
install_malloc_hook
};
assert(scope::current);
return scope::current->user_alloc?
scope::current->user_alloc(size):
::malloc(size);
}
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void void
ircd::allocator::install_malloc_hook() __attribute__((weak))
{ ircd::allocator::scope::hook_fini()
assert(!their_malloc_hook); noexcept
their_malloc_hook = __malloc_hook;
__malloc_hook = malloc_hook;
}
#pragma GCC diagnostic pop
#else
void
ircd::allocator::install_malloc_hook()
{ {
} }
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_malloc_hook()
{
__malloc_hook = their_malloc_hook;
}
#pragma GCC diagnostic pop
#else
void
ircd::allocator::uninstall_malloc_hook()
{
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::install_realloc_hook()
{
assert(!their_realloc_hook);
their_realloc_hook = __realloc_hook;
__realloc_hook = realloc_hook;
}
#pragma GCC diagnostic pop
#else
void
ircd::allocator::install_realloc_hook()
{
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_realloc_hook()
{
__realloc_hook = their_realloc_hook;
}
#else
void
ircd::allocator::uninstall_realloc_hook()
{
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::install_free_hook()
{
assert(!their_free_hook);
their_free_hook = __free_hook;
__free_hook = free_hook;
}
#pragma GCC diagnostic pop
#else
void
ircd::allocator::install_free_hook()
{
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_free_hook()
{
__free_hook = their_free_hook;
}
#pragma GCC diagnostic pop
#else
void
ircd::allocator::uninstall_free_hook()
{
}
#endif
// //
// allocator::profile // allocator::profile

164
ircd/allocator_gnu.cc Normal file
View file

@ -0,0 +1,164 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#include <RB_INC_MALLOC_H
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H) && defined(IRCD_ALLOCATOR_USE_DEFAULT)
#define IRCD_ALLOCATOR_USE_GNU
#endif
namespace ircd::allocator
{
void *(*their_malloc_hook)(size_t, const void *);
static void *malloc_hook(size_t, const void *);
static void install_malloc_hook();
static void uninstall_malloc_hook();
void *(*their_realloc_hook)(void *, size_t, const void *);
static void *realloc_hook(void *, size_t, const void *);
static void install_realloc_hook();
static void uninstall_realloc_hook();
void (*their_free_hook)(void *, const void *);
static void free_hook(void *, const void *);
static void install_free_hook();
static void uninstall_free_hook();
}
#ifdef IRCD_ALLOCATOR_USE_GNU
ircd::string_view
ircd::allocator::info(const mutable_buffer &buf)
{
std::stringstream out;
pubsetbuf(out, buf);
const auto ma
{
::mallinfo()
};
char pbuf[96];
out << "arena: " << pretty(pbuf, iec(ma.arena)) << std::endl
<< "ordblks: " << ma.ordblks << std::endl
<< "smblks: " << ma.smblks << std::endl
<< "hblks: " << ma.hblks << std::endl
<< "hblkhd: " << pretty(pbuf, iec(ma.hblkhd)) << std::endl
<< "usmblks: " << pretty(pbuf, iec(ma.usmblks)) << std::endl
<< "fsmblks: " << pretty(pbuf, iec(ma.fsmblks)) << std::endl
<< "uordblks: " << pretty(pbuf, iec(ma.uordblks)) << std::endl
<< "fordblks: " << pretty(pbuf, iec(ma.fordblks)) << std::endl
<< "keepcost: " << pretty(pbuf, iec(ma.keepcost)) << std::endl
;
return view(out, buf);
}
#endif
#ifdef IRCD_ALLOCATOR_USE_GNU
bool
ircd::allocator::trim(const size_t &pad)
noexcept
{
return malloc_trim(pad);
}
#endif
#ifdef IRCD_ALLOCATOR_USE_GNU
void
ircd::allocator::scope::hook_init()
noexcept
{
install_malloc_hook();
install_realloc_hook();
install_free_hook();
}
#endif
#ifdef IRCD_ALLOCATOR_USE_GNU
void
ircd::allocator::scope::hook_fini()
noexcept
{
uninstall_malloc_hook();
uninstall_realloc_hook();
uninstall_free_hook();
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::install_malloc_hook()
{
assert(!their_malloc_hook);
their_malloc_hook = __malloc_hook;
__malloc_hook = malloc_hook;
}
#pragma GCC diagnostic pop
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_malloc_hook()
{
__malloc_hook = their_malloc_hook;
}
#pragma GCC diagnostic pop
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::install_realloc_hook()
{
assert(!their_realloc_hook);
their_realloc_hook = __realloc_hook;
__realloc_hook = realloc_hook;
}
#pragma GCC diagnostic pop
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_realloc_hook()
{
__realloc_hook = their_realloc_hook;
}
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::install_free_hook()
{
assert(!their_free_hook);
their_free_hook = __free_hook;
__free_hook = free_hook;
}
#pragma GCC diagnostic pop
#endif
#if defined(__GNU_LIBRARY__) && defined(HAVE_MALLOC_H)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
void
ircd::allocator::uninstall_free_hook()
{
__free_hook = their_free_hook;
}
#pragma GCC diagnostic pop
#endif