mallocx.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #include "test/jemalloc_test.h"
  2. static unsigned
  3. get_nsizes_impl(const char *cmd) {
  4. unsigned ret;
  5. size_t z;
  6. z = sizeof(unsigned);
  7. assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
  8. "Unexpected mallctl(\"%s\", ...) failure", cmd);
  9. return ret;
  10. }
  11. static unsigned
  12. get_nlarge(void) {
  13. return get_nsizes_impl("arenas.nlextents");
  14. }
  15. static size_t
  16. get_size_impl(const char *cmd, size_t ind) {
  17. size_t ret;
  18. size_t z;
  19. size_t mib[4];
  20. size_t miblen = 4;
  21. z = sizeof(size_t);
  22. assert_d_eq(mallctlnametomib(cmd, mib, &miblen),
  23. 0, "Unexpected mallctlnametomib(\"%s\", ...) failure", cmd);
  24. mib[2] = ind;
  25. z = sizeof(size_t);
  26. assert_d_eq(mallctlbymib(mib, miblen, (void *)&ret, &z, NULL, 0),
  27. 0, "Unexpected mallctlbymib([\"%s\", %zu], ...) failure", cmd, ind);
  28. return ret;
  29. }
  30. static size_t
  31. get_large_size(size_t ind) {
  32. return get_size_impl("arenas.lextent.0.size", ind);
  33. }
  34. /*
  35. * On systems which can't merge extents, tests that call this function generate
  36. * a lot of dirty memory very quickly. Purging between cycles mitigates
  37. * potential OOM on e.g. 32-bit Windows.
  38. */
  39. static void
  40. purge(void) {
  41. assert_d_eq(mallctl("arena.0.purge", NULL, NULL, NULL, 0), 0,
  42. "Unexpected mallctl error");
  43. }
  44. TEST_BEGIN(test_overflow) {
  45. size_t largemax;
  46. largemax = get_large_size(get_nlarge()-1);
  47. assert_ptr_null(mallocx(largemax+1, 0),
  48. "Expected OOM for mallocx(size=%#zx, 0)", largemax+1);
  49. assert_ptr_null(mallocx(ZU(PTRDIFF_MAX)+1, 0),
  50. "Expected OOM for mallocx(size=%#zx, 0)", ZU(PTRDIFF_MAX)+1);
  51. assert_ptr_null(mallocx(SIZE_T_MAX, 0),
  52. "Expected OOM for mallocx(size=%#zx, 0)", SIZE_T_MAX);
  53. assert_ptr_null(mallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),
  54. "Expected OOM for mallocx(size=1, MALLOCX_ALIGN(%#zx))",
  55. ZU(PTRDIFF_MAX)+1);
  56. }
  57. TEST_END
  58. TEST_BEGIN(test_oom) {
  59. size_t largemax;
  60. bool oom;
  61. void *ptrs[3];
  62. unsigned i;
  63. /*
  64. * It should be impossible to allocate three objects that each consume
  65. * nearly half the virtual address space.
  66. */
  67. largemax = get_large_size(get_nlarge()-1);
  68. oom = false;
  69. for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
  70. ptrs[i] = mallocx(largemax, 0);
  71. if (ptrs[i] == NULL) {
  72. oom = true;
  73. }
  74. }
  75. assert_true(oom,
  76. "Expected OOM during series of calls to mallocx(size=%zu, 0)",
  77. largemax);
  78. for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
  79. if (ptrs[i] != NULL) {
  80. dallocx(ptrs[i], 0);
  81. }
  82. }
  83. purge();
  84. #if LG_SIZEOF_PTR == 3
  85. assert_ptr_null(mallocx(0x8000000000000000ULL,
  86. MALLOCX_ALIGN(0x8000000000000000ULL)),
  87. "Expected OOM for mallocx()");
  88. assert_ptr_null(mallocx(0x8000000000000000ULL,
  89. MALLOCX_ALIGN(0x80000000)),
  90. "Expected OOM for mallocx()");
  91. #else
  92. assert_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)),
  93. "Expected OOM for mallocx()");
  94. #endif
  95. }
  96. TEST_END
  97. TEST_BEGIN(test_basic) {
  98. #define MAXSZ (((size_t)1) << 23)
  99. size_t sz;
  100. for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
  101. size_t nsz, rsz;
  102. void *p;
  103. nsz = nallocx(sz, 0);
  104. assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
  105. p = mallocx(sz, 0);
  106. assert_ptr_not_null(p,
  107. "Unexpected mallocx(size=%zx, flags=0) error", sz);
  108. rsz = sallocx(p, 0);
  109. assert_zu_ge(rsz, sz, "Real size smaller than expected");
  110. assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
  111. dallocx(p, 0);
  112. p = mallocx(sz, 0);
  113. assert_ptr_not_null(p,
  114. "Unexpected mallocx(size=%zx, flags=0) error", sz);
  115. dallocx(p, 0);
  116. nsz = nallocx(sz, MALLOCX_ZERO);
  117. assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
  118. p = mallocx(sz, MALLOCX_ZERO);
  119. assert_ptr_not_null(p,
  120. "Unexpected mallocx(size=%zx, flags=MALLOCX_ZERO) error",
  121. nsz);
  122. rsz = sallocx(p, 0);
  123. assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
  124. dallocx(p, 0);
  125. purge();
  126. }
  127. #undef MAXSZ
  128. }
  129. TEST_END
  130. TEST_BEGIN(test_alignment_and_size) {
  131. const char *percpu_arena;
  132. size_t sz = sizeof(percpu_arena);
  133. if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) ||
  134. strcmp(percpu_arena, "disabled") != 0) {
  135. test_skip("test_alignment_and_size skipped: "
  136. "not working with percpu arena.");
  137. };
  138. #define MAXALIGN (((size_t)1) << 23)
  139. #define NITER 4
  140. size_t nsz, rsz, alignment, total;
  141. unsigned i;
  142. void *ps[NITER];
  143. for (i = 0; i < NITER; i++) {
  144. ps[i] = NULL;
  145. }
  146. for (alignment = 8;
  147. alignment <= MAXALIGN;
  148. alignment <<= 1) {
  149. total = 0;
  150. for (sz = 1;
  151. sz < 3 * alignment && sz < (1U << 31);
  152. sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
  153. for (i = 0; i < NITER; i++) {
  154. nsz = nallocx(sz, MALLOCX_ALIGN(alignment) |
  155. MALLOCX_ZERO);
  156. assert_zu_ne(nsz, 0,
  157. "nallocx() error for alignment=%zu, "
  158. "size=%zu (%#zx)", alignment, sz, sz);
  159. ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |
  160. MALLOCX_ZERO);
  161. assert_ptr_not_null(ps[i],
  162. "mallocx() error for alignment=%zu, "
  163. "size=%zu (%#zx)", alignment, sz, sz);
  164. rsz = sallocx(ps[i], 0);
  165. assert_zu_ge(rsz, sz,
  166. "Real size smaller than expected for "
  167. "alignment=%zu, size=%zu", alignment, sz);
  168. assert_zu_eq(nsz, rsz,
  169. "nallocx()/sallocx() size mismatch for "
  170. "alignment=%zu, size=%zu", alignment, sz);
  171. assert_ptr_null(
  172. (void *)((uintptr_t)ps[i] & (alignment-1)),
  173. "%p inadequately aligned for"
  174. " alignment=%zu, size=%zu", ps[i],
  175. alignment, sz);
  176. total += rsz;
  177. if (total >= (MAXALIGN << 1)) {
  178. break;
  179. }
  180. }
  181. for (i = 0; i < NITER; i++) {
  182. if (ps[i] != NULL) {
  183. dallocx(ps[i], 0);
  184. ps[i] = NULL;
  185. }
  186. }
  187. }
  188. purge();
  189. }
  190. #undef MAXALIGN
  191. #undef NITER
  192. }
  193. TEST_END
  194. int
  195. main(void) {
  196. return test(
  197. test_overflow,
  198. test_oom,
  199. test_basic,
  200. test_alignment_and_size);
  201. }