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) do { \ 121 bool 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(debug); 130 TEST_MALLCTL_CONFIG(fill); 131 TEST_MALLCTL_CONFIG(lazy_lock); 132 TEST_MALLCTL_CONFIG(munmap); 133 TEST_MALLCTL_CONFIG(prof); 134 TEST_MALLCTL_CONFIG(prof_libgcc); 135 TEST_MALLCTL_CONFIG(prof_libunwind); 136 TEST_MALLCTL_CONFIG(stats); 137 TEST_MALLCTL_CONFIG(tcache); 138 TEST_MALLCTL_CONFIG(tls); 139 TEST_MALLCTL_CONFIG(utrace); 140 TEST_MALLCTL_CONFIG(valgrind); 141 TEST_MALLCTL_CONFIG(xmalloc); 142 143#undef TEST_MALLCTL_CONFIG 144} 145TEST_END 146 147TEST_BEGIN(test_mallctl_opt) 148{ 149 bool config_always = true; 150 151#define TEST_MALLCTL_OPT(t, opt, config) do { \ 152 t oldval; \ 153 size_t sz = sizeof(oldval); \ 154 int expected = config_##config ? 0 : ENOENT; \ 155 int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \ 156 assert_d_eq(result, expected, \ 157 "Unexpected mallctl() result for opt."#opt); \ 158 assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \ 159} while (0) 160 161 TEST_MALLCTL_OPT(bool, abort, always); 162 TEST_MALLCTL_OPT(size_t, lg_chunk, always); 163 TEST_MALLCTL_OPT(const char *, dss, always); 164 TEST_MALLCTL_OPT(size_t, narenas, always); 165 TEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always); 166 TEST_MALLCTL_OPT(bool, stats_print, always); 167 TEST_MALLCTL_OPT(bool, junk, fill); 168 TEST_MALLCTL_OPT(size_t, quarantine, fill); 169 TEST_MALLCTL_OPT(bool, redzone, fill); 170 TEST_MALLCTL_OPT(bool, zero, fill); 171 TEST_MALLCTL_OPT(bool, utrace, utrace); 172 TEST_MALLCTL_OPT(bool, xmalloc, xmalloc); 173 TEST_MALLCTL_OPT(bool, tcache, tcache); 174 TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache); 175 TEST_MALLCTL_OPT(bool, prof, prof); 176 TEST_MALLCTL_OPT(const char *, prof_prefix, prof); 177 TEST_MALLCTL_OPT(bool, prof_active, prof); 178 TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof); 179 TEST_MALLCTL_OPT(bool, prof_accum, prof); 180 TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof); 181 TEST_MALLCTL_OPT(bool, prof_gdump, prof); 182 TEST_MALLCTL_OPT(bool, prof_final, prof); 183 TEST_MALLCTL_OPT(bool, prof_leak, prof); 184 185#undef TEST_MALLCTL_OPT 186} 187TEST_END 188 189TEST_BEGIN(test_manpage_example) 190{ 191 unsigned nbins, i; 192 size_t mib[4]; 193 size_t len, miblen; 194 195 len = sizeof(nbins); 196 assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0, 197 "Unexpected mallctl() failure"); 198 199 miblen = 4; 200 assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0, 201 "Unexpected mallctlnametomib() failure"); 202 for (i = 0; i < nbins; i++) { 203 size_t bin_size; 204 205 mib[2] = i; 206 len = sizeof(bin_size); 207 assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0), 208 0, "Unexpected mallctlbymib() failure"); 209 /* Do something with bin_size... */ 210 } 211} 212TEST_END 213 214TEST_BEGIN(test_thread_arena) 215{ 216 unsigned arena_old, arena_new, narenas; 217 size_t sz = sizeof(unsigned); 218 219 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 220 "Unexpected mallctl() failure"); 221 assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect"); 222 arena_new = narenas - 1; 223 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 224 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 225 arena_new = 0; 226 assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new, 227 sizeof(unsigned)), 0, "Unexpected mallctl() failure"); 228} 229TEST_END 230 231TEST_BEGIN(test_arena_i_purge) 232{ 233 unsigned narenas; 234 size_t sz = sizeof(unsigned); 235 size_t mib[3]; 236 size_t miblen = 3; 237 238 assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0, 239 "Unexpected mallctl() failure"); 240 241 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 242 "Unexpected mallctl() failure"); 243 assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0, 244 "Unexpected mallctlnametomib() failure"); 245 mib[1] = narenas; 246 assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0, 247 "Unexpected mallctlbymib() failure"); 248} 249TEST_END 250 251TEST_BEGIN(test_arena_i_dss) 252{ 253 const char *dss_prec_old, *dss_prec_new; 254 size_t sz = sizeof(dss_prec_old); 255 size_t mib[3]; 256 size_t miblen; 257 258 miblen = sizeof(mib)/sizeof(size_t); 259 assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0, 260 "Unexpected mallctlnametomib() error"); 261 262 dss_prec_new = "disabled"; 263 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, 264 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 265 assert_str_ne(dss_prec_old, "primary", 266 "Unexpected default for dss precedence"); 267 268 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old, 269 sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure"); 270 271 mib[1] = narenas_total_get(); 272 dss_prec_new = "disabled"; 273 assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new, 274 sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure"); 275 assert_str_ne(dss_prec_old, "primary", 276 "Unexpected default for dss precedence"); 277} 278TEST_END 279 280TEST_BEGIN(test_arenas_initialized) 281{ 282 unsigned narenas; 283 size_t sz = sizeof(narenas); 284 285 assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0, 286 "Unexpected mallctl() failure"); 287 { 288 VARIABLE_ARRAY(bool, initialized, narenas); 289 290 sz = narenas * sizeof(bool); 291 assert_d_eq(mallctl("arenas.initialized", initialized, &sz, 292 NULL, 0), 0, "Unexpected mallctl() failure"); 293 } 294} 295TEST_END 296 297TEST_BEGIN(test_arenas_constants) 298{ 299 300#define TEST_ARENAS_CONSTANT(t, name, expected) do { \ 301 t name; \ 302 size_t sz = sizeof(t); \ 303 assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \ 304 "Unexpected mallctl() failure"); \ 305 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 306} while (0) 307 308 TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM); 309 TEST_ARENAS_CONSTANT(size_t, page, PAGE); 310 TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS); 311 TEST_ARENAS_CONSTANT(size_t, nlruns, nlclasses); 312 313#undef TEST_ARENAS_CONSTANT 314} 315TEST_END 316 317TEST_BEGIN(test_arenas_bin_constants) 318{ 319 320#define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \ 321 t name; \ 322 size_t sz = sizeof(t); \ 323 assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \ 324 0, "Unexpected mallctl() failure"); \ 325 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 326} while (0) 327 328 TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size); 329 TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs); 330 TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size); 331 332#undef TEST_ARENAS_BIN_CONSTANT 333} 334TEST_END 335 336TEST_BEGIN(test_arenas_lrun_constants) 337{ 338 339#define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \ 340 t name; \ 341 size_t sz = sizeof(t); \ 342 assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \ 343 0), 0, "Unexpected mallctl() failure"); \ 344 assert_zu_eq(name, expected, "Incorrect "#name" size"); \ 345} while (0) 346 347 TEST_ARENAS_LRUN_CONSTANT(size_t, size, (1 << LG_PAGE)); 348 349#undef TEST_ARENAS_LRUN_CONSTANT 350} 351TEST_END 352 353TEST_BEGIN(test_arenas_extend) 354{ 355 unsigned narenas_before, arena, narenas_after; 356 size_t sz = sizeof(unsigned); 357 358 assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0, 359 "Unexpected mallctl() failure"); 360 assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0, 361 "Unexpected mallctl() failure"); 362 assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0, 363 "Unexpected mallctl() failure"); 364 365 assert_u_eq(narenas_before+1, narenas_after, 366 "Unexpected number of arenas before versus after extension"); 367 assert_u_eq(arena, narenas_after-1, "Unexpected arena index"); 368} 369TEST_END 370 371TEST_BEGIN(test_stats_arenas) 372{ 373 374#define TEST_STATS_ARENAS(t, name) do { \ 375 t name; \ 376 size_t sz = sizeof(t); \ 377 assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \ 378 0), 0, "Unexpected mallctl() failure"); \ 379} while (0) 380 381 TEST_STATS_ARENAS(const char *, dss); 382 TEST_STATS_ARENAS(unsigned, nthreads); 383 TEST_STATS_ARENAS(size_t, pactive); 384 TEST_STATS_ARENAS(size_t, pdirty); 385 386#undef TEST_STATS_ARENAS 387} 388TEST_END 389 390int 391main(void) 392{ 393 394 return (test( 395 test_mallctl_errors, 396 test_mallctlnametomib_errors, 397 test_mallctlbymib_errors, 398 test_mallctl_read_write, 399 test_mallctlnametomib_short_mib, 400 test_mallctl_config, 401 test_mallctl_opt, 402 test_manpage_example, 403 test_thread_arena, 404 test_arena_i_purge, 405 test_arena_i_dss, 406 test_arenas_initialized, 407 test_arenas_constants, 408 test_arenas_bin_constants, 409 test_arenas_lrun_constants, 410 test_arenas_extend, 411 test_stats_arenas)); 412} 413