mallocx.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. /*
  45. * GCC "-Walloc-size-larger-than" warning detects when one of the memory
  46. * allocation functions is called with a size larger than the maximum size that
  47. * they support. Here we want to explicitly test that the allocation functions
  48. * do indeed fail properly when this is the case, which triggers the warning.
  49. * Therefore we disable the warning for these tests.
  50. */
  51. JEMALLOC_DIAGNOSTIC_PUSH
  52. JEMALLOC_DIAGNOSTIC_IGNORE_ALLOC_SIZE_LARGER_THAN
  53. TEST_BEGIN(test_overflow) {
  54. size_t largemax;
  55. largemax = get_large_size(get_nlarge()-1);
  56. assert_ptr_null(mallocx(largemax+1, 0),
  57. "Expected OOM for mallocx(size=%#zx, 0)", largemax+1);
  58. assert_ptr_null(mallocx(ZU(PTRDIFF_MAX)+1, 0),
  59. "Expected OOM for mallocx(size=%#zx, 0)", ZU(PTRDIFF_MAX)+1);
  60. assert_ptr_null(mallocx(SIZE_T_MAX, 0),
  61. "Expected OOM for mallocx(size=%#zx, 0)", SIZE_T_MAX);
  62. assert_ptr_null(mallocx(1, MALLOCX_ALIGN(ZU(PTRDIFF_MAX)+1)),
  63. "Expected OOM for mallocx(size=1, MALLOCX_ALIGN(%#zx))",
  64. ZU(PTRDIFF_MAX)+1);
  65. }
  66. TEST_END
  67. static void *
  68. remote_alloc(void *arg) {
  69. unsigned arena;
  70. size_t sz = sizeof(unsigned);
  71. assert_d_eq(mallctl("arenas.create", (void *)&arena, &sz, NULL, 0), 0,
  72. "Unexpected mallctl() failure");
  73. size_t large_sz;
  74. sz = sizeof(size_t);
  75. assert_d_eq(mallctl("arenas.lextent.0.size", (void *)&large_sz, &sz,
  76. NULL, 0), 0, "Unexpected mallctl failure");
  77. void *ptr = mallocx(large_sz, MALLOCX_ARENA(arena)
  78. | MALLOCX_TCACHE_NONE);
  79. void **ret = (void **)arg;
  80. *ret = ptr;
  81. return NULL;
  82. }
  83. TEST_BEGIN(test_remote_free) {
  84. thd_t thd;
  85. void *ret;
  86. thd_create(&thd, remote_alloc, (void *)&ret);
  87. thd_join(thd, NULL);
  88. assert_ptr_not_null(ret, "Unexpected mallocx failure");
  89. /* Avoid TCACHE_NONE to explicitly test tcache_flush(). */
  90. dallocx(ret, 0);
  91. mallctl("thread.tcache.flush", NULL, NULL, NULL, 0);
  92. }
  93. TEST_END
  94. TEST_BEGIN(test_oom) {
  95. size_t largemax;
  96. bool oom;
  97. void *ptrs[3];
  98. unsigned i;
  99. /*
  100. * It should be impossible to allocate three objects that each consume
  101. * nearly half the virtual address space.
  102. */
  103. largemax = get_large_size(get_nlarge()-1);
  104. oom = false;
  105. for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
  106. ptrs[i] = mallocx(largemax, MALLOCX_ARENA(0));
  107. if (ptrs[i] == NULL) {
  108. oom = true;
  109. }
  110. }
  111. assert_true(oom,
  112. "Expected OOM during series of calls to mallocx(size=%zu, 0)",
  113. largemax);
  114. for (i = 0; i < sizeof(ptrs) / sizeof(void *); i++) {
  115. if (ptrs[i] != NULL) {
  116. dallocx(ptrs[i], 0);
  117. }
  118. }
  119. purge();
  120. #if LG_SIZEOF_PTR == 3
  121. assert_ptr_null(mallocx(0x8000000000000000ULL,
  122. MALLOCX_ALIGN(0x8000000000000000ULL)),
  123. "Expected OOM for mallocx()");
  124. assert_ptr_null(mallocx(0x8000000000000000ULL,
  125. MALLOCX_ALIGN(0x80000000)),
  126. "Expected OOM for mallocx()");
  127. #else
  128. assert_ptr_null(mallocx(0x80000000UL, MALLOCX_ALIGN(0x80000000UL)),
  129. "Expected OOM for mallocx()");
  130. #endif
  131. }
  132. TEST_END
  133. /* Re-enable the "-Walloc-size-larger-than=" warning */
  134. JEMALLOC_DIAGNOSTIC_POP
  135. TEST_BEGIN(test_basic) {
  136. #define MAXSZ (((size_t)1) << 23)
  137. size_t sz;
  138. for (sz = 1; sz < MAXSZ; sz = nallocx(sz, 0) + 1) {
  139. size_t nsz, rsz;
  140. void *p;
  141. nsz = nallocx(sz, 0);
  142. assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
  143. p = mallocx(sz, 0);
  144. assert_ptr_not_null(p,
  145. "Unexpected mallocx(size=%zx, flags=0) error", sz);
  146. rsz = sallocx(p, 0);
  147. assert_zu_ge(rsz, sz, "Real size smaller than expected");
  148. assert_zu_eq(nsz, rsz, "nallocx()/sallocx() size mismatch");
  149. dallocx(p, 0);
  150. p = mallocx(sz, 0);
  151. assert_ptr_not_null(p,
  152. "Unexpected mallocx(size=%zx, flags=0) error", sz);
  153. dallocx(p, 0);
  154. nsz = nallocx(sz, MALLOCX_ZERO);
  155. assert_zu_ne(nsz, 0, "Unexpected nallocx() error");
  156. p = mallocx(sz, MALLOCX_ZERO);
  157. assert_ptr_not_null(p,
  158. "Unexpected mallocx(size=%zx, flags=MALLOCX_ZERO) error",
  159. nsz);
  160. rsz = sallocx(p, 0);
  161. assert_zu_eq(nsz, rsz, "nallocx()/sallocx() rsize mismatch");
  162. dallocx(p, 0);
  163. purge();
  164. }
  165. #undef MAXSZ
  166. }
  167. TEST_END
  168. TEST_BEGIN(test_alignment_and_size) {
  169. const char *percpu_arena;
  170. size_t sz = sizeof(percpu_arena);
  171. if(mallctl("opt.percpu_arena", (void *)&percpu_arena, &sz, NULL, 0) ||
  172. strcmp(percpu_arena, "disabled") != 0) {
  173. test_skip("test_alignment_and_size skipped: "
  174. "not working with percpu arena.");
  175. };
  176. #define MAXALIGN (((size_t)1) << 23)
  177. #define NITER 4
  178. size_t nsz, rsz, alignment, total;
  179. unsigned i;
  180. void *ps[NITER];
  181. for (i = 0; i < NITER; i++) {
  182. ps[i] = NULL;
  183. }
  184. for (alignment = 8;
  185. alignment <= MAXALIGN;
  186. alignment <<= 1) {
  187. total = 0;
  188. for (sz = 1;
  189. sz < 3 * alignment && sz < (1U << 31);
  190. sz += (alignment >> (LG_SIZEOF_PTR-1)) - 1) {
  191. for (i = 0; i < NITER; i++) {
  192. nsz = nallocx(sz, MALLOCX_ALIGN(alignment) |
  193. MALLOCX_ZERO | MALLOCX_ARENA(0));
  194. assert_zu_ne(nsz, 0,
  195. "nallocx() error for alignment=%zu, "
  196. "size=%zu (%#zx)", alignment, sz, sz);
  197. ps[i] = mallocx(sz, MALLOCX_ALIGN(alignment) |
  198. MALLOCX_ZERO | MALLOCX_ARENA(0));
  199. assert_ptr_not_null(ps[i],
  200. "mallocx() error for alignment=%zu, "
  201. "size=%zu (%#zx)", alignment, sz, sz);
  202. rsz = sallocx(ps[i], 0);
  203. assert_zu_ge(rsz, sz,
  204. "Real size smaller than expected for "
  205. "alignment=%zu, size=%zu", alignment, sz);
  206. assert_zu_eq(nsz, rsz,
  207. "nallocx()/sallocx() size mismatch for "
  208. "alignment=%zu, size=%zu", alignment, sz);
  209. assert_ptr_null(
  210. (void *)((uintptr_t)ps[i] & (alignment-1)),
  211. "%p inadequately aligned for"
  212. " alignment=%zu, size=%zu", ps[i],
  213. alignment, sz);
  214. total += rsz;
  215. if (total >= (MAXALIGN << 1)) {
  216. break;
  217. }
  218. }
  219. for (i = 0; i < NITER; i++) {
  220. if (ps[i] != NULL) {
  221. dallocx(ps[i], 0);
  222. ps[i] = NULL;
  223. }
  224. }
  225. }
  226. purge();
  227. }
  228. #undef MAXALIGN
  229. #undef NITER
  230. }
  231. TEST_END
  232. int
  233. main(void) {
  234. return test(
  235. test_overflow,
  236. test_oom,
  237. test_remote_free,
  238. test_basic,
  239. test_alignment_and_size);
  240. }