tcache_max.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "test/jemalloc_test.h"
  2. #include "test/san.h"
  3. const char *malloc_conf = TEST_SAN_UAF_ALIGN_DISABLE;
  4. enum {
  5. alloc_option_start = 0,
  6. use_malloc = 0,
  7. use_mallocx,
  8. alloc_option_end
  9. };
  10. enum {
  11. dalloc_option_start = 0,
  12. use_free = 0,
  13. use_dallocx,
  14. use_sdallocx,
  15. dalloc_option_end
  16. };
  17. static unsigned alloc_option, dalloc_option;
  18. static size_t tcache_max;
  19. static void *
  20. alloc_func(size_t sz) {
  21. void *ret;
  22. switch (alloc_option) {
  23. case use_malloc:
  24. ret = malloc(sz);
  25. break;
  26. case use_mallocx:
  27. ret = mallocx(sz, 0);
  28. break;
  29. default:
  30. unreachable();
  31. }
  32. expect_ptr_not_null(ret, "Unexpected malloc / mallocx failure");
  33. return ret;
  34. }
  35. static void
  36. dalloc_func(void *ptr, size_t sz) {
  37. switch (dalloc_option) {
  38. case use_free:
  39. free(ptr);
  40. break;
  41. case use_dallocx:
  42. dallocx(ptr, 0);
  43. break;
  44. case use_sdallocx:
  45. sdallocx(ptr, sz, 0);
  46. break;
  47. default:
  48. unreachable();
  49. }
  50. }
  51. static size_t
  52. tcache_bytes_read(void) {
  53. uint64_t epoch;
  54. assert_d_eq(mallctl("epoch", NULL, NULL, (void *)&epoch, sizeof(epoch)),
  55. 0, "Unexpected mallctl() failure");
  56. size_t tcache_bytes;
  57. size_t sz = sizeof(tcache_bytes);
  58. assert_d_eq(mallctl(
  59. "stats.arenas." STRINGIFY(MALLCTL_ARENAS_ALL) ".tcache_bytes",
  60. &tcache_bytes, &sz, NULL, 0), 0, "Unexpected mallctl failure");
  61. return tcache_bytes;
  62. }
  63. static void
  64. tcache_bytes_check_update(size_t *prev, ssize_t diff) {
  65. size_t tcache_bytes = tcache_bytes_read();
  66. expect_zu_eq(tcache_bytes, *prev + diff, "tcache bytes not expected");
  67. *prev += diff;
  68. }
  69. static void
  70. test_tcache_bytes_alloc(size_t alloc_size) {
  71. expect_d_eq(mallctl("thread.tcache.flush", NULL, NULL, NULL, 0), 0,
  72. "Unexpected tcache flush failure");
  73. size_t usize = sz_s2u(alloc_size);
  74. /* No change is expected if usize is outside of tcache_max range. */
  75. bool cached = (usize <= tcache_max);
  76. ssize_t diff = cached ? usize : 0;
  77. void *ptr1 = alloc_func(alloc_size);
  78. void *ptr2 = alloc_func(alloc_size);
  79. size_t bytes = tcache_bytes_read();
  80. dalloc_func(ptr2, alloc_size);
  81. /* Expect tcache_bytes increase after dalloc */
  82. tcache_bytes_check_update(&bytes, diff);
  83. dalloc_func(ptr1, alloc_size);
  84. /* Expect tcache_bytes increase again */
  85. tcache_bytes_check_update(&bytes, diff);
  86. void *ptr3 = alloc_func(alloc_size);
  87. if (cached) {
  88. expect_ptr_eq(ptr1, ptr3, "Unexpected cached ptr");
  89. }
  90. /* Expect tcache_bytes decrease after alloc */
  91. tcache_bytes_check_update(&bytes, -diff);
  92. void *ptr4 = alloc_func(alloc_size);
  93. if (cached) {
  94. expect_ptr_eq(ptr2, ptr4, "Unexpected cached ptr");
  95. }
  96. /* Expect tcache_bytes decrease again */
  97. tcache_bytes_check_update(&bytes, -diff);
  98. dalloc_func(ptr3, alloc_size);
  99. tcache_bytes_check_update(&bytes, diff);
  100. dalloc_func(ptr4, alloc_size);
  101. tcache_bytes_check_update(&bytes, diff);
  102. }
  103. static void
  104. test_tcache_max_impl(void) {
  105. size_t sz;
  106. sz = sizeof(tcache_max);
  107. assert_d_eq(mallctl("arenas.tcache_max", (void *)&tcache_max,
  108. &sz, NULL, 0), 0, "Unexpected mallctl() failure");
  109. /* opt.tcache_max set to 1024 in tcache_max.sh */
  110. expect_zu_eq(tcache_max, 1024, "tcache_max not expected");
  111. test_tcache_bytes_alloc(1);
  112. test_tcache_bytes_alloc(tcache_max - 1);
  113. test_tcache_bytes_alloc(tcache_max);
  114. test_tcache_bytes_alloc(tcache_max + 1);
  115. test_tcache_bytes_alloc(PAGE - 1);
  116. test_tcache_bytes_alloc(PAGE);
  117. test_tcache_bytes_alloc(PAGE + 1);
  118. size_t large;
  119. sz = sizeof(large);
  120. assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&large, &sz, NULL,
  121. 0), 0, "Unexpected mallctl() failure");
  122. test_tcache_bytes_alloc(large - 1);
  123. test_tcache_bytes_alloc(large);
  124. test_tcache_bytes_alloc(large + 1);
  125. }
  126. TEST_BEGIN(test_tcache_max) {
  127. test_skip_if(!config_stats);
  128. test_skip_if(!opt_tcache);
  129. test_skip_if(opt_prof);
  130. test_skip_if(san_uaf_detection_enabled());
  131. for (alloc_option = alloc_option_start;
  132. alloc_option < alloc_option_end;
  133. alloc_option++) {
  134. for (dalloc_option = dalloc_option_start;
  135. dalloc_option < dalloc_option_end;
  136. dalloc_option++) {
  137. test_tcache_max_impl();
  138. }
  139. }
  140. }
  141. TEST_END
  142. int
  143. main(void) {
  144. return test(test_tcache_max);
  145. }