fix-malloc-p2.patch 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. commit 0dc7fc1cf094406a138e4d1bcf9553e59edcf89d
  2. Author: Florian Weimer <fweimer@redhat.com>
  3. Date: Thu Aug 10 19:36:56 2023 +0200
  4. malloc: Remove bin scanning from memalign (bug 30723)
  5. On the test workload (mpv --cache=yes with VP9 video decoding), the
  6. bin scanning has a very poor success rate (less than 2%). The tcache
  7. scanning has about 50% success rate, so keep that.
  8. Update comments in malloc/tst-memalign-2 to indicate the purpose
  9. of the tests. Even with the scanning removed, the additional
  10. merging opportunities since commit 542b1105852568c3ebc712225ae78b
  11. ("malloc: Enable merging of remainders in memalign (bug 30723)")
  12. are sufficient to pass the existing large bins test.
  13. Remove leftover variables from _int_free from refactoring in the
  14. same commit.
  15. Reviewed-by: DJ Delorie <dj@redhat.com>
  16. diff --git a/malloc/malloc.c b/malloc/malloc.c
  17. index 948f9759af..d0bbbf3710 100644
  18. --- a/malloc/malloc.c
  19. +++ b/malloc/malloc.c
  20. @@ -4488,12 +4488,6 @@ _int_free (mstate av, mchunkptr p, int have_lock)
  21. {
  22. INTERNAL_SIZE_T size; /* its size */
  23. mfastbinptr *fb; /* associated fastbin */
  24. - mchunkptr nextchunk; /* next contiguous chunk */
  25. - INTERNAL_SIZE_T nextsize; /* its size */
  26. - int nextinuse; /* true if nextchunk is used */
  27. - INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */
  28. - mchunkptr bck; /* misc temp for linking */
  29. - mchunkptr fwd; /* misc temp for linking */
  30. size = chunksize (p);
  31. @@ -5032,42 +5026,6 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
  32. ------------------------------ memalign ------------------------------
  33. */
  34. -/* Returns 0 if the chunk is not and does not contain the requested
  35. - aligned sub-chunk, else returns the amount of "waste" from
  36. - trimming. NB is the *chunk* byte size, not the user byte
  37. - size. */
  38. -static size_t
  39. -chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t nb)
  40. -{
  41. - void *m = chunk2mem (p);
  42. - INTERNAL_SIZE_T size = chunksize (p);
  43. - void *aligned_m = m;
  44. -
  45. - if (__glibc_unlikely (misaligned_chunk (p)))
  46. - malloc_printerr ("_int_memalign(): unaligned chunk detected");
  47. -
  48. - aligned_m = PTR_ALIGN_UP (m, alignment);
  49. -
  50. - INTERNAL_SIZE_T front_extra = (intptr_t) aligned_m - (intptr_t) m;
  51. -
  52. - /* We can't trim off the front as it's too small. */
  53. - if (front_extra > 0 && front_extra < MINSIZE)
  54. - return 0;
  55. -
  56. - /* If it's a perfect fit, it's an exception to the return value rule
  57. - (we would return zero waste, which looks like "not usable"), so
  58. - handle it here by returning a small non-zero value instead. */
  59. - if (size == nb && front_extra == 0)
  60. - return 1;
  61. -
  62. - /* If the block we need fits in the chunk, calculate total waste. */
  63. - if (size > nb + front_extra)
  64. - return size - nb;
  65. -
  66. - /* Can't use this chunk. */
  67. - return 0;
  68. -}
  69. -
  70. /* BYTES is user requested bytes, not requested chunksize bytes. */
  71. static void *
  72. _int_memalign (mstate av, size_t alignment, size_t bytes)
  73. @@ -5082,7 +5040,6 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
  74. mchunkptr remainder; /* spare room at end to split off */
  75. unsigned long remainder_size; /* its size */
  76. INTERNAL_SIZE_T size;
  77. - mchunkptr victim;
  78. nb = checked_request2size (bytes);
  79. if (nb == 0)
  80. @@ -5101,129 +5058,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
  81. we don't find anything in those bins, the common malloc code will
  82. scan starting at 2x. */
  83. - /* This will be set if we found a candidate chunk. */
  84. - victim = NULL;
  85. -
  86. - /* Fast bins are singly-linked, hard to remove a chunk from the middle
  87. - and unlikely to meet our alignment requirements. We have not done
  88. - any experimentation with searching for aligned fastbins. */
  89. -
  90. - if (av != NULL)
  91. - {
  92. - int first_bin_index;
  93. - int first_largebin_index;
  94. - int last_bin_index;
  95. -
  96. - if (in_smallbin_range (nb))
  97. - first_bin_index = smallbin_index (nb);
  98. - else
  99. - first_bin_index = largebin_index (nb);
  100. -
  101. - if (in_smallbin_range (nb * 2))
  102. - last_bin_index = smallbin_index (nb * 2);
  103. - else
  104. - last_bin_index = largebin_index (nb * 2);
  105. -
  106. - first_largebin_index = largebin_index (MIN_LARGE_SIZE);
  107. -
  108. - int victim_index; /* its bin index */
  109. -
  110. - for (victim_index = first_bin_index;
  111. - victim_index < last_bin_index;
  112. - victim_index ++)
  113. - {
  114. - victim = NULL;
  115. -
  116. - if (victim_index < first_largebin_index)
  117. - {
  118. - /* Check small bins. Small bin chunks are doubly-linked despite
  119. - being the same size. */
  120. -
  121. - mchunkptr fwd; /* misc temp for linking */
  122. - mchunkptr bck; /* misc temp for linking */
  123. -
  124. - bck = bin_at (av, victim_index);
  125. - fwd = bck->fd;
  126. - while (fwd != bck)
  127. - {
  128. - if (chunk_ok_for_memalign (fwd, alignment, nb) > 0)
  129. - {
  130. - victim = fwd;
  131. -
  132. - /* Unlink it */
  133. - victim->fd->bk = victim->bk;
  134. - victim->bk->fd = victim->fd;
  135. - break;
  136. - }
  137. -
  138. - fwd = fwd->fd;
  139. - }
  140. - }
  141. - else
  142. - {
  143. - /* Check large bins. */
  144. - mchunkptr fwd; /* misc temp for linking */
  145. - mchunkptr bck; /* misc temp for linking */
  146. - mchunkptr best = NULL;
  147. - size_t best_size = 0;
  148. -
  149. - bck = bin_at (av, victim_index);
  150. - fwd = bck->fd;
  151. + /* Call malloc with worst case padding to hit alignment. */
  152. + m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
  153. - while (fwd != bck)
  154. - {
  155. - int extra;
  156. -
  157. - if (chunksize (fwd) < nb)
  158. - break;
  159. - extra = chunk_ok_for_memalign (fwd, alignment, nb);
  160. - if (extra > 0
  161. - && (extra <= best_size || best == NULL))
  162. - {
  163. - best = fwd;
  164. - best_size = extra;
  165. - }
  166. + if (m == 0)
  167. + return 0; /* propagate failure */
  168. - fwd = fwd->fd;
  169. - }
  170. - victim = best;
  171. -
  172. - if (victim != NULL)
  173. - {
  174. - unlink_chunk (av, victim);
  175. - break;
  176. - }
  177. - }
  178. -
  179. - if (victim != NULL)
  180. - break;
  181. - }
  182. - }
  183. -
  184. - /* Strategy: find a spot within that chunk that meets the alignment
  185. - request, and then possibly free the leading and trailing space.
  186. - This strategy is incredibly costly and can lead to external
  187. - fragmentation if header and footer chunks are unused. */
  188. -
  189. - if (victim != NULL)
  190. - {
  191. - p = victim;
  192. - m = chunk2mem (p);
  193. - set_inuse (p);
  194. - if (av != &main_arena)
  195. - set_non_main_arena (p);
  196. - }
  197. - else
  198. - {
  199. - /* Call malloc with worst case padding to hit alignment. */
  200. -
  201. - m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
  202. -
  203. - if (m == 0)
  204. - return 0; /* propagate failure */
  205. -
  206. - p = mem2chunk (m);
  207. - }
  208. + p = mem2chunk (m);
  209. if ((((unsigned long) (m)) % alignment) != 0) /* misaligned */
  210. {
  211. diff --git a/malloc/tst-memalign-2.c b/malloc/tst-memalign-2.c
  212. index f229283dbf..ecd6fa249e 100644
  213. --- a/malloc/tst-memalign-2.c
  214. +++ b/malloc/tst-memalign-2.c
  215. @@ -86,7 +86,8 @@ do_test (void)
  216. TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2);
  217. }
  218. - /* Test for non-head tcache hits. */
  219. + /* Test for non-head tcache hits. This exercises the memalign
  220. + scanning code to find matching allocations. */
  221. for (i = 0; i < array_length (ptr); ++ i)
  222. {
  223. if (i == 4)
  224. @@ -113,7 +114,9 @@ do_test (void)
  225. free (p);
  226. TEST_VERIFY (count > 0);
  227. - /* Large bins test. */
  228. + /* Large bins test. This verifies that the over-allocated parts
  229. + that memalign releases for future allocations can be reused by
  230. + memalign itself at least in some cases. */
  231. for (i = 0; i < LN; ++ i)
  232. {