mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-18 14:47:18 +03:00
test: handle profiled xallocx no-grow in extent test
With profiling active, xallocx may decline to grow an allocation that is not page-aligned. The profiling path can require sampled xallocx growth to use page-aligned pointers; otherwise it can return the old usable size without committing the purged tail. Observed on Darwin, where decommit/commit are real VM state changes. The shrink/purge half succeeds and records a decommit, then the profiling-limited grow skips the matching commit. This is not Darwin-specific. Linux no-overcommit should expose the same mismatch. Usual Linux overcommit behavior papers it over by making commit/decommit hooks report unsupported, so both sides of the old equality check stay false. Relax the default-path assertion only while profiling is active, and add a page-aligned case that still requires xallocx shrink and grow to succeed, preserving commit/merge coverage. Assisted-by: Codex gpt-5.5 xhigh
This commit is contained in:
parent
fb5499aa9c
commit
7029edec97
1 changed files with 66 additions and 27 deletions
|
|
@ -4,6 +4,57 @@
|
|||
|
||||
#include "jemalloc/internal/arena.h"
|
||||
|
||||
static void
|
||||
test_decommit_commit(unsigned arena_ind, int flags, size_t large0,
|
||||
size_t *purge_mib, size_t purge_miblen, bool expect_xallocx_success) {
|
||||
void *p;
|
||||
bool xallocx_success_b, xallocx_success_c;
|
||||
|
||||
try_dalloc = false;
|
||||
try_decommit = true;
|
||||
p = mallocx(large0 * 2, flags);
|
||||
expect_ptr_not_null(p, "Unexpected mallocx() error");
|
||||
did_decommit = false;
|
||||
did_commit = false;
|
||||
called_split = false;
|
||||
did_split = false;
|
||||
did_merge = false;
|
||||
xallocx_success_b = (xallocx(p, large0, 0, flags) == large0);
|
||||
expect_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
|
||||
0, "Unexpected arena.%u.purge error", arena_ind);
|
||||
if (xallocx_success_b) {
|
||||
expect_true(did_split, "Expected split");
|
||||
}
|
||||
xallocx_success_c = (xallocx(p, large0 * 2, 0, flags) == large0 * 2);
|
||||
if (expect_xallocx_success) {
|
||||
expect_true(xallocx_success_b, "Expected xallocx shrink");
|
||||
expect_true(xallocx_success_c, "Expected xallocx grow");
|
||||
}
|
||||
if (did_split && xallocx_success_c) {
|
||||
expect_b_eq(
|
||||
did_decommit, did_commit, "Expected decommit/commit match");
|
||||
}
|
||||
if (xallocx_success_b && xallocx_success_c) {
|
||||
expect_true(did_merge, "Expected merge");
|
||||
}
|
||||
dallocx(p, flags);
|
||||
try_dalloc = true;
|
||||
try_decommit = false;
|
||||
}
|
||||
|
||||
static bool
|
||||
prof_active_enabled(void) {
|
||||
bool active = false;
|
||||
size_t sz = sizeof(active);
|
||||
|
||||
if (!config_prof) {
|
||||
return false;
|
||||
}
|
||||
expect_d_eq(mallctl("prof.active", &active, &sz, NULL, 0), 0,
|
||||
"Unexpected prof.active failure");
|
||||
return active;
|
||||
}
|
||||
|
||||
static void
|
||||
test_extent_body(unsigned arena_ind) {
|
||||
void *p;
|
||||
|
|
@ -11,9 +62,13 @@ test_extent_body(unsigned arena_ind) {
|
|||
size_t purge_mib[3];
|
||||
size_t purge_miblen;
|
||||
int flags;
|
||||
bool xallocx_success_a, xallocx_success_b, xallocx_success_c;
|
||||
bool xallocx_success_a;
|
||||
bool expect_xallocx_success;
|
||||
bool prof_active;
|
||||
|
||||
flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
|
||||
expect_xallocx_success = maps_coalesce && try_split && try_merge;
|
||||
prof_active = prof_active_enabled();
|
||||
|
||||
/* Get large size classes. */
|
||||
sz = sizeof(size_t);
|
||||
|
|
@ -58,32 +113,16 @@ test_extent_body(unsigned arena_ind) {
|
|||
try_dalloc = true;
|
||||
|
||||
/* Test decommit/commit and observe split/merge. */
|
||||
try_dalloc = false;
|
||||
try_decommit = true;
|
||||
p = mallocx(large0 * 2, flags);
|
||||
expect_ptr_not_null(p, "Unexpected mallocx() error");
|
||||
did_decommit = false;
|
||||
did_commit = false;
|
||||
called_split = false;
|
||||
did_split = false;
|
||||
did_merge = false;
|
||||
xallocx_success_b = (xallocx(p, large0, 0, flags) == large0);
|
||||
expect_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0),
|
||||
0, "Unexpected arena.%u.purge error", arena_ind);
|
||||
if (xallocx_success_b) {
|
||||
expect_true(did_split, "Expected split");
|
||||
}
|
||||
xallocx_success_c = (xallocx(p, large0 * 2, 0, flags) == large0 * 2);
|
||||
if (did_split) {
|
||||
expect_b_eq(
|
||||
did_decommit, did_commit, "Expected decommit/commit match");
|
||||
}
|
||||
if (xallocx_success_b && xallocx_success_c) {
|
||||
expect_true(did_merge, "Expected merge");
|
||||
}
|
||||
dallocx(p, flags);
|
||||
try_dalloc = true;
|
||||
try_decommit = false;
|
||||
test_decommit_commit(arena_ind, flags, large0, purge_mib, purge_miblen,
|
||||
expect_xallocx_success && !prof_active);
|
||||
|
||||
/*
|
||||
* Active profiling may decline to grow a non-sampled allocation if it
|
||||
* is not page-aligned. Force page alignment to keep deterministic
|
||||
* coverage for the successful grow/commit/merge path.
|
||||
*/
|
||||
test_decommit_commit(arena_ind, flags | MALLOCX_ALIGN(PAGE), large0,
|
||||
purge_mib, purge_miblen, expect_xallocx_success);
|
||||
|
||||
/* Make sure non-large allocation succeeds. */
|
||||
p = mallocx(42, flags);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue