summaryrefslogtreecommitdiffstats
path: root/deps/jemalloc/test/unit/oversize_threshold.c
diff options
context:
space:
mode:
Diffstat (limited to 'deps/jemalloc/test/unit/oversize_threshold.c')
-rw-r--r--deps/jemalloc/test/unit/oversize_threshold.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/deps/jemalloc/test/unit/oversize_threshold.c b/deps/jemalloc/test/unit/oversize_threshold.c
new file mode 100644
index 0000000..44a8f76
--- /dev/null
+++ b/deps/jemalloc/test/unit/oversize_threshold.c
@@ -0,0 +1,133 @@
+#include "test/jemalloc_test.h"
+
+#include "jemalloc/internal/ctl.h"
+
+static void
+arena_mallctl(const char *mallctl_str, unsigned arena, void *oldp,
+ size_t *oldlen, void *newp, size_t newlen) {
+ int err;
+ char buf[100];
+ malloc_snprintf(buf, sizeof(buf), mallctl_str, arena);
+
+ err = mallctl(buf, oldp, oldlen, newp, newlen);
+ expect_d_eq(0, err, "Mallctl failed; %s", buf);
+}
+
+TEST_BEGIN(test_oversize_threshold_get_set) {
+ int err;
+ size_t old_threshold;
+ size_t new_threshold;
+ size_t threshold_sz = sizeof(old_threshold);
+
+ unsigned arena;
+ size_t arena_sz = sizeof(arena);
+ err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
+ expect_d_eq(0, err, "Arena creation failed");
+
+ /* Just a write. */
+ new_threshold = 1024 * 1024;
+ arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
+ &new_threshold, threshold_sz);
+
+ /* Read and write */
+ new_threshold = 2 * 1024 * 1024;
+ arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
+ &threshold_sz, &new_threshold, threshold_sz);
+ expect_zu_eq(1024 * 1024, old_threshold, "Should have read old value");
+
+ /* Just a read */
+ arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
+ &threshold_sz, NULL, 0);
+ expect_zu_eq(2 * 1024 * 1024, old_threshold, "Should have read old value");
+}
+TEST_END
+
+static size_t max_purged = 0;
+static bool
+purge_forced_record_max(extent_hooks_t* hooks, void *addr, size_t sz,
+ size_t offset, size_t length, unsigned arena_ind) {
+ if (length > max_purged) {
+ max_purged = length;
+ }
+ return false;
+}
+
+static bool
+dalloc_record_max(extent_hooks_t *extent_hooks, void *addr, size_t sz,
+ bool comitted, unsigned arena_ind) {
+ if (sz > max_purged) {
+ max_purged = sz;
+ }
+ return false;
+}
+
+extent_hooks_t max_recording_extent_hooks;
+
+TEST_BEGIN(test_oversize_threshold) {
+ max_recording_extent_hooks = ehooks_default_extent_hooks;
+ max_recording_extent_hooks.purge_forced = &purge_forced_record_max;
+ max_recording_extent_hooks.dalloc = &dalloc_record_max;
+
+ extent_hooks_t *extent_hooks = &max_recording_extent_hooks;
+
+ int err;
+
+ unsigned arena;
+ size_t arena_sz = sizeof(arena);
+ err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
+ expect_d_eq(0, err, "Arena creation failed");
+ arena_mallctl("arena.%u.extent_hooks", arena, NULL, NULL, &extent_hooks,
+ sizeof(extent_hooks));
+
+ /*
+ * This test will fundamentally race with purging, since we're going to
+ * check the dirty stats to see if our oversized allocation got purged.
+ * We don't want other purging to happen accidentally. We can't just
+ * disable purging entirely, though, since that will also disable
+ * oversize purging. Just set purging intervals to be very large.
+ */
+ ssize_t decay_ms = 100 * 1000;
+ ssize_t decay_ms_sz = sizeof(decay_ms);
+ arena_mallctl("arena.%u.dirty_decay_ms", arena, NULL, NULL, &decay_ms,
+ decay_ms_sz);
+ arena_mallctl("arena.%u.muzzy_decay_ms", arena, NULL, NULL, &decay_ms,
+ decay_ms_sz);
+
+ /* Clean everything out. */
+ arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
+ max_purged = 0;
+
+ /* Set threshold to 1MB. */
+ size_t threshold = 1024 * 1024;
+ size_t threshold_sz = sizeof(threshold);
+ arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
+ &threshold, threshold_sz);
+
+ /* Allocating and freeing half a megabyte should leave them dirty. */
+ void *ptr = mallocx(512 * 1024, MALLOCX_ARENA(arena));
+ dallocx(ptr, MALLOCX_TCACHE_NONE);
+ if (!is_background_thread_enabled()) {
+ expect_zu_lt(max_purged, 512 * 1024, "Expected no 512k purge");
+ }
+
+ /* Purge again to reset everything out. */
+ arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
+ max_purged = 0;
+
+ /*
+ * Allocating and freeing 2 megabytes should have them purged because of
+ * the oversize threshold.
+ */
+ ptr = mallocx(2 * 1024 * 1024, MALLOCX_ARENA(arena));
+ dallocx(ptr, MALLOCX_TCACHE_NONE);
+ expect_zu_ge(max_purged, 2 * 1024 * 1024, "Expected a 2MB purge");
+}
+TEST_END
+
+int
+main(void) {
+ return test_no_reentrancy(
+ test_oversize_threshold_get_set,
+ test_oversize_threshold);
+}
+