Home | History | Annotate | Line # | Download | only in unit
      1  1.1  christos #include "test/jemalloc_test.h"
      2  1.1  christos 
      3  1.1  christos #include "jemalloc/internal/ctl.h"
      4  1.1  christos 
      5  1.1  christos static void
      6  1.1  christos arena_mallctl(const char *mallctl_str, unsigned arena, void *oldp,
      7  1.1  christos     size_t *oldlen, void *newp, size_t newlen) {
      8  1.1  christos 	int err;
      9  1.1  christos 	char buf[100];
     10  1.1  christos 	malloc_snprintf(buf, sizeof(buf), mallctl_str, arena);
     11  1.1  christos 
     12  1.1  christos 	err = mallctl(buf, oldp, oldlen, newp, newlen);
     13  1.1  christos 	expect_d_eq(0, err, "Mallctl failed; %s", buf);
     14  1.1  christos }
     15  1.1  christos 
     16  1.1  christos TEST_BEGIN(test_oversize_threshold_get_set) {
     17  1.1  christos 	int err;
     18  1.1  christos 	size_t old_threshold;
     19  1.1  christos 	size_t new_threshold;
     20  1.1  christos 	size_t threshold_sz = sizeof(old_threshold);
     21  1.1  christos 
     22  1.1  christos 	unsigned arena;
     23  1.1  christos 	size_t arena_sz = sizeof(arena);
     24  1.1  christos 	err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
     25  1.1  christos 	expect_d_eq(0, err, "Arena creation failed");
     26  1.1  christos 
     27  1.1  christos 	/* Just a write. */
     28  1.1  christos 	new_threshold = 1024 * 1024;
     29  1.1  christos 	arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
     30  1.1  christos 	    &new_threshold, threshold_sz);
     31  1.1  christos 
     32  1.1  christos 	/* Read and write */
     33  1.1  christos 	new_threshold = 2 * 1024 * 1024;
     34  1.1  christos 	arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
     35  1.1  christos 	    &threshold_sz, &new_threshold, threshold_sz);
     36  1.1  christos 	expect_zu_eq(1024 * 1024, old_threshold, "Should have read old value");
     37  1.1  christos 
     38  1.1  christos 	/* Just a read */
     39  1.1  christos 	arena_mallctl("arena.%u.oversize_threshold", arena, &old_threshold,
     40  1.1  christos 	    &threshold_sz, NULL, 0);
     41  1.1  christos 	expect_zu_eq(2 * 1024 * 1024, old_threshold, "Should have read old value");
     42  1.1  christos }
     43  1.1  christos TEST_END
     44  1.1  christos 
     45  1.1  christos static size_t max_purged = 0;
     46  1.1  christos static bool
     47  1.1  christos purge_forced_record_max(extent_hooks_t* hooks, void *addr, size_t sz,
     48  1.1  christos     size_t offset, size_t length, unsigned arena_ind) {
     49  1.1  christos 	if (length > max_purged) {
     50  1.1  christos 		max_purged = length;
     51  1.1  christos 	}
     52  1.1  christos 	return false;
     53  1.1  christos }
     54  1.1  christos 
     55  1.1  christos static bool
     56  1.1  christos dalloc_record_max(extent_hooks_t *extent_hooks, void *addr, size_t sz,
     57  1.1  christos     bool comitted, unsigned arena_ind) {
     58  1.1  christos 	if (sz > max_purged) {
     59  1.1  christos 		max_purged = sz;
     60  1.1  christos 	}
     61  1.1  christos 	return false;
     62  1.1  christos }
     63  1.1  christos 
     64  1.1  christos extent_hooks_t max_recording_extent_hooks;
     65  1.1  christos 
     66  1.1  christos TEST_BEGIN(test_oversize_threshold) {
     67  1.1  christos 	max_recording_extent_hooks = ehooks_default_extent_hooks;
     68  1.1  christos 	max_recording_extent_hooks.purge_forced = &purge_forced_record_max;
     69  1.1  christos 	max_recording_extent_hooks.dalloc = &dalloc_record_max;
     70  1.1  christos 
     71  1.1  christos 	extent_hooks_t *extent_hooks = &max_recording_extent_hooks;
     72  1.1  christos 
     73  1.1  christos 	int err;
     74  1.1  christos 
     75  1.1  christos 	unsigned arena;
     76  1.1  christos 	size_t arena_sz = sizeof(arena);
     77  1.1  christos 	err = mallctl("arenas.create", (void *)&arena, &arena_sz, NULL, 0);
     78  1.1  christos 	expect_d_eq(0, err, "Arena creation failed");
     79  1.1  christos 	arena_mallctl("arena.%u.extent_hooks", arena, NULL, NULL, &extent_hooks,
     80  1.1  christos 	    sizeof(extent_hooks));
     81  1.1  christos 
     82  1.1  christos 	/*
     83  1.1  christos 	 * This test will fundamentally race with purging, since we're going to
     84  1.1  christos 	 * check the dirty stats to see if our oversized allocation got purged.
     85  1.1  christos 	 * We don't want other purging to happen accidentally.  We can't just
     86  1.1  christos 	 * disable purging entirely, though, since that will also disable
     87  1.1  christos 	 * oversize purging.  Just set purging intervals to be very large.
     88  1.1  christos 	 */
     89  1.1  christos 	ssize_t decay_ms = 100 * 1000;
     90  1.1  christos 	ssize_t decay_ms_sz = sizeof(decay_ms);
     91  1.1  christos 	arena_mallctl("arena.%u.dirty_decay_ms", arena, NULL, NULL, &decay_ms,
     92  1.1  christos 	    decay_ms_sz);
     93  1.1  christos 	arena_mallctl("arena.%u.muzzy_decay_ms", arena, NULL, NULL, &decay_ms,
     94  1.1  christos 	    decay_ms_sz);
     95  1.1  christos 
     96  1.1  christos 	/* Clean everything out. */
     97  1.1  christos 	arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
     98  1.1  christos 	max_purged = 0;
     99  1.1  christos 
    100  1.1  christos 	/* Set threshold to 1MB. */
    101  1.1  christos 	size_t threshold = 1024 * 1024;
    102  1.1  christos 	size_t threshold_sz = sizeof(threshold);
    103  1.1  christos 	arena_mallctl("arena.%u.oversize_threshold", arena, NULL, NULL,
    104  1.1  christos 	    &threshold, threshold_sz);
    105  1.1  christos 
    106  1.1  christos 	/* Allocating and freeing half a megabyte should leave them dirty. */
    107  1.1  christos 	void *ptr = mallocx(512 * 1024, MALLOCX_ARENA(arena));
    108  1.1  christos 	dallocx(ptr, MALLOCX_TCACHE_NONE);
    109  1.1  christos 	if (!is_background_thread_enabled()) {
    110  1.1  christos 		expect_zu_lt(max_purged, 512 * 1024, "Expected no 512k purge");
    111  1.1  christos 	}
    112  1.1  christos 
    113  1.1  christos 	/* Purge again to reset everything out. */
    114  1.1  christos 	arena_mallctl("arena.%u.purge", arena, NULL, NULL, NULL, 0);
    115  1.1  christos 	max_purged = 0;
    116  1.1  christos 
    117  1.1  christos 	/*
    118  1.1  christos 	 * Allocating and freeing 2 megabytes should have them purged because of
    119  1.1  christos 	 * the oversize threshold.
    120  1.1  christos 	 */
    121  1.1  christos 	ptr = mallocx(2 * 1024 * 1024, MALLOCX_ARENA(arena));
    122  1.1  christos 	dallocx(ptr, MALLOCX_TCACHE_NONE);
    123  1.1  christos 	expect_zu_ge(max_purged, 2 * 1024 * 1024, "Expected a 2MB purge");
    124  1.1  christos }
    125  1.1  christos TEST_END
    126  1.1  christos 
    127  1.1  christos int
    128  1.1  christos main(void) {
    129  1.1  christos 	return test_no_reentrancy(
    130  1.1  christos 	    test_oversize_threshold_get_set,
    131  1.1  christos 	    test_oversize_threshold);
    132  1.1  christos }
    133  1.1  christos 
    134