mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 23:25:38 +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:
@@ -219,40 +219,6 @@ isc__mem_create(const char *name, isc_mem_t **_ISC_MEM_FLARG);
|
|||||||
* mctxp != NULL && *mctxp == NULL */
|
* 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
|
#if ISC_MEM_TRACE
|
||||||
#define isc_mem_ref(ptr) isc_mem__ref(ptr, __func__, __FILE__, __LINE__)
|
#define isc_mem_ref(ptr) isc_mem__ref(ptr, __func__, __FILE__, __LINE__)
|
||||||
#define isc_mem_unref(ptr) isc_mem__unref(ptr, __func__, __FILE__, __LINE__)
|
#define isc_mem_unref(ptr) isc_mem__unref(ptr, __func__, __FILE__, __LINE__)
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -16,17 +16,21 @@
|
|||||||
#if !defined(HAVE_JEMALLOC)
|
#if !defined(HAVE_JEMALLOC)
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <isc/overflow.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
const char *malloc_conf = NULL;
|
const char *malloc_conf = NULL;
|
||||||
|
|
||||||
#define MALLOCX_ZERO ((int)0x40)
|
/*
|
||||||
#define MALLOCX_TCACHE_NONE (0)
|
* The MALLOCX_ZERO and MALLOCX_ZERO_GET macros were taken literal from
|
||||||
#define MALLOCX_ARENA(a) (0)
|
* 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 {
|
typedef union {
|
||||||
size_t size;
|
size_t size;
|
||||||
@@ -44,7 +48,7 @@ mallocx(size_t size, int flags) {
|
|||||||
si->size = size;
|
si->size = size;
|
||||||
ptr = &si[1];
|
ptr = &si[1];
|
||||||
|
|
||||||
if ((flags & MALLOCX_ZERO) != 0) {
|
if (MALLOCX_ZERO_GET(flags)) {
|
||||||
memset(ptr, 0, size);
|
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));
|
size_info *si = realloc(&(((size_info *)ptr)[-1]), size + sizeof(*si));
|
||||||
INSIST(si != NULL);
|
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,
|
memset((uint8_t *)si + sizeof(*si) + si->size, 0,
|
||||||
size - si->size);
|
size - si->size);
|
||||||
}
|
}
|
||||||
|
139
lib/isc/mem.c
139
lib/isc/mem.c
@@ -64,8 +64,6 @@
|
|||||||
unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
|
unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
|
||||||
unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
|
unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
|
||||||
|
|
||||||
#define ISC_MEM_ILLEGAL_ARENA (UINT_MAX)
|
|
||||||
|
|
||||||
volatile void *isc__mem_malloc = mallocx;
|
volatile void *isc__mem_malloc = mallocx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -73,8 +71,6 @@ volatile void *isc__mem_malloc = mallocx;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ZERO_ALLOCATION_SIZE sizeof(void *)
|
#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
|
#define DEBUG_TABLE_COUNT 512U
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -118,14 +114,12 @@ struct isc_mem {
|
|||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int jemalloc_flags;
|
unsigned int jemalloc_flags;
|
||||||
unsigned int jemalloc_arena;
|
|
||||||
unsigned int debugging;
|
unsigned int debugging;
|
||||||
isc_mutex_t lock;
|
isc_mutex_t lock;
|
||||||
bool checkfree;
|
bool checkfree;
|
||||||
isc_refcount_t references;
|
isc_refcount_t references;
|
||||||
char *name;
|
char *name;
|
||||||
atomic_size_t inuse;
|
atomic_size_t inuse;
|
||||||
atomic_bool hi_called;
|
|
||||||
atomic_bool is_overmem;
|
atomic_bool is_overmem;
|
||||||
atomic_size_t hi_water;
|
atomic_size_t hi_water;
|
||||||
atomic_size_t lo_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 &&
|
if ((flags & ISC__MEM_ZERO) == 0 &&
|
||||||
(ctx->flags & ISC_MEMFLAG_FILL) != 0)
|
(ctx->flags & ISC_MEMFLAG_FILL) != 0)
|
||||||
{
|
{
|
||||||
ssize_t diff_size = new_size - old_size;
|
if (new_size > old_size) {
|
||||||
|
size_t diff_size = new_size - old_size;
|
||||||
void *diff_ptr = (uint8_t *)new_ptr + old_size;
|
void *diff_ptr = (uint8_t *)new_ptr + old_size;
|
||||||
if (diff_size > 0) {
|
|
||||||
/* Mnemonic for "beef". */
|
/* Mnemonic for "beef". */
|
||||||
memset(diff_ptr, 0xbe, diff_size);
|
memset(diff_ptr, 0xbe, diff_size);
|
||||||
}
|
}
|
||||||
@@ -377,48 +371,6 @@ mem_putstats(isc_mem_t *ctx, size_t size) {
|
|||||||
* Private.
|
* 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
|
void
|
||||||
isc__mem_initialize(void) {
|
isc__mem_initialize(void) {
|
||||||
/*
|
/*
|
||||||
@@ -465,7 +417,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
|
|||||||
.debugging = debugging,
|
.debugging = debugging,
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
.jemalloc_flags = jemalloc_flags,
|
.jemalloc_flags = jemalloc_flags,
|
||||||
.jemalloc_arena = ISC_MEM_ILLEGAL_ARENA,
|
|
||||||
.checkfree = true,
|
.checkfree = true,
|
||||||
.name = strdup(name),
|
.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->inuse, 0);
|
||||||
atomic_init(&ctx->hi_water, 0);
|
atomic_init(&ctx->hi_water, 0);
|
||||||
atomic_init(&ctx->lo_water, 0);
|
atomic_init(&ctx->lo_water, 0);
|
||||||
atomic_init(&ctx->hi_called, false);
|
|
||||||
atomic_init(&ctx->is_overmem, false);
|
atomic_init(&ctx->is_overmem, false);
|
||||||
|
|
||||||
ISC_LIST_INIT(ctx->pools);
|
ISC_LIST_INIT(ctx->pools);
|
||||||
@@ -509,8 +459,6 @@ mem_create(const char *name, isc_mem_t **ctxp, unsigned int debugging,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
mem_destroy(isc_mem_t *ctx) {
|
mem_destroy(isc_mem_t *ctx) {
|
||||||
unsigned int arena_no;
|
|
||||||
|
|
||||||
isc_refcount_destroy(&ctx->references);
|
isc_refcount_destroy(&ctx->references);
|
||||||
|
|
||||||
LOCK(&contextslock);
|
LOCK(&contextslock);
|
||||||
@@ -519,8 +467,6 @@ mem_destroy(isc_mem_t *ctx) {
|
|||||||
|
|
||||||
ctx->magic = 0;
|
ctx->magic = 0;
|
||||||
|
|
||||||
arena_no = ctx->jemalloc_arena;
|
|
||||||
|
|
||||||
INSIST(ISC_LIST_EMPTY(ctx->pools));
|
INSIST(ISC_LIST_EMPTY(ctx->pools));
|
||||||
|
|
||||||
#if ISC_MEM_TRACKLINES
|
#if ISC_MEM_TRACKLINES
|
||||||
@@ -552,10 +498,6 @@ mem_destroy(isc_mem_t *ctx) {
|
|||||||
INSIST(atomic_load(&ctx->inuse) == 0);
|
INSIST(atomic_load(&ctx->inuse) == 0);
|
||||||
}
|
}
|
||||||
sdallocx(ctx, sizeof(*ctx), ctx->jemalloc_flags);
|
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
|
#if ISC_MEM_TRACE
|
||||||
@@ -1416,83 +1358,6 @@ isc__mem_create(const char *name, isc_mem_t **mctxp FLARG) {
|
|||||||
#endif /* ISC_MEM_TRACKLINES */
|
#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
|
void
|
||||||
isc__mem_printactive(isc_mem_t *ctx, FILE *file) {
|
isc__mem_printactive(isc_mem_t *ctx, FILE *file) {
|
||||||
#if ISC_MEM_TRACKLINES
|
#if ISC_MEM_TRACKLINES
|
||||||
|
Reference in New Issue
Block a user