mallctl.c 12 KB

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