Split ctl handlers by mallctl namespace

Move mallctl handler implementations out of src/ctl.c into namespace-oriented ctl_* modules, while keeping the mallctl tree and dispatch machinery centralized in ctl.c.

Add shared ctl mallctl helper macros and thin ctl arena/stat interfaces needed by the split modules. Wire the new sources into Makefile.in and MSVC project files.

Keep behavior unchanged; this is intended as a readability and navigation refactor.
This commit is contained in:
Slobodan Predolac 2026-05-27 16:13:09 -07:00
parent 4e903a0a32
commit bcfc9b27cd
26 changed files with 3670 additions and 3468 deletions

View file

@ -115,7 +115,11 @@ bool ctl_boot(void);
void ctl_prefork(tsdn_t *tsdn);
void ctl_postfork_parent(tsdn_t *tsdn);
void ctl_postfork_child(tsdn_t *tsdn);
void ctl_mtx_lock(tsdn_t *tsdn);
void ctl_mtx_unlock(tsdn_t *tsdn);
void ctl_mtx_assert_held(tsdn_t *tsdn);
void ctl_mtx_prof_read(tsdn_t *tsdn, mutex_prof_data_t *mutex_prof_data);
void ctl_mtx_prof_data_reset(tsdn_t *tsdn);
#define xmallctl(name, oldp, oldlenp, newp, newlen) \
do { \

View file

@ -0,0 +1,18 @@
#ifndef JEMALLOC_INTERNAL_CTL_ARENA_H
#define JEMALLOC_INTERNAL_CTL_ARENA_H
#include "jemalloc/internal/arena.h"
#include "jemalloc/internal/ctl_mallctl.h"
bool ctl_arenas_init(tsd_t *tsd);
ctl_arena_t *ctl_arenas_refresh(tsdn_t *tsdn);
ctl_arena_t *ctl_arenas_i(size_t i);
uint64_t ctl_arenas_epoch_get(void);
void ctl_arenas_epoch_advance(void);
unsigned ctl_narenas_get(tsdn_t *tsdn);
bool ctl_arena_i_indexable(tsdn_t *tsdn, size_t i);
bool ctl_arenas_i_verify(size_t i, unsigned narenas);
int ctl_arena_create(tsd_t *tsd, void *oldp, size_t *oldlenp,
const arena_config_t *config);
#endif /* JEMALLOC_INTERNAL_CTL_ARENA_H */

View file

@ -0,0 +1,162 @@
#ifndef JEMALLOC_INTERNAL_CTL_MALLCTL_H
#define JEMALLOC_INTERNAL_CTL_MALLCTL_H
#include "jemalloc/internal/ctl.h"
/*
* Shared helpers for the mallctl handlers that the ctl_* namespace modules
* implement. These replace the former READ/WRITE/... macros with memcpy-based
* functions. Helpers used by more than one source file live here as
* static inline; helpers used by a single module are defined JET_EXTERN in that
* module instead (e.g. ctl_read_xor_write in ctl_thread.c).
*/
static inline int
ctl_writeonly(void *oldp, size_t *oldlenp) {
if (oldp != NULL || oldlenp != NULL) {
return EPERM;
}
return 0;
}
static inline int
ctl_assured_write(void *dst, size_t dst_size, const void *newp,
size_t newlen) {
if (newp == NULL || newlen != dst_size) {
return EINVAL;
}
memcpy(dst, newp, dst_size);
return 0;
}
static inline int
ctl_read(void *oldp, size_t *oldlenp, const void *src, size_t src_size) {
if (oldp == NULL || oldlenp == NULL) {
return 0;
}
const size_t oldlen = *oldlenp;
if (oldlen != src_size) {
size_t copylen = (src_size <= oldlen) ? src_size : oldlen;
memcpy(oldp, src, copylen);
*oldlenp = copylen;
return EINVAL;
}
memcpy(oldp, src, src_size);
return 0;
}
static inline int
ctl_write(void *dst, size_t dst_size, const void *newp, size_t newlen) {
if (newp == NULL) {
return 0;
}
if (newlen != dst_size) {
return EINVAL;
}
memcpy(dst, newp, dst_size);
return 0;
}
static inline int
ctl_readonly(const void *newp, size_t newlen) {
if (newp != NULL || newlen != 0) {
return EPERM;
}
return 0;
}
static inline int
ctl_neither_read_nor_write(void *oldp, size_t *oldlenp, const void *newp,
size_t newlen) {
if (oldp != NULL || oldlenp != NULL || newp != NULL || newlen != 0) {
return EPERM;
}
return 0;
}
static inline int
ctl_verify_read(void *oldp, size_t *oldlenp, size_t expected_size) {
if (oldp == NULL || oldlenp == NULL || *oldlenp != expected_size) {
if (oldlenp != NULL) {
*oldlenp = 0;
}
return EINVAL;
}
return 0;
}
static inline int
ctl_mib_unsigned(unsigned *dst, const size_t *mib, size_t mib_index) {
const size_t value = mib[mib_index];
if (value > UINT_MAX) {
return EFAULT;
}
*dst = (unsigned)value;
return 0;
}
/*
* Read-only handler generators for the split modules. These mirror the
* CTL_RO_* generators in ctl.c but emit externally linked handlers (referenced
* from the mallctl tree in ctl.c) and reach ctl_mtx through its accessors,
* since ctl_mtx itself is private to ctl.c.
*/
#define CTL_RO_GEN_PUBLIC(n, v, t) \
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
ctl_mtx_lock(tsd_tsdn(tsd)); \
int ret = ctl_readonly(newp, newlen); \
if (ret == 0) { \
t oldval = (v); \
ret = ctl_read(oldp, oldlenp, &oldval, sizeof(t)); \
} \
ctl_mtx_unlock(tsd_tsdn(tsd)); \
return ret; \
}
#define CTL_RO_CGEN_PUBLIC(c, n, v, t) \
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
if (!(c)) { \
return ENOENT; \
} \
ctl_mtx_lock(tsd_tsdn(tsd)); \
int ret = ctl_readonly(newp, newlen); \
if (ret == 0) { \
t oldval = (v); \
ret = ctl_read(oldp, oldlenp, &oldval, sizeof(t)); \
} \
ctl_mtx_unlock(tsd_tsdn(tsd)); \
return ret; \
}
/*
* ctl_mtx is not acquired, under the assumption that no pertinent data will
* mutate during the call.
*/
#define CTL_RO_NL_GEN_PUBLIC(n, v, t) \
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
int ret = ctl_readonly(newp, newlen); \
if (ret == 0) { \
t oldval = (v); \
ret = ctl_read(oldp, oldlenp, &oldval, sizeof(t)); \
} \
return ret; \
}
#define CTL_RO_NL_CGEN_PUBLIC(c, n, v, t) \
int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
if (!(c)) { \
return ENOENT; \
} \
int ret = ctl_readonly(newp, newlen); \
if (ret == 0) { \
t oldval = (v); \
ret = ctl_read(oldp, oldlenp, &oldval, sizeof(t)); \
} \
return ret; \
}
#endif /* JEMALLOC_INTERNAL_CTL_MALLCTL_H */

View file

@ -0,0 +1,9 @@
#ifndef JEMALLOC_INTERNAL_CTL_STATS_H
#define JEMALLOC_INTERNAL_CTL_STATS_H
#include "jemalloc/internal/ctl_mallctl.h"
bool ctl_stats_init(tsdn_t *tsdn);
void ctl_stats_refresh(tsdn_t *tsdn, ctl_arena_t *ctl_sarena);
#endif /* JEMALLOC_INTERNAL_CTL_STATS_H */

View file

@ -12,7 +12,7 @@
/*
* The following struct is for experimental purposes. See
* experimental_utilization_batch_query_ctl in src/ctl.c.
* experimental_utilization_batch_query_ctl in src/ctl_utilization.c.
*/
typedef struct inspect_extent_util_stats_s inspect_extent_util_stats_t;
struct inspect_extent_util_stats_s {