1 1.1 christos #include "test/jemalloc_test.h" 2 1.1 christos 3 1.1 christos /* Config -- "narenas:1,bin_shards:1-160:16|129-512:4|256-256:8" */ 4 1.1 christos 5 1.1 christos #define NTHREADS 16 6 1.1 christos #define REMOTE_NALLOC 256 7 1.1 christos 8 1.1 christos static void * 9 1.1 christos thd_producer(void *varg) { 10 1.1 christos void **mem = varg; 11 1.1 christos unsigned arena, i; 12 1.1 christos size_t sz; 13 1.1 christos 14 1.1 christos sz = sizeof(arena); 15 1.1 christos /* Remote arena. */ 16 1.1 christos expect_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0, 17 1.1 christos "Unexpected mallctl() failure"); 18 1.1 christos for (i = 0; i < REMOTE_NALLOC / 2; i++) { 19 1.1 christos mem[i] = mallocx(1, MALLOCX_TCACHE_NONE | MALLOCX_ARENA(arena)); 20 1.1 christos } 21 1.1 christos 22 1.1 christos /* Remote bin. */ 23 1.1 christos for (; i < REMOTE_NALLOC; i++) { 24 1.1 christos mem[i] = mallocx(1, MALLOCX_TCACHE_NONE | MALLOCX_ARENA(0)); 25 1.1 christos } 26 1.1 christos 27 1.1 christos return NULL; 28 1.1 christos } 29 1.1 christos 30 1.1 christos TEST_BEGIN(test_producer_consumer) { 31 1.1 christos thd_t thds[NTHREADS]; 32 1.1 christos void *mem[NTHREADS][REMOTE_NALLOC]; 33 1.1 christos unsigned i; 34 1.1 christos 35 1.1 christos /* Create producer threads to allocate. */ 36 1.1 christos for (i = 0; i < NTHREADS; i++) { 37 1.1 christos thd_create(&thds[i], thd_producer, mem[i]); 38 1.1 christos } 39 1.1 christos for (i = 0; i < NTHREADS; i++) { 40 1.1 christos thd_join(thds[i], NULL); 41 1.1 christos } 42 1.1 christos /* Remote deallocation by the current thread. */ 43 1.1 christos for (i = 0; i < NTHREADS; i++) { 44 1.1 christos for (unsigned j = 0; j < REMOTE_NALLOC; j++) { 45 1.1 christos expect_ptr_not_null(mem[i][j], 46 1.1 christos "Unexpected remote allocation failure"); 47 1.1 christos dallocx(mem[i][j], 0); 48 1.1 christos } 49 1.1 christos } 50 1.1 christos } 51 1.1 christos TEST_END 52 1.1 christos 53 1.1 christos static void * 54 1.1 christos thd_start(void *varg) { 55 1.1 christos void *ptr, *ptr2; 56 1.1 christos edata_t *edata; 57 1.1 christos unsigned shard1, shard2; 58 1.1 christos 59 1.1 christos tsdn_t *tsdn = tsdn_fetch(); 60 1.1 christos /* Try triggering allocations from sharded bins. */ 61 1.1 christos for (unsigned i = 0; i < 1024; i++) { 62 1.1 christos ptr = mallocx(1, MALLOCX_TCACHE_NONE); 63 1.1 christos ptr2 = mallocx(129, MALLOCX_TCACHE_NONE); 64 1.1 christos 65 1.1 christos edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr); 66 1.1 christos shard1 = edata_binshard_get(edata); 67 1.1 christos dallocx(ptr, 0); 68 1.1 christos expect_u_lt(shard1, 16, "Unexpected bin shard used"); 69 1.1 christos 70 1.1 christos edata = emap_edata_lookup(tsdn, &arena_emap_global, ptr2); 71 1.1 christos shard2 = edata_binshard_get(edata); 72 1.1 christos dallocx(ptr2, 0); 73 1.1 christos expect_u_lt(shard2, 4, "Unexpected bin shard used"); 74 1.1 christos 75 1.1 christos if (shard1 > 0 || shard2 > 0) { 76 1.1 christos /* Triggered sharded bin usage. */ 77 1.1 christos return (void *)(uintptr_t)shard1; 78 1.1 christos } 79 1.1 christos } 80 1.1 christos 81 1.1 christos return NULL; 82 1.1 christos } 83 1.1 christos 84 1.1 christos TEST_BEGIN(test_bin_shard_mt) { 85 1.1 christos test_skip_if(have_percpu_arena && 86 1.1 christos PERCPU_ARENA_ENABLED(opt_percpu_arena)); 87 1.1 christos 88 1.1 christos thd_t thds[NTHREADS]; 89 1.1 christos unsigned i; 90 1.1 christos for (i = 0; i < NTHREADS; i++) { 91 1.1 christos thd_create(&thds[i], thd_start, NULL); 92 1.1 christos } 93 1.1 christos bool sharded = false; 94 1.1 christos for (i = 0; i < NTHREADS; i++) { 95 1.1 christos void *ret; 96 1.1 christos thd_join(thds[i], &ret); 97 1.1 christos if (ret != NULL) { 98 1.1 christos sharded = true; 99 1.1 christos } 100 1.1 christos } 101 1.1 christos expect_b_eq(sharded, true, "Did not find sharded bins"); 102 1.1 christos } 103 1.1 christos TEST_END 104 1.1 christos 105 1.1 christos TEST_BEGIN(test_bin_shard) { 106 1.1 christos unsigned nbins, i; 107 1.1 christos size_t mib[4], mib2[4]; 108 1.1 christos size_t miblen, miblen2, len; 109 1.1 christos 110 1.1 christos len = sizeof(nbins); 111 1.1 christos expect_d_eq(mallctl("arenas.nbins", (void *)&nbins, &len, NULL, 0), 0, 112 1.1 christos "Unexpected mallctl() failure"); 113 1.1 christos 114 1.1 christos miblen = 4; 115 1.1 christos expect_d_eq(mallctlnametomib("arenas.bin.0.nshards", mib, &miblen), 0, 116 1.1 christos "Unexpected mallctlnametomib() failure"); 117 1.1 christos miblen2 = 4; 118 1.1 christos expect_d_eq(mallctlnametomib("arenas.bin.0.size", mib2, &miblen2), 0, 119 1.1 christos "Unexpected mallctlnametomib() failure"); 120 1.1 christos 121 1.1 christos for (i = 0; i < nbins; i++) { 122 1.1 christos uint32_t nshards; 123 1.1 christos size_t size, sz1, sz2; 124 1.1 christos 125 1.1 christos mib[2] = i; 126 1.1 christos sz1 = sizeof(nshards); 127 1.1 christos expect_d_eq(mallctlbymib(mib, miblen, (void *)&nshards, &sz1, 128 1.1 christos NULL, 0), 0, "Unexpected mallctlbymib() failure"); 129 1.1 christos 130 1.1 christos mib2[2] = i; 131 1.1 christos sz2 = sizeof(size); 132 1.1 christos expect_d_eq(mallctlbymib(mib2, miblen2, (void *)&size, &sz2, 133 1.1 christos NULL, 0), 0, "Unexpected mallctlbymib() failure"); 134 1.1 christos 135 1.1 christos if (size >= 1 && size <= 128) { 136 1.1 christos expect_u_eq(nshards, 16, "Unexpected nshards"); 137 1.1 christos } else if (size == 256) { 138 1.1 christos expect_u_eq(nshards, 8, "Unexpected nshards"); 139 1.1 christos } else if (size > 128 && size <= 512) { 140 1.1 christos expect_u_eq(nshards, 4, "Unexpected nshards"); 141 1.1 christos } else { 142 1.1 christos expect_u_eq(nshards, 1, "Unexpected nshards"); 143 1.1 christos } 144 1.1 christos } 145 1.1 christos } 146 1.1 christos TEST_END 147 1.1 christos 148 1.1 christos int 149 1.1 christos main(void) { 150 1.1 christos return test_no_reentrancy( 151 1.1 christos test_bin_shard, 152 1.1 christos test_bin_shard_mt, 153 1.1 christos test_producer_consumer); 154 1.1 christos } 155