1a0698ed9Schristos #include "test/jemalloc_test.h" 2a0698ed9Schristos 3a0698ed9Schristos static unsigned 4a0698ed9Schristos get_nsizes_impl(const char *cmd) { 5a0698ed9Schristos unsigned ret; 6a0698ed9Schristos size_t z; 7a0698ed9Schristos 8a0698ed9Schristos z = sizeof(unsigned); 9*7bdf38e5Schristos expect_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0, 10a0698ed9Schristos "Unexpected mallctl(\"%s\", ...) failure", cmd); 11a0698ed9Schristos 12a0698ed9Schristos return ret; 13a0698ed9Schristos } 14a0698ed9Schristos 15a0698ed9Schristos static unsigned 16a0698ed9Schristos get_nlarge(void) { 17a0698ed9Schristos return get_nsizes_impl("arenas.nlextents"); 18a0698ed9Schristos } 19a0698ed9Schristos 20a0698ed9Schristos static size_t 21a0698ed9Schristos get_size_impl(const char *cmd, size_t ind) { 22a0698ed9Schristos size_t ret; 23a0698ed9Schristos size_t z; 24a0698ed9Schristos size_t mib[4]; 25a0698ed9Schristos size_t miblen = 4; 26a0698ed9Schristos 27a0698ed9Schristos z = sizeof(size_t); 28*7bdf38e5Schristos expect_d_eq(mallctlnametomib(cmd, mib, &miblen), 29a0698ed9Schristos 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd); 30a0698ed9Schristos mib[2] = ind; 31a0698ed9Schristos z = sizeof(size_t); 32*7bdf38e5Schristos expect_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0), 33a0698ed9Schristos 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind); 34a0698ed9Schristos 35a0698ed9Schristos return ret; 36a0698ed9Schristos } 37a0698ed9Schristos 38a0698ed9Schristos static size_t 39a0698ed9Schristos get_large_size(size_t ind) { 40a0698ed9Schristos return get_size_impl("arenas.lextent.0.size", ind); 41a0698ed9Schristos } 42a0698ed9Schristos 43a0698ed9Schristos /* 44a0698ed9Schristos * On systems which can't merge extents, tests that call this function generate 45a0698ed9Schristos * a lot of dirty memory very quickly. Purging between cycles mitigates 46a0698ed9Schristos * potential OOM on e.g. 32-bit Windows. 47a0698ed9Schristos */ 48a0698ed9Schristos static void 49a0698ed9Schristos purge(void) { 50*7bdf38e5Schristos expect_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 51a0698ed9Schristos "Unexpected mallctl error"); 52a0698ed9Schristos } 53a0698ed9Schristos 54*7bdf38e5Schristos /* 55*7bdf38e5Schristos * GCC "-Walloc-size-larger-than" warning detects when one of the memory 56*7bdf38e5Schristos * allocation functions is called with a size larger than the maximum size that 57*7bdf38e5Schristos * they support. Here we want to explicitly test that the allocation functions 58*7bdf38e5Schristos * do indeed fail properly when this is the case, which triggers the warning. 59*7bdf38e5Schristos * Therefore we disable the warning for these tests. 60*7bdf38e5Schristos */ 61*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_PUSH 62*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN 63*7bdf38e5Schristos 64a0698ed9Schristos TEST_BEGIN(test_overflow) { 65a0698ed9Schristos size_t largemax; 66a0698ed9Schristos 67a0698ed9Schristos largemax = get_large_size(get_nlarge()-1); 68a0698ed9Schristos 69*7bdf38e5Schristos expect_ptr_null(mallocx(largemax+1, 0), 70a0698ed9Schristos "Expected OOM for mallocx(size=%#zx, 0)", largemax+1); 71a0698ed9Schristos 72*7bdf38e5Schristos expect_ptr_null(mallocx(ZU(PTRDIFF_MAX)+1, 0), 73a0698ed9Schristos "Expected OOM for mallocx(size=%#zx, 0)", ZU(PTRDIFF_MAX)+1); 74a0698ed9Schristos 75*7bdf38e5Schristos expect_ptr_null(mallocx(SIZE_T_MAX, 0), 76a0698ed9Schristos "Expected OOM for mallocx(size=%#zx, 0)", SIZE_T_MAX); 77a0698ed9Schristos 78*7bdf38e5Schristos expect_ptr_null(mallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)), 79a0698ed9Schristos "Expected OOM for mallocx(size=1, MALLOCX_ALIGN(%#zx))", 80a0698ed9Schristos ZU(PTRDIFF_MAX)+1); 81a0698ed9Schristos } 82a0698ed9Schristos TEST_END 83a0698ed9Schristos 84*7bdf38e5Schristos static void * 85*7bdf38e5Schristos remote_alloc(void *arg) { 86*7bdf38e5Schristos unsigned arena; 87*7bdf38e5Schristos size_t sz = sizeof(unsigned); 88*7bdf38e5Schristos expect_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, 89*7bdf38e5Schristos "Unexpected mallctl() failure"); 90*7bdf38e5Schristos size_t large_sz; 91*7bdf38e5Schristos sz = sizeof(size_t); 92*7bdf38e5Schristos expect_d_eq(mallctl("arenas.lextent.0.size", (void *)&large_sz, &sz, 93*7bdf38e5Schristos NULL, 0), 0, "Unexpected mallctl failure"); 94*7bdf38e5Schristos 95*7bdf38e5Schristos void *ptr = mallocx(large_sz, MALLOCX_ARENA(arena) 96*7bdf38e5Schristos | MALLOCX_TCACHE_NONE); 97*7bdf38e5Schristos void **ret = (void **)arg; 98*7bdf38e5Schristos *ret = ptr; 99*7bdf38e5Schristos 100*7bdf38e5Schristos return NULL; 101*7bdf38e5Schristos } 102*7bdf38e5Schristos 103*7bdf38e5Schristos TEST_BEGIN(test_remote_free) { 104*7bdf38e5Schristos thd_t thd; 105*7bdf38e5Schristos void *ret; 106*7bdf38e5Schristos thd_create(&thd, remote_alloc, (void *)&ret); 107*7bdf38e5Schristos thd_join(thd, NULL); 108*7bdf38e5Schristos expect_ptr_not_null(ret, "Unexpected mallocx failure"); 109*7bdf38e5Schristos 110*7bdf38e5Schristos /* Avoid TCACHE_NONE to explicitly test tcache_flush(). */ 111*7bdf38e5Schristos dallocx(ret, 0); 112*7bdf38e5Schristos mallctl("thread.tcache.flush", NULL, NULL, NULL, 0); 113*7bdf38e5Schristos } 114*7bdf38e5Schristos TEST_END 115*7bdf38e5Schristos 116a0698ed9Schristos TEST_BEGIN(test_oom) { 117a0698ed9Schristos size_t largemax; 118a0698ed9Schristos bool oom; 119a0698ed9Schristos void *ptrs[3]; 120a0698ed9Schristos unsigned i; 121a0698ed9Schristos 122a0698ed9Schristos /* 123a0698ed9Schristos * It should be impossible to allocate three objects that each consume 124a0698ed9Schristos * nearly half the virtual address space. 125a0698ed9Schristos */ 126a0698ed9Schristos largemax = get_large_size(get_nlarge()-1); 127a0698ed9Schristos oom = false; 128a0698ed9Schristos for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) { 129*7bdf38e5Schristos ptrs[i] = mallocx(largemax, MALLOCX_ARENA(0)); 130a0698ed9Schristos if (ptrs[i] == NULL) { 131a0698ed9Schristos oom = true; 132a0698ed9Schristos } 133a0698ed9Schristos } 134*7bdf38e5Schristos expect_true(oom, 135a0698ed9Schristos "Expected OOM during series of calls to mallocx(size=%zu, 0)", 136a0698ed9Schristos largemax); 137a0698ed9Schristos for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) { 138a0698ed9Schristos if (ptrs[i] != NULL) { 139a0698ed9Schristos dallocx(ptrs[i], 0); 140a0698ed9Schristos } 141a0698ed9Schristos } 142a0698ed9Schristos purge(); 143a0698ed9Schristos 144a0698ed9Schristos #if LG_SIZEOF_PTR == 3 145*7bdf38e5Schristos expect_ptr_null(mallocx(0x8000000000000000ULL, 146a0698ed9Schristos MALLOCX_ALIGN(0x8000000000000000ULL)), 147a0698ed9Schristos "Expected OOM for mallocx()"); 148*7bdf38e5Schristos expect_ptr_null(mallocx(0x8000000000000000ULL, 149a0698ed9Schristos MALLOCX_ALIGN(0x80000000)), 150a0698ed9Schristos "Expected OOM for mallocx()"); 151a0698ed9Schristos #else 152*7bdf38e5Schristos expect_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)), 153a0698ed9Schristos "Expected OOM for mallocx()"); 154a0698ed9Schristos #endif 155a0698ed9Schristos } 156a0698ed9Schristos TEST_END 157a0698ed9Schristos 158*7bdf38e5Schristos /* Re-enable the "-Walloc-size-larger-than=" warning */ 159*7bdf38e5Schristos JEMALLOC_DIAGNOSTIC_POP 160*7bdf38e5Schristos 161a0698ed9Schristos TEST_BEGIN(test_basic) { 162a0698ed9Schristos #define MAXSZ (((size_t)1) << 23) 163a0698ed9Schristos size_t sz; 164a0698ed9Schristos 165a0698ed9Schristos for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) { 166a0698ed9Schristos size_t nsz, rsz; 167a0698ed9Schristos void *p; 168a0698ed9Schristos nsz = nallocx(sz, 0); 169*7bdf38e5Schristos expect_zu_ne(nsz, 0, "Unexpected nallocx() error"); 170a0698ed9Schristos p = mallocx(sz, 0); 171*7bdf38e5Schristos expect_ptr_not_null(p, 172a0698ed9Schristos "Unexpected mallocx(size=%zx, flags=0) error", sz); 173a0698ed9Schristos rsz = sallocx(p, 0); 174*7bdf38e5Schristos expect_zu_ge(rsz, sz, "Real size smaller than expected"); 175*7bdf38e5Schristos expect_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch"); 176a0698ed9Schristos dallocx(p, 0); 177a0698ed9Schristos 178a0698ed9Schristos p = mallocx(sz, 0); 179*7bdf38e5Schristos expect_ptr_not_null(p, 180a0698ed9Schristos "Unexpected mallocx(size=%zx, flags=0) error", sz); 181a0698ed9Schristos dallocx(p, 0); 182a0698ed9Schristos 183a0698ed9Schristos nsz = nallocx(sz, MALLOCX_ZERO); 184*7bdf38e5Schristos expect_zu_ne(nsz, 0, "Unexpected nallocx() error"); 185a0698ed9Schristos p = mallocx(sz, MALLOCX_ZERO); 186*7bdf38e5Schristos expect_ptr_not_null(p, 187a0698ed9Schristos "Unexpected mallocx(size=%zx, flags=MALLOCX_ZERO) error", 188a0698ed9Schristos nsz); 189a0698ed9Schristos rsz = sallocx(p, 0); 190*7bdf38e5Schristos expect_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch"); 191a0698ed9Schristos dallocx(p, 0); 192a0698ed9Schristos purge(); 193a0698ed9Schristos } 194a0698ed9Schristos #undef MAXSZ 195a0698ed9Schristos } 196a0698ed9Schristos TEST_END 197a0698ed9Schristos 198a0698ed9Schristos TEST_BEGIN(test_alignment_and_size) { 199a0698ed9Schristos const char *percpu_arena; 200a0698ed9Schristos size_t sz = sizeof(percpu_arena); 201a0698ed9Schristos 202a0698ed9Schristos if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) || 203a0698ed9Schristos strcmp(percpu_arena, "disabled") != 0) { 204a0698ed9Schristos test_skip("test_alignment_and_size skipped: " 205a0698ed9Schristos "not working with percpu arena."); 206a0698ed9Schristos }; 207a0698ed9Schristos #define MAXALIGN (((size_t)1) << 23) 208a0698ed9Schristos #define NITER 4 209a0698ed9Schristos size_t nsz, rsz, alignment, total; 210a0698ed9Schristos unsigned i; 211a0698ed9Schristos void *ps[NITER]; 212a0698ed9Schristos 213a0698ed9Schristos for (i = 0; i < NITER; i++) { 214a0698ed9Schristos ps[i] = NULL; 215a0698ed9Schristos } 216a0698ed9Schristos 217a0698ed9Schristos for (alignment = 8; 218a0698ed9Schristos alignment <= MAXALIGN; 219a0698ed9Schristos alignment <<= 1) { 220a0698ed9Schristos total = 0; 221a0698ed9Schristos for (sz = 1; 222a0698ed9Schristos sz < 3 * alignment && sz < (1U << 31); 223a0698ed9Schristos sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) { 224a0698ed9Schristos for (i = 0; i < NITER; i++) { 225a0698ed9Schristos nsz = nallocx(sz, MALLOCX_ALIGN(alignment) | 226*7bdf38e5Schristos MALLOCX_ZERO | MALLOCX_ARENA(0)); 227*7bdf38e5Schristos expect_zu_ne(nsz, 0, 228a0698ed9Schristos "nallocx() error for alignment=%zu, " 229a0698ed9Schristos "size=%zu (%#zx)", alignment, sz, sz); 230a0698ed9Schristos ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) | 231*7bdf38e5Schristos MALLOCX_ZERO | MALLOCX_ARENA(0)); 232*7bdf38e5Schristos expect_ptr_not_null(ps[i], 233a0698ed9Schristos "mallocx() error for alignment=%zu, " 234a0698ed9Schristos "size=%zu (%#zx)", alignment, sz, sz); 235a0698ed9Schristos rsz = sallocx(ps[i], 0); 236*7bdf38e5Schristos expect_zu_ge(rsz, sz, 237a0698ed9Schristos "Real size smaller than expected for " 238a0698ed9Schristos "alignment=%zu, size=%zu", alignment, sz); 239*7bdf38e5Schristos expect_zu_eq(nsz, rsz, 240a0698ed9Schristos "nallocx()/sallocx() size mismatch for " 241a0698ed9Schristos "alignment=%zu, size=%zu", alignment, sz); 242*7bdf38e5Schristos expect_ptr_null( 243a0698ed9Schristos (void *)((uintptr_t)ps[i] & (alignment-1)), 244a0698ed9Schristos "%p inadequately aligned for" 245a0698ed9Schristos " alignment=%zu, size=%zu", ps[i], 246a0698ed9Schristos alignment, sz); 247a0698ed9Schristos total += rsz; 248a0698ed9Schristos if (total >= (MAXALIGN << 1)) { 249a0698ed9Schristos break; 250a0698ed9Schristos } 251a0698ed9Schristos } 252a0698ed9Schristos for (i = 0; i < NITER; i++) { 253a0698ed9Schristos if (ps[i] != NULL) { 254a0698ed9Schristos dallocx(ps[i], 0); 255a0698ed9Schristos ps[i] = NULL; 256a0698ed9Schristos } 257a0698ed9Schristos } 258a0698ed9Schristos } 259a0698ed9Schristos purge(); 260a0698ed9Schristos } 261a0698ed9Schristos #undef MAXALIGN 262a0698ed9Schristos #undef NITER 263a0698ed9Schristos } 264a0698ed9Schristos TEST_END 265a0698ed9Schristos 266a0698ed9Schristos int 267a0698ed9Schristos main(void) { 268a0698ed9Schristos return test( 269a0698ed9Schristos test_overflow, 270a0698ed9Schristos test_oom, 271*7bdf38e5Schristos test_remote_free, 272a0698ed9Schristos test_basic, 273a0698ed9Schristos test_alignment_and_size); 274a0698ed9Schristos } 275