Home | History | Annotate | Download | only in integration
      1 #include "test/jemalloc_test.h"
      2 
      3 static unsigned
      4 get_nsizes_impl(const char *cmd) {
      5 	unsigned ret;
      6 	size_t z;
      7 
      8 	z = sizeof(unsigned);
      9 	assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
     10 	    "Unexpected mallctl(\"%s\", ...) failure", cmd);
     11 
     12 	return ret;
     13 }
     14 
     15 static unsigned
     16 get_nlarge(void) {
     17 	return get_nsizes_impl("arenas.nlextents");
     18 }
     19 
     20 static size_t
     21 get_size_impl(const char *cmd, size_t ind) {
     22 	size_t ret;
     23 	size_t z;
     24 	size_t mib[4];
     25 	size_t miblen = 4;
     26 
     27 	z = sizeof(size_t);
     28 	assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
     29 	    0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
     30 	mib[2] = ind;
     31 	z = sizeof(size_t);
     32 	assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
     33 	    0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
     34 
     35 	return ret;
     36 }
     37 
     38 static size_t
     39 get_large_size(size_t ind) {
     40 	return get_size_impl("arenas.lextent.0.size", ind);
     41 }
     42 
     43 /*
     44  * On systems which can't merge extents, tests that call this function generate
     45  * a lot of dirty memory very quickly.  Purging between cycles mitigates
     46  * potential OOM on e.g. 32-bit Windows.
     47  */
     48 static void
     49 purge(void) {
     50 	assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
     51 	    "Unexpected mallctl error");
     52 }
     53 
     54 TEST_BEGIN(test_overflow) {
     55 	size_t largemax;
     56 
     57 	largemax = get_large_size(get_nlarge()-1);
     58 
     59 	assert_ptr_null(mallocx(largemax+1, 0),
     60 	    "Expected OOM for mallocx(size=%#zx, 0)", largemax+1);
     61 
     62 	assert_ptr_null(mallocx(ZU(PTRDIFF_MAX)+1, 0),
     63 	    "Expected OOM for mallocx(size=%#zx, 0)", ZU(PTRDIFF_MAX)+1);
     64 
     65 	assert_ptr_null(mallocx(SIZE_T_MAX, 0),
     66 	    "Expected OOM for mallocx(size=%#zx, 0)", SIZE_T_MAX);
     67 
     68 	assert_ptr_null(mallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),
     69 	    "Expected OOM for mallocx(size=1, MALLOCX_ALIGN(%#zx))",
     70 	    ZU(PTRDIFF_MAX)+1);
     71 }
     72 TEST_END
     73 
     74 TEST_BEGIN(test_oom) {
     75 	size_t largemax;
     76 	bool oom;
     77 	void *ptrs[3];
     78 	unsigned i;
     79 
     80 	/*
     81 	 * It should be impossible to allocate three objects that each consume
     82 	 * nearly half the virtual address space.
     83 	 */
     84 	largemax = get_large_size(get_nlarge()-1);
     85 	oom = false;
     86 	for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
     87 		ptrs[i] = mallocx(largemax, 0);
     88 		if (ptrs[i] == NULL) {
     89 			oom = true;
     90 		}
     91 	}
     92 	assert_true(oom,
     93 	    "Expected OOM during series of calls to mallocx(size=%zu, 0)",
     94 	    largemax);
     95 	for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
     96 		if (ptrs[i] != NULL) {
     97 			dallocx(ptrs[i], 0);
     98 		}
     99 	}
    100 	purge();
    101 
    102 #if LG_SIZEOF_PTR == 3
    103 	assert_ptr_null(mallocx(0x8000000000000000ULL,
    104 	    MALLOCX_ALIGN(0x8000000000000000ULL)),
    105 	    "Expected OOM for mallocx()");
    106 	assert_ptr_null(mallocx(0x8000000000000000ULL,
    107 	    MALLOCX_ALIGN(0x80000000)),
    108 	    "Expected OOM for mallocx()");
    109 #else
    110 	assert_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)),
    111 	    "Expected OOM for mallocx()");
    112 #endif
    113 }
    114 TEST_END
    115 
    116 TEST_BEGIN(test_basic) {
    117 #define MAXSZ (((size_t)1) << 23)
    118 	size_t sz;
    119 
    120 	for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
    121 		size_t nsz, rsz;
    122 		void *p;
    123 		nsz = nallocx(sz, 0);
    124 		assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
    125 		p = mallocx(sz, 0);
    126 		assert_ptr_not_null(p,
    127 		    "Unexpected mallocx(size=%zx, flags=0) error", sz);
    128 		rsz = sallocx(p, 0);
    129 		assert_zu_ge(rsz, sz, "Real size smaller than expected");
    130 		assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
    131 		dallocx(p, 0);
    132 
    133 		p = mallocx(sz, 0);
    134 		assert_ptr_not_null(p,
    135 		    "Unexpected mallocx(size=%zx, flags=0) error", sz);
    136 		dallocx(p, 0);
    137 
    138 		nsz = nallocx(sz, MALLOCX_ZERO);
    139 		assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
    140 		p = mallocx(sz, MALLOCX_ZERO);
    141 		assert_ptr_not_null(p,
    142 		    "Unexpected mallocx(size=%zx, flags=MALLOCX_ZERO) error",
    143 		    nsz);
    144 		rsz = sallocx(p, 0);
    145 		assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
    146 		dallocx(p, 0);
    147 		purge();
    148 	}
    149 #undef MAXSZ
    150 }
    151 TEST_END
    152 
    153 TEST_BEGIN(test_alignment_and_size) {
    154 	const char *percpu_arena;
    155 	size_t sz = sizeof(percpu_arena);
    156 
    157 	if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) ||
    158 	    strcmp(percpu_arena, "disabled") != 0) {
    159 		test_skip("test_alignment_and_size skipped: "
    160 		    "not working with percpu arena.");
    161 	};
    162 #define MAXALIGN (((size_t)1) << 23)
    163 #define NITER 4
    164 	size_t nsz, rsz, alignment, total;
    165 	unsigned i;
    166 	void *ps[NITER];
    167 
    168 	for (i = 0; i < NITER; i++) {
    169 		ps[i] = NULL;
    170 	}
    171 
    172 	for (alignment = 8;
    173 	    alignment <= MAXALIGN;
    174 	    alignment <<= 1) {
    175 		total = 0;
    176 		for (sz = 1;
    177 		    sz < 3 * alignment && sz < (1U << 31);
    178 		    sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
    179 			for (i = 0; i < NITER; i++) {
    180 				nsz = nallocx(sz, MALLOCX_ALIGN(alignment) |
    181 				    MALLOCX_ZERO);
    182 				assert_zu_ne(nsz, 0,
    183 				    "nallocx() error for alignment=%zu, "
    184 				    "size=%zu (%#zx)", alignment, sz, sz);
    185 				ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |
    186 				    MALLOCX_ZERO);
    187 				assert_ptr_not_null(ps[i],
    188 				    "mallocx() error for alignment=%zu, "
    189 				    "size=%zu (%#zx)", alignment, sz, sz);
    190 				rsz = sallocx(ps[i], 0);
    191 				assert_zu_ge(rsz, sz,
    192 				    "Real size smaller than expected for "
    193 				    "alignment=%zu, size=%zu", alignment, sz);
    194 				assert_zu_eq(nsz, rsz,
    195 				    "nallocx()/sallocx() size mismatch for "
    196 				    "alignment=%zu, size=%zu", alignment, sz);
    197 				assert_ptr_null(
    198 				    (void *)((uintptr_t)ps[i] & (alignment-1)),
    199 				    "%p inadequately aligned for"
    200 				    " alignment=%zu, size=%zu", ps[i],
    201 				    alignment, sz);
    202 				total += rsz;
    203 				if (total >= (MAXALIGN << 1)) {
    204 					break;
    205 				}
    206 			}
    207 			for (i = 0; i < NITER; i++) {
    208 				if (ps[i] != NULL) {
    209 					dallocx(ps[i], 0);
    210 					ps[i] = NULL;
    211 				}
    212 			}
    213 		}
    214 		purge();
    215 	}
    216 #undef MAXALIGN
    217 #undef NITER
    218 }
    219 TEST_END
    220 
    221 int
    222 main(void) {
    223 	return test(
    224 	    test_overflow,
    225 	    test_oom,
    226 	    test_basic,
    227 	    test_alignment_and_size);
    228 }
    229