2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 06:25:31 +00:00

fix: dev: Various cleanups related to the isc_mem unit

Merge branch 'ondrej/tidy-up-isc-mem-unit' into 'main'

See merge request isc-projects/bind9!10671
This commit is contained in:
Ondřej Surý
2025-06-30 13:22:53 +02:00
4 changed files with 15 additions and 178 deletions

View File

@@ -219,40 +219,6 @@ isc__mem_create(const char *name, isc_mem_t **_ISC_MEM_FLARG);
* mctxp != NULL && *mctxp == NULL */
/*@}*/
#define isc_mem_create_arena(name, cp) \
isc__mem_create_arena((name), (cp)_ISC_MEM_FILELINE)
void
isc__mem_create_arena(const char *name, isc_mem_t **_ISC_MEM_FLARG);
/*!<
* \brief Create a memory context that routs all its operations to a
* dedicated jemalloc arena (when available). When jemalloc is not
* available, the function is, effectively, an alias to
* isc_mem_create().
*
* Requires:
* mctxp != NULL && *mctxp == NULL */
/*@}*/
isc_result_t
isc_mem_arena_set_muzzy_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms);
isc_result_t
isc_mem_arena_set_dirty_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms);
/*!<
* \brief These two functions set the given parameters on the
* jemalloc arena associated with the memory context (if there is
* one). When jemalloc is not available, these are no-op.
*
* NOTE: The "muzzy_decay_ms" and "dirty_decay_ms" are the most common
* parameters to adjust when the defaults do not work well (per the
* official jemalloc tuning guide:
* https://github.com/jemalloc/jemalloc/blob/dev/TUNING.md).
*
* Requires:
* mctx - a valid memory context.
*/
/*@}*/
#if ISC_MEM_TRACE
#define isc_mem_ref(ptr) isc_mem__ref(ptr, __func__, __FILE__, __LINE__)
#define isc_mem_unref(ptr) isc_mem__unref(ptr, __func__, __FILE__, __LINE__)

View File

@@ -13,6 +13,8 @@
#pragma once
#include <stdbool.h>
#include <isc/util.h>
/*

View File

@@ -16,17 +16,21 @@
#if !defined(HAVE_JEMALLOC)
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <isc/overflow.h>
#include <isc/util.h>
const char *malloc_conf = NULL;
#define MALLOCX_ZERO ((int)0x40)
#define MALLOCX_TCACHE_NONE (0)
#define MALLOCX_ARENA(a) (0)
/*
* The MALLOCX_ZERO and MALLOCX_ZERO_GET macros were taken literal from
* jemalloc_macros.h and jemalloc_internal_types.h headers respectively.
*/
#include <stdlib.h>
#define MALLOCX_ZERO ((int)0x40)
#define MALLOCX_ZERO_GET(flags) ((bool)(flags & MALLOCX_ZERO))
typedef union {
size_t size;
@@ -44,7 +48,7 @@ mallocx(size_t size, int flags) {
si->size = size;
ptr = &si[1];
if ((flags & MALLOCX_ZERO) != 0) {
if (MALLOCX_ZERO_GET(flags)) {
memset(ptr, 0, size);
}
@@ -70,7 +74,7 @@ rallocx(void *ptr, size_t size, int flags) {
size_info *si = realloc(&(((size_info *)ptr)[-1]), size + sizeof(*si));
INSIST(si != NULL);
if ((flags & MALLOCX_ZERO) != 0 && size > si->size) {
if (MALLOCX_ZERO_GET(flags) && size > si->size) {
memset((uint8_t *)si + sizeof(*si) + si->size, 0,
size - si->size);
}

View File

@@ -64,8 +64,6 @@
unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
#define ISC_MEM_ILLEGAL_ARENA (UINT_MAX)
volatile void *isc__mem_malloc = mallocx;
/*
@@ -73,8 +71,6 @@ volatile void *isc__mem_malloc = mallocx;
*/
#define ZERO_ALLOCATION_SIZE sizeof(void *)
#define ALIGNMENT 8U /*%< must be a power of 2 */
#define ALIGNMENT_SIZE sizeof(size_info)
#define DEBUG_TABLE_COUNT 512U
/*
@@ -118,14 +114,12 @@ struct isc_mem {
unsigned int magic;
unsigned int flags;
unsigned int jemalloc_flags;
unsigned int jemalloc_arena;
unsigned int debugging;
isc_mutex_t lock;
bool checkfree;
isc_refcount_t references;
char *name;
atomic_size_t inuse;
atomic_bool hi_called;
atomic_bool is_overmem;
atomic_size_t hi_water;
atomic_size_t lo_water;
@@ -345,9 +339,9 @@ mem_realloc(isc_mem_t *ctx, void *old_ptr, size_t old_size, size_t new_size,
if ((flags & ISC__MEM_ZERO) == 0 &&
(ctx->flags & ISC_MEMFLAG_FILL) != 0)
{
ssize_t diff_size = new_size - old_size;
void *diff_ptr = (uint8_t *)new_ptr + old_size;
if (diff_size > 0) {
if (new_size > old_size) {
size_t diff_size = new_size - old_size;
void *diff_ptr = (uint8_t *)new_ptr + old_size;
/* Mnemonic for "beef". */
memset(diff_ptr, 0xbe, diff_size);
}
@@ -377,48 +371,6 @@ mem_putstats(isc_mem_t *ctx, size_t size) {
* Private.
*/
static bool
mem_jemalloc_arena_create(unsigned int *pnew_arenano) {
REQUIRE(pnew_arenano != NULL);
#ifdef JEMALLOC_API_SUPPORTED
unsigned int arenano = 0;
size_t len = sizeof(arenano);
int res = 0;
res = mallctl("arenas.create", &arenano, &len, NULL, 0);
if (res != 0) {
return false;
}
*pnew_arenano = arenano;
return true;
#else
*pnew_arenano = ISC_MEM_ILLEGAL_ARENA;
return true;
#endif /* JEMALLOC_API_SUPPORTED */
}
static bool
mem_jemalloc_arena_destroy(unsigned int arenano) {
#ifdef JEMALLOC_API_SUPPORTED
int res = 0;
char buf[256] = { 0 };
(void)snprintf(buf, sizeof(buf), "arena.%u.destroy", arenano);
res = mallctl(buf, NULL, NULL, NULL, 0);
if (res != 0) {
return false;
}
return true;
#else
UNUSED(arenano);
return true;
#endif /* JEMALLOC_API_SUPPORTED */
}
void
isc__mem_initialize(void) {
/*
@@ -465,7 +417,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
.debugging = debugging,
.flags = flags,
.jemalloc_flags = jemalloc_flags,
.jemalloc_arena = ISC_MEM_ILLEGAL_ARENA,
.checkfree = true,
.name = strdup(name),
};
@@ -476,7 +427,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
atomic_init(&ctx->inuse, 0);
atomic_init(&ctx->hi_water, 0);
atomic_init(&ctx->lo_water, 0);
atomic_init(&ctx->hi_called, false);
atomic_init(&ctx->is_overmem, false);
ISC_LIST_INIT(ctx->pools);
@@ -509,8 +459,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
static void
mem_destroy(isc_mem_t *ctx) {
unsigned int arena_no;
isc_refcount_destroy(&ctx->references);
LOCK(&contextslock);
@@ -519,8 +467,6 @@ mem_destroy(isc_mem_t *ctx) {
ctx->magic = 0;
arena_no = ctx->jemalloc_arena;
INSIST(ISC_LIST_EMPTY(ctx->pools));
#if ISC_MEM_TRACKLINES
@@ -552,10 +498,6 @@ mem_destroy(isc_mem_t *ctx) {
INSIST(atomic_load(&ctx->inuse) == 0);
}
sdallocx(ctx, sizeof(*ctx), ctx->jemalloc_flags);
if (arena_no != ISC_MEM_ILLEGAL_ARENA) {
RUNTIME_CHECK(mem_jemalloc_arena_destroy(arena_no) == true);
}
}
#if ISC_MEM_TRACE
@@ -1416,83 +1358,6 @@ isc__mem_create(const char *name, isc_mem_t **mctxp FLARG) {
#endif /* ISC_MEM_TRACKLINES */
}
void
isc__mem_create_arena(const char *name, isc_mem_t **mctxp FLARG) {
unsigned int arena_no = ISC_MEM_ILLEGAL_ARENA;
RUNTIME_CHECK(mem_jemalloc_arena_create(&arena_no));
/*
* We use MALLOCX_TCACHE_NONE to bypass the tcache and route
* allocations directly to the arena. That is a recommendation
* from jemalloc developers:
*
* https://github.com/jemalloc/jemalloc/issues/2483#issuecomment-1698173849
*/
mem_create(name, mctxp, isc_mem_debugging, isc_mem_defaultflags,
arena_no == ISC_MEM_ILLEGAL_ARENA
? 0
: MALLOCX_ARENA(arena_no) | MALLOCX_TCACHE_NONE);
(*mctxp)->jemalloc_arena = arena_no;
#if ISC_MEM_TRACKLINES
if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0) {
fprintf(stderr,
"create mctx %p func %s file %s line %u "
"for jemalloc arena %u\n",
*mctxp, func, file, line, arena_no);
}
#endif /* ISC_MEM_TRACKLINES */
}
#ifdef JEMALLOC_API_SUPPORTED
static bool
jemalloc_set_ssize_value(const char *valname, ssize_t newval) {
int ret;
ret = mallctl(valname, NULL, NULL, &newval, sizeof(newval));
return ret == 0;
}
#endif /* JEMALLOC_API_SUPPORTED */
static isc_result_t
mem_set_arena_ssize_value(isc_mem_t *mctx, const char *arena_valname,
const ssize_t newval) {
REQUIRE(VALID_CONTEXT(mctx));
#ifdef JEMALLOC_API_SUPPORTED
bool ret;
char buf[256] = { 0 };
if (mctx->jemalloc_arena == ISC_MEM_ILLEGAL_ARENA) {
return ISC_R_UNEXPECTED;
}
(void)snprintf(buf, sizeof(buf), "arena.%u.%s", mctx->jemalloc_arena,
arena_valname);
ret = jemalloc_set_ssize_value(buf, newval);
if (!ret) {
return ISC_R_FAILURE;
}
return ISC_R_SUCCESS;
#else
UNUSED(arena_valname);
UNUSED(newval);
return ISC_R_NOTIMPLEMENTED;
#endif
}
isc_result_t
isc_mem_arena_set_muzzy_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms) {
return mem_set_arena_ssize_value(mctx, "muzzy_decay_ms", decay_ms);
}
isc_result_t
isc_mem_arena_set_dirty_decay_ms(isc_mem_t *mctx, const ssize_t decay_ms) {
return mem_set_arena_ssize_value(mctx, "dirty_decay_ms", decay_ms);
}
void
isc__mem_printactive(isc_mem_t *ctx, FILE *file) {
#if ISC_MEM_TRACKLINES