Mallctl: Add experimental.hooks.[install|remove].
This commit is contained in:
parent
126e9a84a5
commit
bb071db92e
59
src/ctl.c
59
src/ctl.c
@ -202,6 +202,8 @@ CTL_PROTO(stats_metadata_thp)
|
||||
CTL_PROTO(stats_resident)
|
||||
CTL_PROTO(stats_mapped)
|
||||
CTL_PROTO(stats_retained)
|
||||
CTL_PROTO(experimental_hooks_install)
|
||||
CTL_PROTO(experimental_hooks_remove)
|
||||
|
||||
#define MUTEX_STATS_CTL_PROTO_GEN(n) \
|
||||
CTL_PROTO(stats_##n##_num_ops) \
|
||||
@ -536,6 +538,15 @@ static const ctl_named_node_t stats_node[] = {
|
||||
{NAME("arenas"), CHILD(indexed, stats_arenas)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t hooks_node[] = {
|
||||
{NAME("install"), CTL(experimental_hooks_install)},
|
||||
{NAME("remove"), CTL(experimental_hooks_remove)},
|
||||
};
|
||||
|
||||
static const ctl_named_node_t experimental_node[] = {
|
||||
{NAME("hooks"), CHILD(named, hooks)}
|
||||
};
|
||||
|
||||
static const ctl_named_node_t root_node[] = {
|
||||
{NAME("version"), CTL(version)},
|
||||
{NAME("epoch"), CTL(epoch)},
|
||||
@ -548,7 +559,8 @@ static const ctl_named_node_t root_node[] = {
|
||||
{NAME("arena"), CHILD(indexed, arena)},
|
||||
{NAME("arenas"), CHILD(named, arenas)},
|
||||
{NAME("prof"), CHILD(named, prof)},
|
||||
{NAME("stats"), CHILD(named, stats)}
|
||||
{NAME("stats"), CHILD(named, stats)},
|
||||
{NAME("experimental"), CHILD(named, experimental)}
|
||||
};
|
||||
static const ctl_named_node_t super_root_node[] = {
|
||||
{NAME(""), CHILD(named, root)}
|
||||
@ -2879,3 +2891,48 @@ label_return:
|
||||
malloc_mutex_unlock(tsdn, &ctl_mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_hooks_install_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
if (oldp == NULL || oldlenp == NULL|| newp == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
/*
|
||||
* Note: this is a *private* struct. This is an experimental interface;
|
||||
* forcing the user to know the jemalloc internals well enough to
|
||||
* extract the ABI hopefully ensures nobody gets too comfortable with
|
||||
* this API, which can change at a moment's notice.
|
||||
*/
|
||||
hooks_t hooks;
|
||||
WRITE(hooks, hooks_t);
|
||||
void *handle = hook_install(tsd_tsdn(tsd), &hooks);
|
||||
if (handle == NULL) {
|
||||
ret = EAGAIN;
|
||||
goto label_return;
|
||||
}
|
||||
READ(handle, void *);
|
||||
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
experimental_hooks_remove_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
|
||||
void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
|
||||
int ret;
|
||||
WRITEONLY();
|
||||
void *handle = NULL;
|
||||
WRITE(handle, void *);
|
||||
if (handle == NULL) {
|
||||
ret = EINVAL;
|
||||
goto label_return;
|
||||
}
|
||||
hook_remove(tsd_tsdn(tsd), handle);
|
||||
ret = 0;
|
||||
label_return:
|
||||
return ret;
|
||||
}
|
||||
|
@ -773,6 +773,43 @@ TEST_BEGIN(test_stats_arenas) {
|
||||
}
|
||||
TEST_END
|
||||
|
||||
static void
|
||||
alloc_hook(void *extra, UNUSED hook_alloc_t type, UNUSED void *result,
|
||||
UNUSED uintptr_t result_raw, UNUSED uintptr_t args_raw[3]) {
|
||||
*(bool *)extra = true;
|
||||
}
|
||||
|
||||
static void
|
||||
dalloc_hook(void *extra, UNUSED hook_dalloc_t type,
|
||||
UNUSED void *address, UNUSED uintptr_t args_raw[3]) {
|
||||
*(bool *)extra = true;
|
||||
}
|
||||
|
||||
TEST_BEGIN(test_hooks) {
|
||||
bool hook_called = false;
|
||||
hooks_t hooks = {&alloc_hook, &dalloc_hook, NULL, &hook_called};
|
||||
void *handle = NULL;
|
||||
size_t sz = sizeof(handle);
|
||||
int err = mallctl("experimental.hooks.install", &handle, &sz, &hooks,
|
||||
sizeof(hooks));
|
||||
assert_d_eq(err, 0, "Hook installation failed");
|
||||
assert_ptr_ne(handle, NULL, "Hook installation gave null handle");
|
||||
void *ptr = mallocx(1, 0);
|
||||
assert_true(hook_called, "Alloc hook not called");
|
||||
hook_called = false;
|
||||
free(ptr);
|
||||
assert_true(hook_called, "Free hook not called");
|
||||
|
||||
err = mallctl("experimental.hooks.remove", NULL, NULL, &handle,
|
||||
sizeof(handle));
|
||||
assert_d_eq(err, 0, "Hook removal failed");
|
||||
hook_called = false;
|
||||
ptr = mallocx(1, 0);
|
||||
free(ptr);
|
||||
assert_false(hook_called, "Hook called after removal");
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test(
|
||||
@ -801,5 +838,6 @@ main(void) {
|
||||
test_arenas_lextent_constants,
|
||||
test_arenas_create,
|
||||
test_arenas_lookup,
|
||||
test_stats_arenas);
|
||||
test_stats_arenas,
|
||||
test_hooks);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user