1#include "test/jemalloc_test.h" 2 3TEST_BEGIN(test_mallctl_errors) 4{ 5 uint64_t epoch; 6 size_t sz; 7 8 assert_d_eq(mallctl("no_such_name", NULL, NULL, NULL, 0), ENOENT, 9 "mallctl() should return ENOENT for non-existent names"); 10 11 assert_d_eq(mallctl("version", NULL, NULL, "0.0.0", strlen("0.0.0")), 12 EPERM, "mallctl() should return EPERM on attempt to write " 13 "read-only value"); 14 15 assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)-1), 16 EINVAL, "mallctl() should return EINVAL for input size mismatch"); 17 assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)+1), 18 EINVAL, "mallctl() should return EINVAL for input size mismatch"); 19 20 sz = sizeof(epoch)-1; 21 assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, 22 "mallctl() should return EINVAL for output size mismatch"); 23 sz = sizeof(epoch)+1; 24 assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL, 25 "mallctl() should return EINVAL for output size mismatch"); 26} 27TEST_END 28 29TEST_BEGIN(test_mallctlnametomib_errors) 30{ 31 size_t mib[1]; 32 size_t miblen; 33 34 miblen = sizeof(mib)/sizeof(size_t); 35 assert_d_eq(mallctlnametomib("no_such_name", mib, &miblen), ENOENT, 36 "mallctlnametomib() should return ENOENT for non-existent names"); 37} 38TEST_END 39 40TEST_BEGIN(test_mallctlbymib_errors) 41{ 42 uint64_t epoch; 43 size_t sz; 44 size_t mib[1]; 45 size_t miblen; 46 47 miblen = sizeof(mib)/sizeof(size_t); 48 assert_d_eq(mallctlnametomib("version", mib, &miblen), 0, 49 "Unexpected mallctlnametomib() failure"); 50 51 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, "0.0.0", 52 strlen("0.0.0")), EPERM, "mallctl() should return EPERM on " 53 "attempt to write read-only value"); 54 55 miblen = sizeof(mib)/sizeof(size_t); 56 assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0, 57 "Unexpected mallctlnametomib() failure"); 58 59 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, 60 sizeof(epoch)-1), EINVAL, 61 "mallctlbymib() should return EINVAL for input size mismatch"); 62 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch, 63 sizeof(epoch)+1), EINVAL, 64 "mallctlbymib() should return EINVAL for input size mismatch"); 65 66 sz = sizeof(epoch)-1; 67 assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, 68 "mallctlbymib() should return EINVAL for output size mismatch"); 69 sz = sizeof(epoch)+1; 70 assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL, 71 "mallctlbymib() should return EINVAL for output size mismatch"); 72} 73TEST_END 74 75TEST_BEGIN(test_mallctl_read_write) 76{ 77 uint64_t old_epoch, new_epoch; 78 size_t sz = sizeof(old_epoch); 79 80 /* Blind. */ 81 assert_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0, 82 "Unexpected mallctl() failure"); 83 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 84 85 /* Read. */ 86 assert_d_eq(mallctl("epoch", &old_epoch, &sz, NULL, 0), 0, 87 "Unexpected mallctl() failure"); 88 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 89 90 /* Write. */ 91 assert_d_eq(mallctl("epoch", NULL, NULL, &new_epoch, sizeof(new_epoch)), 92 0, "Unexpected mallctl() failure"); 93 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 94 95 /* Read+write. */ 96 assert_d_eq(mallctl("epoch", &old_epoch, &sz, &new_epoch, 97 sizeof(new_epoch)), 0, "Unexpected mallctl() failure"); 98 assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size"); 99} 100TEST_END 101 102TEST_BEGIN(test_mallctlnametomib_short_mib) 103{ 104 size_t mib[4]; 105 size_t miblen; 106 107 miblen = 3; 108 mib[3] = 42; 109 assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0, 110 "Unexpected mallctlnametomib() failure"); 111 assert_zu_eq(miblen, 3, "Unexpected mib output length"); 112 assert_zu_eq(mib[3], 42, 113 "mallctlnametomib() wrote past the end of the input mib"); 114} 115TEST_END 116 117TEST_BEGIN(test_mallctl_config) 118{ 119 120#define TEST_MALLCTL_CONFIG(config, t) do { \ 121 t oldval; \ 122 size_t sz = sizeof(oldval); \ 123 assert_d_eq(mallctl("config."#config, &oldval, &sz, NULL, 0), \ 124 0, "Unexpected mallctl() failure"); \ 125 assert_b_eq(oldval, config_##config, "Incorrect config value"); \ 126 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ 127} while (0) 128 129 TEST_MALLCTL_CONFIG(cache_oblivious, bool); 130 TEST_MALLCTL_CONFIG(debug, bool); 131 TEST_MALLCTL_CONFIG(fill, bool); 132 TEST_MALLCTL_CONFIG(lazy_lock, bool); 133 TEST_MALLCTL_CONFIG(malloc_conf, const char *); 134 TEST_MALLCTL_CONFIG(munmap, bool); 135 TEST_MALLCTL_CONFIG(prof, bool); 136 TEST_MALLCTL_CONFIG(prof_libgcc, bool); 137 TEST_MALLCTL_CONFIG(prof_libunwind, bool); 138 TEST_MALLCTL_CONFIG(stats, bool); 139 TEST_MALLCTL_CONFIG(tcache, bool); 140 TEST_MALLCTL_CONFIG(tls, bool); 141 TEST_MALLCTL_CONFIG(utrace, bool); 142 TEST_MALLCTL_CONFIG(valgrind, bool); 143 TEST_MALLCTL_CONFIG(xmalloc, bool); 144 145#undef TEST_MALLCTL_CONFIG 146} 147TEST_END 148 149TEST_BEGIN(test_mallctl_opt) 150{ 151 bool config_always = true; 152 153#define TEST_MALLCTL_OPT(t, opt, config) do { \ 154 t oldval; \ 155 size_t sz = sizeof(oldval); \ 156 int expected = config_##config ? 0 : ENOENT; \ 157 int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \ 158 assert_d_eq(result, expected, \ 159 "Unexpected mallctl() result for opt."#opt); \ 160 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ 161} while (0) 162 163 TEST_MALLCTL_OPT(bool, abort, always); 164 TEST_MALLCTL_OPT(size_t, lg_chunk, always); 165 TEST_MALLCTL_OPT(const char *, dss, always); 166 TEST_MALLCTL_OPT(unsigned, narenas, always); 167 TEST_MALLCTL_OPT(const char *, purge, always); 168 TEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always); 169 TEST_MALLCTL_OPT(ssize_t, decay_time, always); 170 TEST_MALLCTL_OPT(bool, stats_print, always); 171 TEST_MALLCTL_OPT(const char *, junk, fill); 172 TEST_MALLCTL_OPT(size_t, quarantine, fill); 173 TEST_MALLCTL_OPT(bool, redzone, fill); 174 TEST_MALLCTL_OPT(bool, zero, fill); 175 TEST_MALLCTL_OPT(bool, utrace, utrace); 176 TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); 177 TEST_MALLCTL_OPT(bool, tcache, tcache); 178 TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache); 179 TEST_MALLCTL_OPT(bool, prof, prof); 180 TEST_MALLCTL_OPT(const char *, prof_prefix, prof); 181 TEST_MALLCTL_OPT(bool, prof_active, prof); 182 TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof); 183 TEST_MALLCTL_OPT(bool, prof_accum, prof); 184 TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof); 185 TEST_MALLCTL_OPT(bool, prof_gdump, prof); 186 TEST_MALLCTL_OPT(bool, prof_final, prof); 187 TEST_MALLCTL_OPT(bool, prof_leak, prof); 188 189#undef TEST_MALLCTL_OPT 190} 191TEST_END 192 193TEST_BEGIN(test_manpage_example) 194{ 195 unsigned nbins, i; 196 size_t mib[4]; 197 size_t len, miblen; 198 199 len = sizeof(nbins); 200 assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, 201 "Unexpected mallctl() failure"); 202 203 miblen = 4; 204 assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0, 205 "Unexpected mallctlnametomib() failure"); 206 for (i = 0; i < nbins; i++) { 207 size_t bin_size; 208 209 mib[2] = i; 210 len = sizeof(bin_size); 211 assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0), 212 0, "Unexpected mallctlbymib() failure"); 213 /* Do something with bin_size... */ 214 } 215} 216TEST_END 217 218TEST_BEGIN(test_tcache_none) 219{ 220 void *p0, *q, *p1; 221 222 test_skip_if(!config_tcache); 223 224 /* Allocate p and q. */ 225 p0 = mallocx(42, 0); 226 assert_ptr_not_null(p0, "Unexpected mallocx() failure"); 227 q = mallocx(42, 0); 228 assert_ptr_not_null(q, "Unexpected mallocx() failure"); 229 230 /* Deallocate p and q, but bypass the tcache for q. */ 231 dallocx(p0, 0); 232 dallocx(q, MALLOCX_TCACHE_NONE); 233 234 /* Make sure that tcache-based allocation returns p, not q. */ 235 p1 = mallocx(42, 0); 236 assert_ptr_not_null(p1, "Unexpected mallocx() failure"); 237 assert_ptr_eq(p0, p1, "Expected tcache to allocate cached region"); 238 239 /* Clean up. */ 240 dallocx(p1, MALLOCX_TCACHE_NONE); 241} 242TEST_END 243 244TEST_BEGIN(test_tcache) 245{ 246#define NTCACHES 10 247 unsigned tis[NTCACHES]; 248 void *ps[NTCACHES]; 249 void *qs[NTCACHES]; 250 unsigned i; 251 size_t sz, psz, qsz; 252 253 test_skip_if(!config_tcache); 254 255 psz = 42; 256 qsz = nallocx(psz, 0) + 1; 257 258 /* Create tcaches. */ 259 for (i = 0; i < NTCACHES; i++) { 260 sz = sizeof(unsigned); 261 assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0, 262 "Unexpected mallctl() failure, i=%u", i); 263 } 264 265 /* Exercise tcache ID recycling. */ 266 for (i = 0; i < NTCACHES; i++) { 267 assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i], 268 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", 269 i); 270 } 271 for (i = 0; i < NTCACHES; i++) { 272 sz = sizeof(unsigned); 273 assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0, 274 "Unexpected mallctl() failure, i=%u", i); 275 } 276 277 /* Flush empty tcaches. */ 278 for (i = 0; i < NTCACHES; i++) { 279 assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i], 280 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", 281 i); 282 } 283 284 /* Cache some allocations. */ 285 for (i = 0; i < NTCACHES; i++) { 286 ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); 287 assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", 288 i); 289 dallocx(ps[i], MALLOCX_TCACHE(tis[i])); 290 291 qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i])); 292 assert_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u", 293 i); 294 dallocx(qs[i], MALLOCX_TCACHE(tis[i])); 295 } 296 297 /* Verify that tcaches allocate cached regions. */ 298 for (i = 0; i < NTCACHES; i++) { 299 void *p0 = ps[i]; 300 ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i])); 301 assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u", 302 i); 303 assert_ptr_eq(ps[i], p0, 304 "Expected mallocx() to allocate cached region, i=%u", i); 305 } 306 307 /* Verify that reallocation uses cached regions. */ 308 for (i = 0; i < NTCACHES; i++) { 309 void *q0 = qs[i]; 310 qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i])); 311 assert_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u", 312 i); 313 assert_ptr_eq(qs[i], q0, 314 "Expected rallocx() to allocate cached region, i=%u", i); 315 /* Avoid undefined behavior in case of test failure. */ 316 if (qs[i] == NULL) 317 qs[i] = ps[i]; 318 } 319 for (i = 0; i < NTCACHES; i++) 320 dallocx(qs[i], MALLOCX_TCACHE(tis[i])); 321 322 /* Flush some non-empty tcaches. */ 323 for (i = 0; i < NTCACHES/2; i++) { 324 assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i], 325 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", 326 i); 327 } 328 329 /* Destroy tcaches. */ 330 for (i = 0; i < NTCACHES; i++) { 331 assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i], 332 sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u", 333 i); 334 } 335} 336TEST_END 337 338TEST_BEGIN(test_thread_arena) 339{ 340 unsigned arena_old, arena_new, narenas; 341 size_t sz = sizeof(unsigned); 342 343 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 344 "Unexpected mallctl() failure"); 345 assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); 346 arena_new = narenas - 1; 347 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 348 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 349 arena_new = 0; 350 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 351 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 352} 353TEST_END 354 355TEST_BEGIN(test_arena_i_lg_dirty_mult) 356{ 357 ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult; 358 size_t sz = sizeof(ssize_t); 359 360 test_skip_if(opt_purge != purge_mode_ratio); 361 362 assert_d_eq(mallctl("arena.0.lg_dirty_mult", &orig_lg_dirty_mult, &sz, 363 NULL, 0), 0, "Unexpected mallctl() failure"); 364 365 lg_dirty_mult = -2; 366 assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL, 367 &lg_dirty_mult, sizeof(ssize_t)), EFAULT, 368 "Unexpected mallctl() success"); 369 370 lg_dirty_mult = (sizeof(size_t) << 3); 371 assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL, 372 &lg_dirty_mult, sizeof(ssize_t)), EFAULT, 373 "Unexpected mallctl() success"); 374 375 for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1; 376 lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult 377 = lg_dirty_mult, lg_dirty_mult++) { 378 ssize_t old_lg_dirty_mult; 379 380 assert_d_eq(mallctl("arena.0.lg_dirty_mult", &old_lg_dirty_mult, 381 &sz, &lg_dirty_mult, sizeof(ssize_t)), 0, 382 "Unexpected mallctl() failure"); 383 assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult, 384 "Unexpected old arena.0.lg_dirty_mult"); 385 } 386} 387TEST_END 388 389TEST_BEGIN(test_arena_i_decay_time) 390{ 391 ssize_t decay_time, orig_decay_time, prev_decay_time; 392 size_t sz = sizeof(ssize_t); 393 394 test_skip_if(opt_purge != purge_mode_decay); 395 396 assert_d_eq(mallctl("arena.0.decay_time", &orig_decay_time, &sz, 397 NULL, 0), 0, "Unexpected mallctl() failure"); 398 399 decay_time = -2; 400 assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL, 401 &decay_time, sizeof(ssize_t)), EFAULT, 402 "Unexpected mallctl() success"); 403 404 decay_time = 0x7fffffff; 405 assert_d_eq(mallctl("arena.0.decay_time", NULL, NULL, 406 &decay_time, sizeof(ssize_t)), 0, 407 "Unexpected mallctl() failure"); 408 409 for (prev_decay_time = decay_time, decay_time = -1; 410 decay_time < 20; prev_decay_time = decay_time, decay_time++) { 411 ssize_t old_decay_time; 412 413 assert_d_eq(mallctl("arena.0.decay_time", &old_decay_time, 414 &sz, &decay_time, sizeof(ssize_t)), 0, 415 "Unexpected mallctl() failure"); 416 assert_zd_eq(old_decay_time, prev_decay_time, 417 "Unexpected old arena.0.decay_time"); 418 } 419} 420TEST_END 421 422TEST_BEGIN(test_arena_i_purge) 423{ 424 unsigned narenas; 425 size_t sz = sizeof(unsigned); 426 size_t mib[3]; 427 size_t miblen = 3; 428 429 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 430 "Unexpected mallctl() failure"); 431 432 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 433 "Unexpected mallctl() failure"); 434 assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0, 435 "Unexpected mallctlnametomib() failure"); 436 mib[1] = narenas; 437 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 438 "Unexpected mallctlbymib() failure"); 439} 440TEST_END 441 442TEST_BEGIN(test_arena_i_decay) 443{ 444 unsigned narenas; 445 size_t sz = sizeof(unsigned); 446 size_t mib[3]; 447 size_t miblen = 3; 448 449 assert_d_eq(mallctl("arena.0.decay", NULL, NULL, NULL, 0), 0, 450 "Unexpected mallctl() failure"); 451 452 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 453 "Unexpected mallctl() failure"); 454 assert_d_eq(mallctlnametomib("arena.0.decay", mib, &miblen), 0, 455 "Unexpected mallctlnametomib() failure"); 456 mib[1] = narenas; 457 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 458 "Unexpected mallctlbymib() failure"); 459} 460TEST_END 461 462TEST_BEGIN(test_arena_i_dss) 463{ 464 const char *dss_prec_old, *dss_prec_new; 465 size_t sz = sizeof(dss_prec_old); 466 size_t mib[3]; 467 size_t miblen; 468 469 miblen = sizeof(mib)/sizeof(size_t); 470 assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, 471 "Unexpected mallctlnametomib() error"); 472 473 dss_prec_new = "disabled"; 474 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, 475 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 476 assert_str_ne(dss_prec_old, "primary", 477 "Unexpected default for dss precedence"); 478 479 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, 480 sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure"); 481 482 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0, 483 "Unexpected mallctl() failure"); 484 assert_str_ne(dss_prec_old, "primary", 485 "Unexpected value for dss precedence"); 486 487 mib[1] = narenas_total_get(); 488 dss_prec_new = "disabled"; 489 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, 490 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 491 assert_str_ne(dss_prec_old, "primary", 492 "Unexpected default for dss precedence"); 493 494 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, 495 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 496 497 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0, 498 "Unexpected mallctl() failure"); 499 assert_str_ne(dss_prec_old, "primary", 500 "Unexpected value for dss precedence"); 501} 502TEST_END 503 504TEST_BEGIN(test_arenas_initialized) 505{ 506 unsigned narenas; 507 size_t sz = sizeof(narenas); 508 509 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 510 "Unexpected mallctl() failure"); 511 { 512 VARIABLE_ARRAY(bool, initialized, narenas); 513 514 sz = narenas * sizeof(bool); 515 assert_d_eq(mallctl("arenas.initialized", initialized, &sz, 516 NULL, 0), 0, "Unexpected mallctl() failure"); 517 } 518} 519TEST_END 520 521TEST_BEGIN(test_arenas_lg_dirty_mult) 522{ 523 ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult; 524 size_t sz = sizeof(ssize_t); 525 526 test_skip_if(opt_purge != purge_mode_ratio); 527 528 assert_d_eq(mallctl("arenas.lg_dirty_mult", &orig_lg_dirty_mult, &sz, 529 NULL, 0), 0, "Unexpected mallctl() failure"); 530 531 lg_dirty_mult = -2; 532 assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL, 533 &lg_dirty_mult, sizeof(ssize_t)), EFAULT, 534 "Unexpected mallctl() success"); 535 536 lg_dirty_mult = (sizeof(size_t) << 3); 537 assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL, 538 &lg_dirty_mult, sizeof(ssize_t)), EFAULT, 539 "Unexpected mallctl() success"); 540 541 for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1; 542 lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult = 543 lg_dirty_mult, lg_dirty_mult++) { 544 ssize_t old_lg_dirty_mult; 545 546 assert_d_eq(mallctl("arenas.lg_dirty_mult", &old_lg_dirty_mult, 547 &sz, &lg_dirty_mult, sizeof(ssize_t)), 0, 548 "Unexpected mallctl() failure"); 549 assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult, 550 "Unexpected old arenas.lg_dirty_mult"); 551 } 552} 553TEST_END 554 555TEST_BEGIN(test_arenas_decay_time) 556{ 557 ssize_t decay_time, orig_decay_time, prev_decay_time; 558 size_t sz = sizeof(ssize_t); 559 560 test_skip_if(opt_purge != purge_mode_decay); 561 562 assert_d_eq(mallctl("arenas.decay_time", &orig_decay_time, &sz, 563 NULL, 0), 0, "Unexpected mallctl() failure"); 564 565 decay_time = -2; 566 assert_d_eq(mallctl("arenas.decay_time", NULL, NULL, 567 &decay_time, sizeof(ssize_t)), EFAULT, 568 "Unexpected mallctl() success"); 569 570 decay_time = 0x7fffffff; 571 assert_d_eq(mallctl("arenas.decay_time", NULL, NULL, 572 &decay_time, sizeof(ssize_t)), 0, 573 "Expected mallctl() failure"); 574 575 for (prev_decay_time = decay_time, decay_time = -1; 576 decay_time < 20; prev_decay_time = decay_time, decay_time++) { 577 ssize_t old_decay_time; 578 579 assert_d_eq(mallctl("arenas.decay_time", &old_decay_time, 580 &sz, &decay_time, sizeof(ssize_t)), 0, 581 "Unexpected mallctl() failure"); 582 assert_zd_eq(old_decay_time, prev_decay_time, 583 "Unexpected old arenas.decay_time"); 584 } 585} 586TEST_END 587 588TEST_BEGIN(test_arenas_constants) 589{ 590 591#define TEST_ARENAS_CONSTANT(t, name, expected) do { \ 592 t name; \ 593 size_t sz = sizeof(t); \ 594 assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \ 595 "Unexpected mallctl() failure"); \ 596 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 597} while (0) 598 599 TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM); 600 TEST_ARENAS_CONSTANT(size_t, page, PAGE); 601 TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS); 602 TEST_ARENAS_CONSTANT(unsigned, nlruns, nlclasses); 603 TEST_ARENAS_CONSTANT(unsigned, nhchunks, nhclasses); 604 605#undef TEST_ARENAS_CONSTANT 606} 607TEST_END 608 609TEST_BEGIN(test_arenas_bin_constants) 610{ 611 612#define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \ 613 t name; \ 614 size_t sz = sizeof(t); \ 615 assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \ 616 0, "Unexpected mallctl() failure"); \ 617 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 618} while (0) 619 620 TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); 621 TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); 622 TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size); 623 624#undef TEST_ARENAS_BIN_CONSTANT 625} 626TEST_END 627 628TEST_BEGIN(test_arenas_lrun_constants) 629{ 630 631#define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \ 632 t name; \ 633 size_t sz = sizeof(t); \ 634 assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \ 635 0), 0, "Unexpected mallctl() failure"); \ 636 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 637} while (0) 638 639 TEST_ARENAS_LRUN_CONSTANT(size_t, size, LARGE_MINCLASS); 640 641#undef TEST_ARENAS_LRUN_CONSTANT 642} 643TEST_END 644 645TEST_BEGIN(test_arenas_hchunk_constants) 646{ 647 648#define TEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do { \ 649 t name; \ 650 size_t sz = sizeof(t); \ 651 assert_d_eq(mallctl("arenas.hchunk.0."#name, &name, &sz, NULL, \ 652 0), 0, "Unexpected mallctl() failure"); \ 653 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 654} while (0) 655 656 TEST_ARENAS_HCHUNK_CONSTANT(size_t, size, chunksize); 657 658#undef TEST_ARENAS_HCHUNK_CONSTANT 659} 660TEST_END 661 662TEST_BEGIN(test_arenas_extend) 663{ 664 unsigned narenas_before, arena, narenas_after; 665 size_t sz = sizeof(unsigned); 666 667 assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0, 668 "Unexpected mallctl() failure"); 669 assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0, 670 "Unexpected mallctl() failure"); 671 assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0, 672 "Unexpected mallctl() failure"); 673 674 assert_u_eq(narenas_before+1, narenas_after, 675 "Unexpected number of arenas before versus after extension"); 676 assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); 677} 678TEST_END 679 680TEST_BEGIN(test_stats_arenas) 681{ 682 683#define TEST_STATS_ARENAS(t, name) do { \ 684 t name; \ 685 size_t sz = sizeof(t); \ 686 assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \ 687 0), 0, "Unexpected mallctl() failure"); \ 688} while (0) 689 690 TEST_STATS_ARENAS(unsigned, nthreads); 691 TEST_STATS_ARENAS(const char *, dss); 692 TEST_STATS_ARENAS(ssize_t, lg_dirty_mult); 693 TEST_STATS_ARENAS(ssize_t, decay_time); 694 TEST_STATS_ARENAS(size_t, pactive); 695 TEST_STATS_ARENAS(size_t, pdirty); 696 697#undef TEST_STATS_ARENAS 698} 699TEST_END 700 701int 702main(void) 703{ 704 705 return (test( 706 test_mallctl_errors, 707 test_mallctlnametomib_errors, 708 test_mallctlbymib_errors, 709 test_mallctl_read_write, 710 test_mallctlnametomib_short_mib, 711 test_mallctl_config, 712 test_mallctl_opt, 713 test_manpage_example, 714 test_tcache_none, 715 test_tcache, 716 test_thread_arena, 717 test_arena_i_lg_dirty_mult, 718 test_arena_i_decay_time, 719 test_arena_i_purge, 720 test_arena_i_decay, 721 test_arena_i_dss, 722 test_arenas_initialized, 723 test_arenas_lg_dirty_mult, 724 test_arenas_decay_time, 725 test_arenas_constants, 726 test_arenas_bin_constants, 727 test_arenas_lrun_constants, 728 test_arenas_hchunk_constants, 729 test_arenas_extend, 730 test_stats_arenas)); 731} 732