summaryrefslogtreecommitdiffstats
path: root/test/unit
diff options
context:
space:
mode:
authorJason Evans <jasone@canonware.com>2017-03-01 23:25:48 (GMT)
committerJason Evans <jasone@canonware.com>2017-03-03 03:43:06 (GMT)
commitfd058f572baf0955091ed0dd66cca78105fdb539 (patch)
tree70bef702dce86395694eab313688a5603adadc32 /test/unit
parentd61a5f76b2e3bcd866e19ab90a59081c5fc917fa (diff)
downloadjemalloc-fd058f572baf0955091ed0dd66cca78105fdb539.zip
jemalloc-fd058f572baf0955091ed0dd66cca78105fdb539.tar.gz
jemalloc-fd058f572baf0955091ed0dd66cca78105fdb539.tar.bz2
Immediately purge cached extents if decay_time is 0.
This fixes a regression caused by 54269dc0ed3e4d04b2539016431de3cfe8330719 (Remove obsolete arena_maybe_purge() call.), as well as providing a general fix. This resolves #665.
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/decay.c105
1 files changed, 104 insertions, 1 deletions
diff --git a/test/unit/decay.c b/test/unit/decay.c
index 9845322..2513dbd 100644
--- a/test/unit/decay.c
+++ b/test/unit/decay.c
@@ -348,10 +348,113 @@ TEST_BEGIN(test_decay_nonmonotonic) {
}
TEST_END
+static unsigned
+do_arena_create(ssize_t decay_time) {
+ unsigned arena_ind;
+ size_t sz = sizeof(unsigned);
+ assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0),
+ 0, "Unexpected mallctl() failure");
+ size_t mib[3];
+ size_t miblen = sizeof(mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("arena.0.decay_time", mib, &miblen), 0,
+ "Unexpected mallctlnametomib() failure");
+ mib[1] = (size_t)arena_ind;
+ assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, (void *)&decay_time,
+ sizeof(decay_time)), 0, "Unexpected mallctlbymib() failure");
+ return arena_ind;
+}
+
+static void
+do_arena_destroy(unsigned arena_ind) {
+ size_t mib[3];
+ size_t miblen = sizeof(mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("arena.0.destroy", mib, &miblen), 0,
+ "Unexpected mallctlnametomib() failure");
+ mib[1] = (size_t)arena_ind;
+ assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
+ "Unexpected mallctlbymib() failure");
+}
+
+void
+do_epoch(void) {
+ uint64_t epoch = 1;
+ assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
+ 0, "Unexpected mallctl() failure");
+}
+
+static size_t
+get_arena_pdirty(unsigned arena_ind) {
+ do_epoch();
+ size_t mib[4];
+ size_t miblen = sizeof(mib)/sizeof(size_t);
+ assert_d_eq(mallctlnametomib("stats.arenas.0.pdirty", mib, &miblen), 0,
+ "Unexpected mallctlnametomib() failure");
+ mib[2] = (size_t)arena_ind;
+ size_t pdirty;
+ size_t sz = sizeof(pdirty);
+ assert_d_eq(mallctlbymib(mib, miblen, (void *)&pdirty, &sz, NULL, 0), 0,
+ "Unexpected mallctlbymib() failure");
+ return pdirty;
+}
+
+static void *
+do_mallocx(size_t size, int flags) {
+ void *p = mallocx(size, flags);
+ assert_ptr_not_null(p, "Unexpected mallocx() failure");
+ return p;
+}
+
+static void
+generate_dirty(unsigned arena_ind, size_t size) {
+ int flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
+ void *p = do_mallocx(size, flags);
+ dallocx(p, flags);
+}
+
+TEST_BEGIN(test_decay_now) {
+ unsigned arena_ind = do_arena_create(0);
+ assert_zu_eq(get_arena_pdirty(arena_ind), 0, "Unexpected dirty pages");
+ size_t sizes[] = {16, PAGE<<2, HUGEPAGE<<2};
+ /* Verify that dirty pages never linger after deallocation. */
+ for (unsigned i = 0; i < sizeof(sizes)/sizeof(size_t); i++) {
+ size_t size = sizes[i];
+ generate_dirty(arena_ind, size);
+ assert_zu_eq(get_arena_pdirty(arena_ind), 0,
+ "Unexpected dirty pages");
+ }
+ do_arena_destroy(arena_ind);
+}
+TEST_END
+
+TEST_BEGIN(test_decay_never) {
+ unsigned arena_ind = do_arena_create(-1);
+ int flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE;
+ assert_zu_eq(get_arena_pdirty(arena_ind), 0, "Unexpected dirty pages");
+ size_t sizes[] = {16, PAGE<<2, HUGEPAGE<<2};
+ void *ptrs[sizeof(sizes)/sizeof(size_t)];
+ for (unsigned i = 0; i < sizeof(sizes)/sizeof(size_t); i++) {
+ ptrs[i] = do_mallocx(sizes[i], flags);
+ }
+ /* Verify that each deallocation generates additional dirty pages. */
+ size_t pdirty_prev = get_arena_pdirty(arena_ind);
+ assert_zu_eq(pdirty_prev, 0, "Unexpected dirty pages");
+ for (unsigned i = 0; i < sizeof(sizes)/sizeof(size_t); i++) {
+ dallocx(ptrs[i], flags);
+ size_t pdirty = get_arena_pdirty(arena_ind);
+ assert_zu_gt(pdirty, pdirty_prev,
+ "Expected dirty pages to increase.");
+ pdirty_prev = pdirty;
+ }
+ do_arena_destroy(arena_ind);
+}
+TEST_END
+
int
main(void) {
return test(
test_decay_ticks,
test_decay_ticker,
- test_decay_nonmonotonic);
+ test_decay_nonmonotonic,
+ test_decay_now,
+ test_decay_never);
}