mallctl.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #include "test/jemalloc_test.h"
  2. TEST_BEGIN(test_mallctl_errors)
  3. {
  4. uint64_t epoch;
  5. size_t sz;
  6. assert_d_eq(mallctl("no_such_name", NULL, NULL, NULL, 0), ENOENT,
  7. "mallctl() should return ENOENT for non-existent names");
  8. assert_d_eq(mallctl("version", NULL, NULL, "0.0.0", strlen("0.0.0")),
  9. EPERM, "mallctl() should return EPERM on attempt to write "
  10. "read-only value");
  11. assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)-1),
  12. EINVAL, "mallctl() should return EINVAL for input size mismatch");
  13. assert_d_eq(mallctl("epoch", NULL, NULL, &epoch, sizeof(epoch)+1),
  14. EINVAL, "mallctl() should return EINVAL for input size mismatch");
  15. sz = sizeof(epoch)-1;
  16. assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL,
  17. "mallctl() should return EINVAL for output size mismatch");
  18. sz = sizeof(epoch)+1;
  19. assert_d_eq(mallctl("epoch", &epoch, &sz, NULL, 0), EINVAL,
  20. "mallctl() should return EINVAL for output size mismatch");
  21. }
  22. TEST_END
  23. TEST_BEGIN(test_mallctlnametomib_errors)
  24. {
  25. size_t mib[1];
  26. size_t miblen;
  27. miblen = sizeof(mib)/sizeof(size_t);
  28. assert_d_eq(mallctlnametomib("no_such_name", mib, &miblen), ENOENT,
  29. "mallctlnametomib() should return ENOENT for non-existent names");
  30. }
  31. TEST_END
  32. TEST_BEGIN(test_mallctlbymib_errors)
  33. {
  34. uint64_t epoch;
  35. size_t sz;
  36. size_t mib[1];
  37. size_t miblen;
  38. miblen = sizeof(mib)/sizeof(size_t);
  39. assert_d_eq(mallctlnametomib("version", mib, &miblen), 0,
  40. "Unexpected mallctlnametomib() failure");
  41. assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, "0.0.0",
  42. strlen("0.0.0")), EPERM, "mallctl() should return EPERM on "
  43. "attempt to write read-only value");
  44. miblen = sizeof(mib)/sizeof(size_t);
  45. assert_d_eq(mallctlnametomib("epoch", mib, &miblen), 0,
  46. "Unexpected mallctlnametomib() failure");
  47. assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,
  48. sizeof(epoch)-1), EINVAL,
  49. "mallctlbymib() should return EINVAL for input size mismatch");
  50. assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, &epoch,
  51. sizeof(epoch)+1), EINVAL,
  52. "mallctlbymib() should return EINVAL for input size mismatch");
  53. sz = sizeof(epoch)-1;
  54. assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,
  55. "mallctlbymib() should return EINVAL for output size mismatch");
  56. sz = sizeof(epoch)+1;
  57. assert_d_eq(mallctlbymib(mib, miblen, &epoch, &sz, NULL, 0), EINVAL,
  58. "mallctlbymib() should return EINVAL for output size mismatch");
  59. }
  60. TEST_END
  61. TEST_BEGIN(test_mallctl_read_write)
  62. {
  63. uint64_t old_epoch, new_epoch;
  64. size_t sz = sizeof(old_epoch);
  65. /* Blind. */
  66. assert_d_eq(mallctl("epoch", NULL, NULL, NULL, 0), 0,
  67. "Unexpected mallctl() failure");
  68. assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
  69. /* Read. */
  70. assert_d_eq(mallctl("epoch", &old_epoch, &sz, NULL, 0), 0,
  71. "Unexpected mallctl() failure");
  72. assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
  73. /* Write. */
  74. assert_d_eq(mallctl("epoch", NULL, NULL, &new_epoch, sizeof(new_epoch)),
  75. 0, "Unexpected mallctl() failure");
  76. assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
  77. /* Read+write. */
  78. assert_d_eq(mallctl("epoch", &old_epoch, &sz, &new_epoch,
  79. sizeof(new_epoch)), 0, "Unexpected mallctl() failure");
  80. assert_zu_eq(sz, sizeof(old_epoch), "Unexpected output size");
  81. }
  82. TEST_END
  83. TEST_BEGIN(test_mallctlnametomib_short_mib)
  84. {
  85. size_t mib[4];
  86. size_t miblen;
  87. miblen = 3;
  88. mib[3] = 42;
  89. assert_d_eq(mallctlnametomib("arenas.bin.0.nregs", mib, &miblen), 0,
  90. "Unexpected mallctlnametomib() failure");
  91. assert_zu_eq(miblen, 3, "Unexpected mib output length");
  92. assert_zu_eq(mib[3], 42,
  93. "mallctlnametomib() wrote past the end of the input mib");
  94. }
  95. TEST_END
  96. TEST_BEGIN(test_mallctl_config)
  97. {
  98. #define TEST_MALLCTL_CONFIG(config) do { \
  99. bool oldval; \
  100. size_t sz = sizeof(oldval); \
  101. assert_d_eq(mallctl("config."#config, &oldval, &sz, NULL, 0), \
  102. 0, "Unexpected mallctl() failure"); \
  103. assert_b_eq(oldval, config_##config, "Incorrect config value"); \
  104. assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
  105. } while (0)
  106. TEST_MALLCTL_CONFIG(cache_oblivious);
  107. TEST_MALLCTL_CONFIG(debug);
  108. TEST_MALLCTL_CONFIG(fill);
  109. TEST_MALLCTL_CONFIG(lazy_lock);
  110. TEST_MALLCTL_CONFIG(munmap);
  111. TEST_MALLCTL_CONFIG(prof);
  112. TEST_MALLCTL_CONFIG(prof_libgcc);
  113. TEST_MALLCTL_CONFIG(prof_libunwind);
  114. TEST_MALLCTL_CONFIG(stats);
  115. TEST_MALLCTL_CONFIG(tcache);
  116. TEST_MALLCTL_CONFIG(tls);
  117. TEST_MALLCTL_CONFIG(utrace);
  118. TEST_MALLCTL_CONFIG(valgrind);
  119. TEST_MALLCTL_CONFIG(xmalloc);
  120. #undef TEST_MALLCTL_CONFIG
  121. }
  122. TEST_END
  123. TEST_BEGIN(test_mallctl_opt)
  124. {
  125. bool config_always = true;
  126. #define TEST_MALLCTL_OPT(t, opt, config) do { \
  127. t oldval; \
  128. size_t sz = sizeof(oldval); \
  129. int expected = config_##config ? 0 : ENOENT; \
  130. int result = mallctl("opt."#opt, &oldval, &sz, NULL, 0); \
  131. assert_d_eq(result, expected, \
  132. "Unexpected mallctl() result for opt."#opt); \
  133. assert_zu_eq(sz, sizeof(oldval), "Unexpected output size"); \
  134. } while (0)
  135. TEST_MALLCTL_OPT(bool, abort, always);
  136. TEST_MALLCTL_OPT(size_t, lg_chunk, always);
  137. TEST_MALLCTL_OPT(const char *, dss, always);
  138. TEST_MALLCTL_OPT(size_t, narenas, always);
  139. TEST_MALLCTL_OPT(ssize_t, lg_dirty_mult, always);
  140. TEST_MALLCTL_OPT(bool, stats_print, always);
  141. TEST_MALLCTL_OPT(const char *, junk, fill);
  142. TEST_MALLCTL_OPT(size_t, quarantine, fill);
  143. TEST_MALLCTL_OPT(bool, redzone, fill);
  144. TEST_MALLCTL_OPT(bool, zero, fill);
  145. TEST_MALLCTL_OPT(bool, utrace, utrace);
  146. TEST_MALLCTL_OPT(bool, xmalloc, xmalloc);
  147. TEST_MALLCTL_OPT(bool, tcache, tcache);
  148. TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);
  149. TEST_MALLCTL_OPT(bool, prof, prof);
  150. TEST_MALLCTL_OPT(const char *, prof_prefix, prof);
  151. TEST_MALLCTL_OPT(bool, prof_active, prof);
  152. TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
  153. TEST_MALLCTL_OPT(bool, prof_accum, prof);
  154. TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
  155. TEST_MALLCTL_OPT(bool, prof_gdump, prof);
  156. TEST_MALLCTL_OPT(bool, prof_final, prof);
  157. TEST_MALLCTL_OPT(bool, prof_leak, prof);
  158. #undef TEST_MALLCTL_OPT
  159. }
  160. TEST_END
  161. TEST_BEGIN(test_manpage_example)
  162. {
  163. unsigned nbins, i;
  164. size_t mib[4];
  165. size_t len, miblen;
  166. len = sizeof(nbins);
  167. assert_d_eq(mallctl("arenas.nbins", &nbins, &len, NULL, 0), 0,
  168. "Unexpected mallctl() failure");
  169. miblen = 4;
  170. assert_d_eq(mallctlnametomib("arenas.bin.0.size", mib, &miblen), 0,
  171. "Unexpected mallctlnametomib() failure");
  172. for (i = 0; i < nbins; i++) {
  173. size_t bin_size;
  174. mib[2] = i;
  175. len = sizeof(bin_size);
  176. assert_d_eq(mallctlbymib(mib, miblen, &bin_size, &len, NULL, 0),
  177. 0, "Unexpected mallctlbymib() failure");
  178. /* Do something with bin_size... */
  179. }
  180. }
  181. TEST_END
  182. TEST_BEGIN(test_tcache_none)
  183. {
  184. void *p0, *q, *p1;
  185. test_skip_if(!config_tcache);
  186. /* Allocate p and q. */
  187. p0 = mallocx(42, 0);
  188. assert_ptr_not_null(p0, "Unexpected mallocx() failure");
  189. q = mallocx(42, 0);
  190. assert_ptr_not_null(q, "Unexpected mallocx() failure");
  191. /* Deallocate p and q, but bypass the tcache for q. */
  192. dallocx(p0, 0);
  193. dallocx(q, MALLOCX_TCACHE_NONE);
  194. /* Make sure that tcache-based allocation returns p, not q. */
  195. p1 = mallocx(42, 0);
  196. assert_ptr_not_null(p1, "Unexpected mallocx() failure");
  197. assert_ptr_eq(p0, p1, "Expected tcache to allocate cached region");
  198. /* Clean up. */
  199. dallocx(p1, MALLOCX_TCACHE_NONE);
  200. }
  201. TEST_END
  202. TEST_BEGIN(test_tcache)
  203. {
  204. #define NTCACHES 10
  205. unsigned tis[NTCACHES];
  206. void *ps[NTCACHES];
  207. void *qs[NTCACHES];
  208. unsigned i;
  209. size_t sz, psz, qsz;
  210. test_skip_if(!config_tcache);
  211. psz = 42;
  212. qsz = nallocx(psz, 0) + 1;
  213. /* Create tcaches. */
  214. for (i = 0; i < NTCACHES; i++) {
  215. sz = sizeof(unsigned);
  216. assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0,
  217. "Unexpected mallctl() failure, i=%u", i);
  218. }
  219. /* Exercise tcache ID recycling. */
  220. for (i = 0; i < NTCACHES; i++) {
  221. assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i],
  222. sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
  223. i);
  224. }
  225. for (i = 0; i < NTCACHES; i++) {
  226. sz = sizeof(unsigned);
  227. assert_d_eq(mallctl("tcache.create", &tis[i], &sz, NULL, 0), 0,
  228. "Unexpected mallctl() failure, i=%u", i);
  229. }
  230. /* Flush empty tcaches. */
  231. for (i = 0; i < NTCACHES; i++) {
  232. assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i],
  233. sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
  234. i);
  235. }
  236. /* Cache some allocations. */
  237. for (i = 0; i < NTCACHES; i++) {
  238. ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
  239. assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
  240. i);
  241. dallocx(ps[i], MALLOCX_TCACHE(tis[i]));
  242. qs[i] = mallocx(qsz, MALLOCX_TCACHE(tis[i]));
  243. assert_ptr_not_null(qs[i], "Unexpected mallocx() failure, i=%u",
  244. i);
  245. dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
  246. }
  247. /* Verify that tcaches allocate cached regions. */
  248. for (i = 0; i < NTCACHES; i++) {
  249. void *p0 = ps[i];
  250. ps[i] = mallocx(psz, MALLOCX_TCACHE(tis[i]));
  251. assert_ptr_not_null(ps[i], "Unexpected mallocx() failure, i=%u",
  252. i);
  253. assert_ptr_eq(ps[i], p0,
  254. "Expected mallocx() to allocate cached region, i=%u", i);
  255. }
  256. /* Verify that reallocation uses cached regions. */
  257. for (i = 0; i < NTCACHES; i++) {
  258. void *q0 = qs[i];
  259. qs[i] = rallocx(ps[i], qsz, MALLOCX_TCACHE(tis[i]));
  260. assert_ptr_not_null(qs[i], "Unexpected rallocx() failure, i=%u",
  261. i);
  262. assert_ptr_eq(qs[i], q0,
  263. "Expected rallocx() to allocate cached region, i=%u", i);
  264. /* Avoid undefined behavior in case of test failure. */
  265. if (qs[i] == NULL)
  266. qs[i] = ps[i];
  267. }
  268. for (i = 0; i < NTCACHES; i++)
  269. dallocx(qs[i], MALLOCX_TCACHE(tis[i]));
  270. /* Flush some non-empty tcaches. */
  271. for (i = 0; i < NTCACHES/2; i++) {
  272. assert_d_eq(mallctl("tcache.flush", NULL, NULL, &tis[i],
  273. sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
  274. i);
  275. }
  276. /* Destroy tcaches. */
  277. for (i = 0; i < NTCACHES; i++) {
  278. assert_d_eq(mallctl("tcache.destroy", NULL, NULL, &tis[i],
  279. sizeof(unsigned)), 0, "Unexpected mallctl() failure, i=%u",
  280. i);
  281. }
  282. }
  283. TEST_END
  284. TEST_BEGIN(test_thread_arena)
  285. {
  286. unsigned arena_old, arena_new, narenas;
  287. size_t sz = sizeof(unsigned);
  288. assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
  289. "Unexpected mallctl() failure");
  290. assert_u_eq(narenas, opt_narenas, "Number of arenas incorrect");
  291. arena_new = narenas - 1;
  292. assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new,
  293. sizeof(unsigned)), 0, "Unexpected mallctl() failure");
  294. arena_new = 0;
  295. assert_d_eq(mallctl("thread.arena", &arena_old, &sz, &arena_new,
  296. sizeof(unsigned)), 0, "Unexpected mallctl() failure");
  297. }
  298. TEST_END
  299. TEST_BEGIN(test_arena_i_lg_dirty_mult)
  300. {
  301. ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;
  302. size_t sz = sizeof(ssize_t);
  303. assert_d_eq(mallctl("arena.0.lg_dirty_mult", &orig_lg_dirty_mult, &sz,
  304. NULL, 0), 0, "Unexpected mallctl() failure");
  305. lg_dirty_mult = -2;
  306. assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
  307. &lg_dirty_mult, sizeof(ssize_t)), EFAULT,
  308. "Unexpected mallctl() success");
  309. lg_dirty_mult = (sizeof(size_t) << 3);
  310. assert_d_eq(mallctl("arena.0.lg_dirty_mult", NULL, NULL,
  311. &lg_dirty_mult, sizeof(ssize_t)), EFAULT,
  312. "Unexpected mallctl() success");
  313. for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
  314. lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult
  315. = lg_dirty_mult, lg_dirty_mult++) {
  316. ssize_t old_lg_dirty_mult;
  317. assert_d_eq(mallctl("arena.0.lg_dirty_mult", &old_lg_dirty_mult,
  318. &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,
  319. "Unexpected mallctl() failure");
  320. assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
  321. "Unexpected old arena.0.lg_dirty_mult");
  322. }
  323. }
  324. TEST_END
  325. TEST_BEGIN(test_arena_i_purge)
  326. {
  327. unsigned narenas;
  328. size_t sz = sizeof(unsigned);
  329. size_t mib[3];
  330. size_t miblen = 3;
  331. assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
  332. "Unexpected mallctl() failure");
  333. assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
  334. "Unexpected mallctl() failure");
  335. assert_d_eq(mallctlnametomib("arena.0.purge", mib, &miblen), 0,
  336. "Unexpected mallctlnametomib() failure");
  337. mib[1] = narenas;
  338. assert_d_eq(mallctlbymib(mib, miblen, NULL, NULL, NULL, 0), 0,
  339. "Unexpected mallctlbymib() failure");
  340. }
  341. TEST_END
  342. TEST_BEGIN(test_arena_i_dss)
  343. {
  344. const char *dss_prec_old, *dss_prec_new;
  345. size_t sz = sizeof(dss_prec_old);
  346. size_t mib[3];
  347. size_t miblen;
  348. miblen = sizeof(mib)/sizeof(size_t);
  349. assert_d_eq(mallctlnametomib("arena.0.dss", mib, &miblen), 0,
  350. "Unexpected mallctlnametomib() error");
  351. dss_prec_new = "disabled";
  352. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,
  353. sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
  354. assert_str_ne(dss_prec_old, "primary",
  355. "Unexpected default for dss precedence");
  356. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,
  357. sizeof(dss_prec_old)), 0, "Unexpected mallctl() failure");
  358. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,
  359. "Unexpected mallctl() failure");
  360. assert_str_ne(dss_prec_old, "primary",
  361. "Unexpected value for dss precedence");
  362. mib[1] = narenas_total_get();
  363. dss_prec_new = "disabled";
  364. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, &dss_prec_new,
  365. sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
  366. assert_str_ne(dss_prec_old, "primary",
  367. "Unexpected default for dss precedence");
  368. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_new, &sz, &dss_prec_old,
  369. sizeof(dss_prec_new)), 0, "Unexpected mallctl() failure");
  370. assert_d_eq(mallctlbymib(mib, miblen, &dss_prec_old, &sz, NULL, 0), 0,
  371. "Unexpected mallctl() failure");
  372. assert_str_ne(dss_prec_old, "primary",
  373. "Unexpected value for dss precedence");
  374. }
  375. TEST_END
  376. TEST_BEGIN(test_arenas_initialized)
  377. {
  378. unsigned narenas;
  379. size_t sz = sizeof(narenas);
  380. assert_d_eq(mallctl("arenas.narenas", &narenas, &sz, NULL, 0), 0,
  381. "Unexpected mallctl() failure");
  382. {
  383. VARIABLE_ARRAY(bool, initialized, narenas);
  384. sz = narenas * sizeof(bool);
  385. assert_d_eq(mallctl("arenas.initialized", initialized, &sz,
  386. NULL, 0), 0, "Unexpected mallctl() failure");
  387. }
  388. }
  389. TEST_END
  390. TEST_BEGIN(test_arenas_lg_dirty_mult)
  391. {
  392. ssize_t lg_dirty_mult, orig_lg_dirty_mult, prev_lg_dirty_mult;
  393. size_t sz = sizeof(ssize_t);
  394. assert_d_eq(mallctl("arenas.lg_dirty_mult", &orig_lg_dirty_mult, &sz,
  395. NULL, 0), 0, "Unexpected mallctl() failure");
  396. lg_dirty_mult = -2;
  397. assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
  398. &lg_dirty_mult, sizeof(ssize_t)), EFAULT,
  399. "Unexpected mallctl() success");
  400. lg_dirty_mult = (sizeof(size_t) << 3);
  401. assert_d_eq(mallctl("arenas.lg_dirty_mult", NULL, NULL,
  402. &lg_dirty_mult, sizeof(ssize_t)), EFAULT,
  403. "Unexpected mallctl() success");
  404. for (prev_lg_dirty_mult = orig_lg_dirty_mult, lg_dirty_mult = -1;
  405. lg_dirty_mult < (ssize_t)(sizeof(size_t) << 3); prev_lg_dirty_mult =
  406. lg_dirty_mult, lg_dirty_mult++) {
  407. ssize_t old_lg_dirty_mult;
  408. assert_d_eq(mallctl("arenas.lg_dirty_mult", &old_lg_dirty_mult,
  409. &sz, &lg_dirty_mult, sizeof(ssize_t)), 0,
  410. "Unexpected mallctl() failure");
  411. assert_zd_eq(old_lg_dirty_mult, prev_lg_dirty_mult,
  412. "Unexpected old arenas.lg_dirty_mult");
  413. }
  414. }
  415. TEST_END
  416. TEST_BEGIN(test_arenas_constants)
  417. {
  418. #define TEST_ARENAS_CONSTANT(t, name, expected) do { \
  419. t name; \
  420. size_t sz = sizeof(t); \
  421. assert_d_eq(mallctl("arenas."#name, &name, &sz, NULL, 0), 0, \
  422. "Unexpected mallctl() failure"); \
  423. assert_zu_eq(name, expected, "Incorrect "#name" size"); \
  424. } while (0)
  425. TEST_ARENAS_CONSTANT(size_t, quantum, QUANTUM);
  426. TEST_ARENAS_CONSTANT(size_t, page, PAGE);
  427. TEST_ARENAS_CONSTANT(unsigned, nbins, NBINS);
  428. TEST_ARENAS_CONSTANT(unsigned, nlruns, nlclasses);
  429. TEST_ARENAS_CONSTANT(unsigned, nhchunks, nhclasses);
  430. #undef TEST_ARENAS_CONSTANT
  431. }
  432. TEST_END
  433. TEST_BEGIN(test_arenas_bin_constants)
  434. {
  435. #define TEST_ARENAS_BIN_CONSTANT(t, name, expected) do { \
  436. t name; \
  437. size_t sz = sizeof(t); \
  438. assert_d_eq(mallctl("arenas.bin.0."#name, &name, &sz, NULL, 0), \
  439. 0, "Unexpected mallctl() failure"); \
  440. assert_zu_eq(name, expected, "Incorrect "#name" size"); \
  441. } while (0)
  442. TEST_ARENAS_BIN_CONSTANT(size_t, size, arena_bin_info[0].reg_size);
  443. TEST_ARENAS_BIN_CONSTANT(uint32_t, nregs, arena_bin_info[0].nregs);
  444. TEST_ARENAS_BIN_CONSTANT(size_t, run_size, arena_bin_info[0].run_size);
  445. #undef TEST_ARENAS_BIN_CONSTANT
  446. }
  447. TEST_END
  448. TEST_BEGIN(test_arenas_lrun_constants)
  449. {
  450. #define TEST_ARENAS_LRUN_CONSTANT(t, name, expected) do { \
  451. t name; \
  452. size_t sz = sizeof(t); \
  453. assert_d_eq(mallctl("arenas.lrun.0."#name, &name, &sz, NULL, \
  454. 0), 0, "Unexpected mallctl() failure"); \
  455. assert_zu_eq(name, expected, "Incorrect "#name" size"); \
  456. } while (0)
  457. TEST_ARENAS_LRUN_CONSTANT(size_t, size, LARGE_MINCLASS);
  458. #undef TEST_ARENAS_LRUN_CONSTANT
  459. }
  460. TEST_END
  461. TEST_BEGIN(test_arenas_hchunk_constants)
  462. {
  463. #define TEST_ARENAS_HCHUNK_CONSTANT(t, name, expected) do { \
  464. t name; \
  465. size_t sz = sizeof(t); \
  466. assert_d_eq(mallctl("arenas.hchunk.0."#name, &name, &sz, NULL, \
  467. 0), 0, "Unexpected mallctl() failure"); \
  468. assert_zu_eq(name, expected, "Incorrect "#name" size"); \
  469. } while (0)
  470. TEST_ARENAS_HCHUNK_CONSTANT(size_t, size, chunksize);
  471. #undef TEST_ARENAS_HCHUNK_CONSTANT
  472. }
  473. TEST_END
  474. TEST_BEGIN(test_arenas_extend)
  475. {
  476. unsigned narenas_before, arena, narenas_after;
  477. size_t sz = sizeof(unsigned);
  478. assert_d_eq(mallctl("arenas.narenas", &narenas_before, &sz, NULL, 0), 0,
  479. "Unexpected mallctl() failure");
  480. assert_d_eq(mallctl("arenas.extend", &arena, &sz, NULL, 0), 0,
  481. "Unexpected mallctl() failure");
  482. assert_d_eq(mallctl("arenas.narenas", &narenas_after, &sz, NULL, 0), 0,
  483. "Unexpected mallctl() failure");
  484. assert_u_eq(narenas_before+1, narenas_after,
  485. "Unexpected number of arenas before versus after extension");
  486. assert_u_eq(arena, narenas_after-1, "Unexpected arena index");
  487. }
  488. TEST_END
  489. TEST_BEGIN(test_stats_arenas)
  490. {
  491. #define TEST_STATS_ARENAS(t, name) do { \
  492. t name; \
  493. size_t sz = sizeof(t); \
  494. assert_d_eq(mallctl("stats.arenas.0."#name, &name, &sz, NULL, \
  495. 0), 0, "Unexpected mallctl() failure"); \
  496. } while (0)
  497. TEST_STATS_ARENAS(const char *, dss);
  498. TEST_STATS_ARENAS(unsigned, nthreads);
  499. TEST_STATS_ARENAS(size_t, pactive);
  500. TEST_STATS_ARENAS(size_t, pdirty);
  501. #undef TEST_STATS_ARENAS
  502. }
  503. TEST_END
  504. int
  505. main(void)
  506. {
  507. return (test(
  508. test_mallctl_errors,
  509. test_mallctlnametomib_errors,
  510. test_mallctlbymib_errors,
  511. test_mallctl_read_write,
  512. test_mallctlnametomib_short_mib,
  513. test_mallctl_config,
  514. test_mallctl_opt,
  515. test_manpage_example,
  516. test_tcache_none,
  517. test_tcache,
  518. test_thread_arena,
  519. test_arena_i_lg_dirty_mult,
  520. test_arena_i_purge,
  521. test_arena_i_dss,
  522. test_arenas_initialized,
  523. test_arenas_lg_dirty_mult,
  524. test_arenas_constants,
  525. test_arenas_bin_constants,
  526. test_arenas_lrun_constants,
  527. test_arenas_hchunk_constants,
  528. test_arenas_extend,
  529. test_stats_arenas));
  530. }