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