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