1#include "test/jemalloc_test.h" 2 3TEST_BEGIN(test_stats_summary) { 4 size_t sz, allocated, active, resident, mapped; 5 int expected = config_stats ? 0 : ENOENT; 6 7 sz = sizeof(size_t); 8 assert_d_eq(mallctl("stats.allocated", (void *)&allocated, &sz, NULL, 9 0), expected, "Unexpected mallctl() result"); 10 assert_d_eq(mallctl("stats.active", (void *)&active, &sz, NULL, 0), 11 expected, "Unexpected mallctl() result"); 12 assert_d_eq(mallctl("stats.resident", (void *)&resident, &sz, NULL, 0), 13 expected, "Unexpected mallctl() result"); 14 assert_d_eq(mallctl("stats.mapped", (void *)&mapped, &sz, NULL, 0), 15 expected, "Unexpected mallctl() result"); 16 17 if (config_stats) { 18 assert_zu_le(allocated, active, 19 "allocated should be no larger than active"); 20 assert_zu_lt(active, resident, 21 "active should be less than resident"); 22 assert_zu_lt(active, mapped, 23 "active should be less than mapped"); 24 } 25} 26TEST_END 27 28TEST_BEGIN(test_stats_large) { 29 void *p; 30 uint64_t epoch; 31 size_t allocated; 32 uint64_t nmalloc, ndalloc, nrequests; 33 size_t sz; 34 int expected = config_stats ? 0 : ENOENT; 35 36 p = mallocx(SMALL_MAXCLASS+1, MALLOCX_ARENA(0)); 37 assert_ptr_not_null(p, "Unexpected mallocx() failure"); 38 39 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 40 0, "Unexpected mallctl() failure"); 41 42 sz = sizeof(size_t); 43 assert_d_eq(mallctl("stats.arenas.0.large.allocated", 44 (void *)&allocated, &sz, NULL, 0), expected, 45 "Unexpected mallctl() result"); 46 sz = sizeof(uint64_t); 47 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc, 48 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 49 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc, 50 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 51 assert_d_eq(mallctl("stats.arenas.0.large.nrequests", 52 (void *)&nrequests, &sz, NULL, 0), expected, 53 "Unexpected mallctl() result"); 54 55 if (config_stats) { 56 assert_zu_gt(allocated, 0, 57 "allocated should be greater than zero"); 58 assert_u64_ge(nmalloc, ndalloc, 59 "nmalloc should be at least as large as ndalloc"); 60 assert_u64_le(nmalloc, nrequests, 61 "nmalloc should no larger than nrequests"); 62 } 63 64 dallocx(p, 0); 65} 66TEST_END 67 68TEST_BEGIN(test_stats_arenas_summary) { 69 void *little, *large; 70 uint64_t epoch; 71 size_t sz; 72 int expected = config_stats ? 0 : ENOENT; 73 size_t mapped; 74 uint64_t dirty_npurge, dirty_nmadvise, dirty_purged; 75 uint64_t muzzy_npurge, muzzy_nmadvise, muzzy_purged; 76 77 little = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0)); 78 assert_ptr_not_null(little, "Unexpected mallocx() failure"); 79 large = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0)); 80 assert_ptr_not_null(large, "Unexpected mallocx() failure"); 81 82 dallocx(little, 0); 83 dallocx(large, 0); 84 85 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 86 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result"); 87 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 88 "Unexpected mallctl() failure"); 89 90 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 91 0, "Unexpected mallctl() failure"); 92 93 sz = sizeof(size_t); 94 assert_d_eq(mallctl("stats.arenas.0.mapped", (void *)&mapped, &sz, NULL, 95 0), expected, "Unexepected mallctl() result"); 96 97 sz = sizeof(uint64_t); 98 assert_d_eq(mallctl("stats.arenas.0.dirty_npurge", 99 (void *)&dirty_npurge, &sz, NULL, 0), expected, 100 "Unexepected mallctl() result"); 101 assert_d_eq(mallctl("stats.arenas.0.dirty_nmadvise", 102 (void *)&dirty_nmadvise, &sz, NULL, 0), expected, 103 "Unexepected mallctl() result"); 104 assert_d_eq(mallctl("stats.arenas.0.dirty_purged", 105 (void *)&dirty_purged, &sz, NULL, 0), expected, 106 "Unexepected mallctl() result"); 107 assert_d_eq(mallctl("stats.arenas.0.muzzy_npurge", 108 (void *)&muzzy_npurge, &sz, NULL, 0), expected, 109 "Unexepected mallctl() result"); 110 assert_d_eq(mallctl("stats.arenas.0.muzzy_nmadvise", 111 (void *)&muzzy_nmadvise, &sz, NULL, 0), expected, 112 "Unexepected mallctl() result"); 113 assert_d_eq(mallctl("stats.arenas.0.muzzy_purged", 114 (void *)&muzzy_purged, &sz, NULL, 0), expected, 115 "Unexepected mallctl() result"); 116 117 if (config_stats) { 118 if (!background_thread_enabled()) { 119 assert_u64_gt(dirty_npurge + muzzy_npurge, 0, 120 "At least one purge should have occurred"); 121 } 122 assert_u64_le(dirty_nmadvise, dirty_purged, 123 "dirty_nmadvise should be no greater than dirty_purged"); 124 assert_u64_le(muzzy_nmadvise, muzzy_purged, 125 "muzzy_nmadvise should be no greater than muzzy_purged"); 126 } 127} 128TEST_END 129 130void * 131thd_start(void *arg) { 132 return NULL; 133} 134 135static void 136no_lazy_lock(void) { 137 thd_t thd; 138 139 thd_create(&thd, thd_start, NULL); 140 thd_join(thd, NULL); 141} 142 143TEST_BEGIN(test_stats_arenas_small) { 144 void *p; 145 size_t sz, allocated; 146 uint64_t epoch, nmalloc, ndalloc, nrequests; 147 int expected = config_stats ? 0 : ENOENT; 148 149 no_lazy_lock(); /* Lazy locking would dodge tcache testing. */ 150 151 p = mallocx(SMALL_MAXCLASS, MALLOCX_ARENA(0)); 152 assert_ptr_not_null(p, "Unexpected mallocx() failure"); 153 154 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 155 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result"); 156 157 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 158 0, "Unexpected mallctl() failure"); 159 160 sz = sizeof(size_t); 161 assert_d_eq(mallctl("stats.arenas.0.small.allocated", 162 (void *)&allocated, &sz, NULL, 0), expected, 163 "Unexpected mallctl() result"); 164 sz = sizeof(uint64_t); 165 assert_d_eq(mallctl("stats.arenas.0.small.nmalloc", (void *)&nmalloc, 166 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 167 assert_d_eq(mallctl("stats.arenas.0.small.ndalloc", (void *)&ndalloc, 168 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 169 assert_d_eq(mallctl("stats.arenas.0.small.nrequests", 170 (void *)&nrequests, &sz, NULL, 0), expected, 171 "Unexpected mallctl() result"); 172 173 if (config_stats) { 174 assert_zu_gt(allocated, 0, 175 "allocated should be greater than zero"); 176 assert_u64_gt(nmalloc, 0, 177 "nmalloc should be no greater than zero"); 178 assert_u64_ge(nmalloc, ndalloc, 179 "nmalloc should be at least as large as ndalloc"); 180 assert_u64_gt(nrequests, 0, 181 "nrequests should be greater than zero"); 182 } 183 184 dallocx(p, 0); 185} 186TEST_END 187 188TEST_BEGIN(test_stats_arenas_large) { 189 void *p; 190 size_t sz, allocated; 191 uint64_t epoch, nmalloc, ndalloc; 192 int expected = config_stats ? 0 : ENOENT; 193 194 p = mallocx((1U << LG_LARGE_MINCLASS), MALLOCX_ARENA(0)); 195 assert_ptr_not_null(p, "Unexpected mallocx() failure"); 196 197 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 198 0, "Unexpected mallctl() failure"); 199 200 sz = sizeof(size_t); 201 assert_d_eq(mallctl("stats.arenas.0.large.allocated", 202 (void *)&allocated, &sz, NULL, 0), expected, 203 "Unexpected mallctl() result"); 204 sz = sizeof(uint64_t); 205 assert_d_eq(mallctl("stats.arenas.0.large.nmalloc", (void *)&nmalloc, 206 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 207 assert_d_eq(mallctl("stats.arenas.0.large.ndalloc", (void *)&ndalloc, 208 &sz, NULL, 0), expected, "Unexpected mallctl() result"); 209 210 if (config_stats) { 211 assert_zu_gt(allocated, 0, 212 "allocated should be greater than zero"); 213 assert_u64_gt(nmalloc, 0, 214 "nmalloc should be greater than zero"); 215 assert_u64_ge(nmalloc, ndalloc, 216 "nmalloc should be at least as large as ndalloc"); 217 } 218 219 dallocx(p, 0); 220} 221TEST_END 222 223static void 224gen_mallctl_str(char *cmd, char *name, unsigned arena_ind) { 225 sprintf(cmd, "stats.arenas.%u.bins.0.%s", arena_ind, name); 226} 227 228TEST_BEGIN(test_stats_arenas_bins) { 229 void *p; 230 size_t sz, curslabs, curregs; 231 uint64_t epoch, nmalloc, ndalloc, nrequests, nfills, nflushes; 232 uint64_t nslabs, nreslabs; 233 int expected = config_stats ? 0 : ENOENT; 234 235 /* Make sure allocation below isn't satisfied by tcache. */ 236 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 237 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result"); 238 239 unsigned arena_ind, old_arena_ind; 240 sz = sizeof(unsigned); 241 assert_d_eq(mallctl("arenas.create", (void *)&arena_ind, &sz, NULL, 0), 242 0, "Arena creation failure"); 243 sz = sizeof(arena_ind); 244 assert_d_eq(mallctl("thread.arena", (void *)&old_arena_ind, &sz, 245 (void *)&arena_ind, sizeof(arena_ind)), 0, 246 "Unexpected mallctl() failure"); 247 248 p = malloc(bin_infos[0].reg_size); 249 assert_ptr_not_null(p, "Unexpected malloc() failure"); 250 251 assert_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 252 opt_tcache ? 0 : EFAULT, "Unexpected mallctl() result"); 253 254 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 255 0, "Unexpected mallctl() failure"); 256 257 char cmd[128]; 258 sz = sizeof(uint64_t); 259 gen_mallctl_str(cmd, "nmalloc", arena_ind); 260 assert_d_eq(mallctl(cmd, (void *)&nmalloc, &sz, NULL, 0), expected, 261 "Unexpected mallctl() result"); 262 gen_mallctl_str(cmd, "ndalloc", arena_ind); 263 assert_d_eq(mallctl(cmd, (void *)&ndalloc, &sz, NULL, 0), expected, 264 "Unexpected mallctl() result"); 265 gen_mallctl_str(cmd, "nrequests", arena_ind); 266 assert_d_eq(mallctl(cmd, (void *)&nrequests, &sz, NULL, 0), expected, 267 "Unexpected mallctl() result"); 268 sz = sizeof(size_t); 269 gen_mallctl_str(cmd, "curregs", arena_ind); 270 assert_d_eq(mallctl(cmd, (void *)&curregs, &sz, NULL, 0), expected, 271 "Unexpected mallctl() result"); 272 273 sz = sizeof(uint64_t); 274 gen_mallctl_str(cmd, "nfills", arena_ind); 275 assert_d_eq(mallctl(cmd, (void *)&nfills, &sz, NULL, 0), expected, 276 "Unexpected mallctl() result"); 277 gen_mallctl_str(cmd, "nflushes", arena_ind); 278 assert_d_eq(mallctl(cmd, (void *)&nflushes, &sz, NULL, 0), expected, 279 "Unexpected mallctl() result"); 280 281 gen_mallctl_str(cmd, "nslabs", arena_ind); 282 assert_d_eq(mallctl(cmd, (void *)&nslabs, &sz, NULL, 0), expected, 283 "Unexpected mallctl() result"); 284 gen_mallctl_str(cmd, "nreslabs", arena_ind); 285 assert_d_eq(mallctl(cmd, (void *)&nreslabs, &sz, NULL, 0), expected, 286 "Unexpected mallctl() result"); 287 sz = sizeof(size_t); 288 gen_mallctl_str(cmd, "curslabs", arena_ind); 289 assert_d_eq(mallctl(cmd, (void *)&curslabs, &sz, NULL, 0), expected, 290 "Unexpected mallctl() result"); 291 292 if (config_stats) { 293 assert_u64_gt(nmalloc, 0, 294 "nmalloc should be greater than zero"); 295 assert_u64_ge(nmalloc, ndalloc, 296 "nmalloc should be at least as large as ndalloc"); 297 assert_u64_gt(nrequests, 0, 298 "nrequests should be greater than zero"); 299 assert_zu_gt(curregs, 0, 300 "allocated should be greater than zero"); 301 if (opt_tcache) { 302 assert_u64_gt(nfills, 0, 303 "At least one fill should have occurred"); 304 assert_u64_gt(nflushes, 0, 305 "At least one flush should have occurred"); 306 } 307 assert_u64_gt(nslabs, 0, 308 "At least one slab should have been allocated"); 309 assert_zu_gt(curslabs, 0, 310 "At least one slab should be currently allocated"); 311 } 312 313 dallocx(p, 0); 314} 315TEST_END 316 317TEST_BEGIN(test_stats_arenas_lextents) { 318 void *p; 319 uint64_t epoch, nmalloc, ndalloc; 320 size_t curlextents, sz, hsize; 321 int expected = config_stats ? 0 : ENOENT; 322 323 sz = sizeof(size_t); 324 assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&hsize, &sz, NULL, 325 0), 0, "Unexpected mallctl() failure"); 326 327 p = mallocx(hsize, MALLOCX_ARENA(0)); 328 assert_ptr_not_null(p, "Unexpected mallocx() failure"); 329 330 assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)), 331 0, "Unexpected mallctl() failure"); 332 333 sz = sizeof(uint64_t); 334 assert_d_eq(mallctl("stats.arenas.0.lextents.0.nmalloc", 335 (void *)&nmalloc, &sz, NULL, 0), expected, 336 "Unexpected mallctl() result"); 337 assert_d_eq(mallctl("stats.arenas.0.lextents.0.ndalloc", 338 (void *)&ndalloc, &sz, NULL, 0), expected, 339 "Unexpected mallctl() result"); 340 sz = sizeof(size_t); 341 assert_d_eq(mallctl("stats.arenas.0.lextents.0.curlextents", 342 (void *)&curlextents, &sz, NULL, 0), expected, 343 "Unexpected mallctl() result"); 344 345 if (config_stats) { 346 assert_u64_gt(nmalloc, 0, 347 "nmalloc should be greater than zero"); 348 assert_u64_ge(nmalloc, ndalloc, 349 "nmalloc should be at least as large as ndalloc"); 350 assert_u64_gt(curlextents, 0, 351 "At least one extent should be currently allocated"); 352 } 353 354 dallocx(p, 0); 355} 356TEST_END 357 358int 359main(void) { 360 return test_no_reentrancy( 361 test_stats_summary, 362 test_stats_large, 363 test_stats_arenas_summary, 364 test_stats_arenas_small, 365 test_stats_arenas_large, 366 test_stats_arenas_bins, 367 test_stats_arenas_lextents); 368} 369