1#include "test/jemalloc_test.h" 2 3#ifdef JEMALLOC_FILL 4const char *malloc_conf = "junk:false"; 5#endif 6 7#include "test/extent_hooks.h" 8 9static void 10test_extent_body(unsigned arena_ind) 11{ 12 void *p; 13 size_t large0, large1, large2, sz; 14 size_t purge_mib[3]; 15 size_t purge_miblen; 16 int flags; 17 bool xallocx_success_a, xallocx_success_b, xallocx_success_c; 18 19 flags = MALLOCX_ARENA(arena_ind) | MALLOCX_TCACHE_NONE; 20 21 /* Get large size classes. */ 22 sz = sizeof(size_t); 23 assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&large0, &sz, NULL, 24 0), 0, "Unexpected arenas.lextent.0.size failure"); 25 assert_d_eq(mallctl("arenas.lextent.1.size", (void *)&large1, &sz, NULL, 26 0), 0, "Unexpected arenas.lextent.1.size failure"); 27 assert_d_eq(mallctl("arenas.lextent.2.size", (void *)&large2, &sz, NULL, 28 0), 0, "Unexpected arenas.lextent.2.size failure"); 29 30 /* Test dalloc/decommit/purge cascade. */ 31 purge_miblen = sizeof(purge_mib)/sizeof(size_t); 32 assert_d_eq(mallctlnametomib("arena.0.purge", purge_mib, &purge_miblen), 33 0, "Unexpected mallctlnametomib() failure"); 34 purge_mib[1] = (size_t)arena_ind; 35 try_dalloc = false; 36 try_decommit = false; 37 p = mallocx(large0 * 2, flags); 38 assert_ptr_not_null(p, "Unexpected mallocx() error"); 39 called_dalloc = false; 40 called_decommit = false; 41 did_purge_lazy = false; 42 did_purge_forced = false; 43 called_split = false; 44 xallocx_success_a = (xallocx(p, large0, 0, flags) == large0); 45 assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0), 46 0, "Unexpected arena.%u.purge error", arena_ind); 47 if (xallocx_success_a) { 48 assert_true(called_dalloc, "Expected dalloc call"); 49 assert_true(called_decommit, "Expected decommit call"); 50 assert_true(did_purge_lazy || did_purge_forced, 51 "Expected purge"); 52 } 53 assert_true(called_split, "Expected split call"); 54 dallocx(p, flags); 55 try_dalloc = true; 56 57 /* Test decommit/commit and observe split/merge. */ 58 try_dalloc = false; 59 try_decommit = true; 60 p = mallocx(large0 * 2, flags); 61 assert_ptr_not_null(p, "Unexpected mallocx() error"); 62 did_decommit = false; 63 did_commit = false; 64 called_split = false; 65 did_split = false; 66 did_merge = false; 67 xallocx_success_b = (xallocx(p, large0, 0, flags) == large0); 68 assert_d_eq(mallctlbymib(purge_mib, purge_miblen, NULL, NULL, NULL, 0), 69 0, "Unexpected arena.%u.purge error", arena_ind); 70 if (xallocx_success_b) 71 assert_true(did_split, "Expected split"); 72 xallocx_success_c = (xallocx(p, large0 * 2, 0, flags) == large0 * 2); 73 if (did_split) { 74 assert_b_eq(did_decommit, did_commit, 75 "Expected decommit/commit match"); 76 } 77 if (xallocx_success_b && xallocx_success_c) 78 assert_true(did_merge, "Expected merge"); 79 dallocx(p, flags); 80 try_dalloc = true; 81 try_decommit = false; 82 83 /* Make sure non-large allocation succeeds. */ 84 p = mallocx(42, flags); 85 assert_ptr_not_null(p, "Unexpected mallocx() error"); 86 dallocx(p, flags); 87} 88 89TEST_BEGIN(test_extent_manual_hook) 90{ 91 unsigned arena_ind; 92 size_t old_size, new_size, sz; 93 size_t hooks_mib[3]; 94 size_t hooks_miblen; 95 extent_hooks_t *new_hooks, *old_hooks; 96 97 extent_hooks_prep(); 98 99 sz = sizeof(unsigned); 100 assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0), 101 0, "Unexpected mallctl() failure"); 102 103 /* Install custom extent hooks. */ 104 hooks_miblen = sizeof(hooks_mib)/sizeof(size_t); 105 assert_d_eq(mallctlnametomib("arena.0.extent_hooks", hooks_mib, 106 &hooks_miblen), 0, "Unexpected mallctlnametomib() failure"); 107 hooks_mib[1] = (size_t)arena_ind; 108 old_size = sizeof(extent_hooks_t *); 109 new_hooks = &hooks; 110 new_size = sizeof(extent_hooks_t *); 111 assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, (void *)&old_hooks, 112 &old_size, (void *)&new_hooks, new_size), 0, 113 "Unexpected extent_hooks error"); 114 assert_ptr_ne(old_hooks->alloc, extent_alloc_hook, 115 "Unexpected extent_hooks error"); 116 assert_ptr_ne(old_hooks->dalloc, extent_dalloc_hook, 117 "Unexpected extent_hooks error"); 118 assert_ptr_ne(old_hooks->commit, extent_commit_hook, 119 "Unexpected extent_hooks error"); 120 assert_ptr_ne(old_hooks->decommit, extent_decommit_hook, 121 "Unexpected extent_hooks error"); 122 assert_ptr_ne(old_hooks->purge_lazy, extent_purge_lazy_hook, 123 "Unexpected extent_hooks error"); 124 assert_ptr_ne(old_hooks->purge_forced, extent_purge_forced_hook, 125 "Unexpected extent_hooks error"); 126 assert_ptr_ne(old_hooks->split, extent_split_hook, 127 "Unexpected extent_hooks error"); 128 assert_ptr_ne(old_hooks->merge, extent_merge_hook, 129 "Unexpected extent_hooks error"); 130 131 test_extent_body(arena_ind); 132 133 /* Restore extent hooks. */ 134 assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, NULL, NULL, 135 (void *)&old_hooks, new_size), 0, "Unexpected extent_hooks error"); 136 assert_d_eq(mallctlbymib(hooks_mib, hooks_miblen, (void *)&old_hooks, 137 &old_size, NULL, 0), 0, "Unexpected extent_hooks error"); 138 assert_ptr_eq(old_hooks, default_hooks, "Unexpected extent_hooks error"); 139 assert_ptr_eq(old_hooks->alloc, default_hooks->alloc, 140 "Unexpected extent_hooks error"); 141 assert_ptr_eq(old_hooks->dalloc, default_hooks->dalloc, 142 "Unexpected extent_hooks error"); 143 assert_ptr_eq(old_hooks->commit, default_hooks->commit, 144 "Unexpected extent_hooks error"); 145 assert_ptr_eq(old_hooks->decommit, default_hooks->decommit, 146 "Unexpected extent_hooks error"); 147 assert_ptr_eq(old_hooks->purge_lazy, default_hooks->purge_lazy, 148 "Unexpected extent_hooks error"); 149 assert_ptr_eq(old_hooks->purge_forced, default_hooks->purge_forced, 150 "Unexpected extent_hooks error"); 151 assert_ptr_eq(old_hooks->split, default_hooks->split, 152 "Unexpected extent_hooks error"); 153 assert_ptr_eq(old_hooks->merge, default_hooks->merge, 154 "Unexpected extent_hooks error"); 155} 156TEST_END 157 158TEST_BEGIN(test_extent_auto_hook) 159{ 160 unsigned arena_ind; 161 size_t new_size, sz; 162 extent_hooks_t *new_hooks; 163 164 extent_hooks_prep(); 165 166 sz = sizeof(unsigned); 167 new_hooks = &hooks; 168 new_size = sizeof(extent_hooks_t *); 169 assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, 170 (void *)&new_hooks, new_size), 0, "Unexpected mallctl() failure"); 171 172 test_extent_body(arena_ind); 173} 174TEST_END 175 176int 177main(void) 178{ 179 return (test( 180 test_extent_manual_hook, 181 test_extent_auto_hook)); 182} 183