1*7bdf38e5Schristos #include "test/jemalloc_test.h" 2*7bdf38e5Schristos 3*7bdf38e5Schristos #include "jemalloc/internal/pa.h" 4*7bdf38e5Schristos 5*7bdf38e5Schristos static void * 6*7bdf38e5Schristos alloc_hook(extent_hooks_t *extent_hooks, void *new_addr, size_t size, 7*7bdf38e5Schristos size_t alignment, bool *zero, bool *commit, unsigned arena_ind) { 8*7bdf38e5Schristos void *ret = pages_map(new_addr, size, alignment, commit); 9*7bdf38e5Schristos return ret; 10*7bdf38e5Schristos } 11*7bdf38e5Schristos 12*7bdf38e5Schristos static bool 13*7bdf38e5Schristos merge_hook(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a, 14*7bdf38e5Schristos void *addr_b, size_t size_b, bool committed, unsigned arena_ind) { 15*7bdf38e5Schristos return !maps_coalesce; 16*7bdf38e5Schristos } 17*7bdf38e5Schristos 18*7bdf38e5Schristos static bool 19*7bdf38e5Schristos split_hook(extent_hooks_t *extent_hooks, void *addr, size_t size, 20*7bdf38e5Schristos size_t size_a, size_t size_b, bool committed, unsigned arena_ind) { 21*7bdf38e5Schristos return !maps_coalesce; 22*7bdf38e5Schristos } 23*7bdf38e5Schristos 24*7bdf38e5Schristos static void 25*7bdf38e5Schristos init_test_extent_hooks(extent_hooks_t *hooks) { 26*7bdf38e5Schristos /* 27*7bdf38e5Schristos * The default hooks are mostly fine for testing. A few of them, 28*7bdf38e5Schristos * though, access globals (alloc for dss setting in an arena, split and 29*7bdf38e5Schristos * merge touch the global emap to find head state. The first of these 30*7bdf38e5Schristos * can be fixed by keeping that state with the hooks, where it logically 31*7bdf38e5Schristos * belongs. The second, though, we can only fix when we use the extent 32*7bdf38e5Schristos * hook API. 33*7bdf38e5Schristos */ 34*7bdf38e5Schristos memcpy(hooks, &ehooks_default_extent_hooks, sizeof(extent_hooks_t)); 35*7bdf38e5Schristos hooks->alloc = &alloc_hook; 36*7bdf38e5Schristos hooks->merge = &merge_hook; 37*7bdf38e5Schristos hooks->split = &split_hook; 38*7bdf38e5Schristos } 39*7bdf38e5Schristos 40*7bdf38e5Schristos typedef struct test_data_s test_data_t; 41*7bdf38e5Schristos struct test_data_s { 42*7bdf38e5Schristos pa_shard_t shard; 43*7bdf38e5Schristos pa_central_t central; 44*7bdf38e5Schristos base_t *base; 45*7bdf38e5Schristos emap_t emap; 46*7bdf38e5Schristos pa_shard_stats_t stats; 47*7bdf38e5Schristos malloc_mutex_t stats_mtx; 48*7bdf38e5Schristos extent_hooks_t hooks; 49*7bdf38e5Schristos }; 50*7bdf38e5Schristos 51*7bdf38e5Schristos test_data_t *init_test_data(ssize_t dirty_decay_ms, ssize_t muzzy_decay_ms) { 52*7bdf38e5Schristos test_data_t *test_data = calloc(1, sizeof(test_data_t)); 53*7bdf38e5Schristos assert_ptr_not_null(test_data, ""); 54*7bdf38e5Schristos init_test_extent_hooks(&test_data->hooks); 55*7bdf38e5Schristos 56*7bdf38e5Schristos base_t *base = base_new(TSDN_NULL, /* ind */ 1, &test_data->hooks, 57*7bdf38e5Schristos /* metadata_use_hooks */ true); 58*7bdf38e5Schristos assert_ptr_not_null(base, ""); 59*7bdf38e5Schristos 60*7bdf38e5Schristos test_data->base = base; 61*7bdf38e5Schristos bool err = emap_init(&test_data->emap, test_data->base, 62*7bdf38e5Schristos /* zeroed */ true); 63*7bdf38e5Schristos assert_false(err, ""); 64*7bdf38e5Schristos 65*7bdf38e5Schristos nstime_t time; 66*7bdf38e5Schristos nstime_init(&time, 0); 67*7bdf38e5Schristos 68*7bdf38e5Schristos err = pa_central_init(&test_data->central, base, opt_hpa, 69*7bdf38e5Schristos &hpa_hooks_default); 70*7bdf38e5Schristos assert_false(err, ""); 71*7bdf38e5Schristos 72*7bdf38e5Schristos const size_t pa_oversize_threshold = 8 * 1024 * 1024; 73*7bdf38e5Schristos err = pa_shard_init(TSDN_NULL, &test_data->shard, &test_data->central, 74*7bdf38e5Schristos &test_data->emap, test_data->base, /* ind */ 1, &test_data->stats, 75*7bdf38e5Schristos &test_data->stats_mtx, &time, pa_oversize_threshold, dirty_decay_ms, 76*7bdf38e5Schristos muzzy_decay_ms); 77*7bdf38e5Schristos assert_false(err, ""); 78*7bdf38e5Schristos 79*7bdf38e5Schristos return test_data; 80*7bdf38e5Schristos } 81*7bdf38e5Schristos 82*7bdf38e5Schristos void destroy_test_data(test_data_t *data) { 83*7bdf38e5Schristos base_delete(TSDN_NULL, data->base); 84*7bdf38e5Schristos free(data); 85*7bdf38e5Schristos } 86*7bdf38e5Schristos 87*7bdf38e5Schristos static void * 88*7bdf38e5Schristos do_alloc_free_purge(void *arg) { 89*7bdf38e5Schristos test_data_t *test_data = (test_data_t *)arg; 90*7bdf38e5Schristos for (int i = 0; i < 10 * 1000; i++) { 91*7bdf38e5Schristos bool deferred_work_generated = false; 92*7bdf38e5Schristos edata_t *edata = pa_alloc(TSDN_NULL, &test_data->shard, PAGE, 93*7bdf38e5Schristos PAGE, /* slab */ false, /* szind */ 0, /* zero */ false, 94*7bdf38e5Schristos /* guarded */ false, &deferred_work_generated); 95*7bdf38e5Schristos assert_ptr_not_null(edata, ""); 96*7bdf38e5Schristos pa_dalloc(TSDN_NULL, &test_data->shard, edata, 97*7bdf38e5Schristos &deferred_work_generated); 98*7bdf38e5Schristos malloc_mutex_lock(TSDN_NULL, 99*7bdf38e5Schristos &test_data->shard.pac.decay_dirty.mtx); 100*7bdf38e5Schristos pac_decay_all(TSDN_NULL, &test_data->shard.pac, 101*7bdf38e5Schristos &test_data->shard.pac.decay_dirty, 102*7bdf38e5Schristos &test_data->shard.pac.stats->decay_dirty, 103*7bdf38e5Schristos &test_data->shard.pac.ecache_dirty, true); 104*7bdf38e5Schristos malloc_mutex_unlock(TSDN_NULL, 105*7bdf38e5Schristos &test_data->shard.pac.decay_dirty.mtx); 106*7bdf38e5Schristos } 107*7bdf38e5Schristos return NULL; 108*7bdf38e5Schristos } 109*7bdf38e5Schristos 110*7bdf38e5Schristos TEST_BEGIN(test_alloc_free_purge_thds) { 111*7bdf38e5Schristos test_data_t *test_data = init_test_data(0, 0); 112*7bdf38e5Schristos thd_t thds[4]; 113*7bdf38e5Schristos for (int i = 0; i < 4; i++) { 114*7bdf38e5Schristos thd_create(&thds[i], do_alloc_free_purge, test_data); 115*7bdf38e5Schristos } 116*7bdf38e5Schristos for (int i = 0; i < 4; i++) { 117*7bdf38e5Schristos thd_join(thds[i], NULL); 118*7bdf38e5Schristos } 119*7bdf38e5Schristos } 120*7bdf38e5Schristos TEST_END 121*7bdf38e5Schristos 122*7bdf38e5Schristos int 123*7bdf38e5Schristos main(void) { 124*7bdf38e5Schristos return test( 125*7bdf38e5Schristos test_alloc_free_purge_thds); 126*7bdf38e5Schristos } 127