free.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. /*
  2. This is a version (aka dlmalloc) of malloc/free/realloc written by
  3. Doug Lea and released to the public domain. Use, modify, and
  4. redistribute this code without permission or acknowledgement in any
  5. way you wish. Send questions, comments, complaints, performance
  6. data, etc to dl@cs.oswego.edu
  7. VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
  8. Note: There may be an updated version of this malloc obtainable at
  9. ftp://gee.cs.oswego.edu/pub/misc/malloc.c
  10. Check before installing!
  11. Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
  12. */
  13. #define munmap __munmap
  14. #include "malloc.h"
  15. /* ------------------------- __malloc_trim -------------------------
  16. __malloc_trim is an inverse of sorts to __malloc_alloc. It gives memory
  17. back to the system (via negative arguments to sbrk) if there is unused
  18. memory at the `high' end of the malloc pool. It is called automatically by
  19. free() when top space exceeds the trim threshold. It is also called by the
  20. public malloc_trim routine. It returns 1 if it actually released any
  21. memory, else 0.
  22. */
  23. static int __malloc_trim(size_t pad, mstate av)
  24. {
  25. long top_size; /* Amount of top-most memory */
  26. long extra; /* Amount to release */
  27. long released; /* Amount actually released */
  28. char* current_brk; /* address returned by pre-check sbrk call */
  29. char* new_brk; /* address returned by post-check sbrk call */
  30. size_t pagesz;
  31. pagesz = av->pagesize;
  32. top_size = chunksize(av->top);
  33. /* Release in pagesize units, keeping at least one page */
  34. extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
  35. if (extra > 0) {
  36. /*
  37. Only proceed if end of memory is where we last set it.
  38. This avoids problems if there were foreign sbrk calls.
  39. */
  40. current_brk = (char*)(MORECORE(0));
  41. if (current_brk == (char*)(av->top) + top_size) {
  42. /*
  43. Attempt to release memory. We ignore MORECORE return value,
  44. and instead call again to find out where new end of memory is.
  45. This avoids problems if first call releases less than we asked,
  46. of if failure somehow altered brk value. (We could still
  47. encounter problems if it altered brk in some very bad way,
  48. but the only thing we can do is adjust anyway, which will cause
  49. some downstream failure.)
  50. */
  51. MORECORE(-extra);
  52. new_brk = (char*)(MORECORE(0));
  53. if (new_brk != (char*)MORECORE_FAILURE) {
  54. released = (long)(current_brk - new_brk);
  55. if (released != 0) {
  56. /* Success. Adjust top. */
  57. av->sbrked_mem -= released;
  58. set_head(av->top, (top_size - released) | PREV_INUSE);
  59. check_malloc_state();
  60. return 1;
  61. }
  62. }
  63. }
  64. }
  65. return 0;
  66. }
  67. /* ------------------------- malloc_trim -------------------------
  68. malloc_trim(size_t pad);
  69. If possible, gives memory back to the system (via negative
  70. arguments to sbrk) if there is unused memory at the `high' end of
  71. the malloc pool. You can call this after freeing large blocks of
  72. memory to potentially reduce the system-level memory requirements
  73. of a program. However, it cannot guarantee to reduce memory. Under
  74. some allocation patterns, some large free blocks of memory will be
  75. locked between two used chunks, so they cannot be given back to
  76. the system.
  77. The `pad' argument to malloc_trim represents the amount of free
  78. trailing space to leave untrimmed. If this argument is zero,
  79. only the minimum amount of memory to maintain internal data
  80. structures will be left (one page or less). Non-zero arguments
  81. can be supplied to maintain enough trailing space to service
  82. future expected allocations without having to re-obtain memory
  83. from the system.
  84. Malloc_trim returns 1 if it actually released any memory, else 0.
  85. On systems that do not support "negative sbrks", it will always
  86. return 0.
  87. */
  88. int malloc_trim(size_t pad)
  89. {
  90. mstate av = get_malloc_state();
  91. __malloc_consolidate(av);
  92. return __malloc_trim(pad, av);
  93. }
  94. /*
  95. Initialize a malloc_state struct.
  96. This is called only from within __malloc_consolidate, which needs
  97. be called in the same contexts anyway. It is never called directly
  98. outside of __malloc_consolidate because some optimizing compilers try
  99. to inline it at all call points, which turns out not to be an
  100. optimization at all. (Inlining it in __malloc_consolidate is fine though.)
  101. */
  102. static void malloc_init_state(mstate av)
  103. {
  104. int i;
  105. mbinptr bin;
  106. /* Establish circular links for normal bins */
  107. for (i = 1; i < NBINS; ++i) {
  108. bin = bin_at(av,i);
  109. bin->fd = bin->bk = bin;
  110. }
  111. av->top_pad = DEFAULT_TOP_PAD;
  112. av->n_mmaps_max = DEFAULT_MMAP_MAX;
  113. av->mmap_threshold = DEFAULT_MMAP_THRESHOLD;
  114. av->trim_threshold = DEFAULT_TRIM_THRESHOLD;
  115. #if MORECORE_CONTIGUOUS
  116. set_contiguous(av);
  117. #else
  118. set_noncontiguous(av);
  119. #endif
  120. set_max_fast(av, DEFAULT_MXFAST);
  121. av->top = initial_top(av);
  122. av->pagesize = malloc_getpagesize;
  123. }
  124. /* ----------------------------------------------------------------------
  125. *
  126. * PUBLIC STUFF
  127. *
  128. * ----------------------------------------------------------------------*/
  129. /* ------------------------- __malloc_consolidate -------------------------
  130. __malloc_consolidate is a specialized version of free() that tears
  131. down chunks held in fastbins. Free itself cannot be used for this
  132. purpose since, among other things, it might place chunks back onto
  133. fastbins. So, instead, we need to use a minor variant of the same
  134. code.
  135. Also, because this routine needs to be called the first time through
  136. malloc anyway, it turns out to be the perfect place to trigger
  137. initialization code.
  138. */
  139. void attribute_hidden __malloc_consolidate(mstate av)
  140. {
  141. mfastbinptr* fb; /* current fastbin being consolidated */
  142. mfastbinptr* maxfb; /* last fastbin (for loop control) */
  143. mchunkptr p; /* current chunk being consolidated */
  144. mchunkptr nextp; /* next chunk to consolidate */
  145. mchunkptr unsorted_bin; /* bin header */
  146. mchunkptr first_unsorted; /* chunk to link to */
  147. /* These have same use as in free() */
  148. mchunkptr nextchunk;
  149. size_t size;
  150. size_t nextsize;
  151. size_t prevsize;
  152. int nextinuse;
  153. mchunkptr bck;
  154. mchunkptr fwd;
  155. /*
  156. If max_fast is 0, we know that av hasn't
  157. yet been initialized, in which case do so below
  158. */
  159. if (av->max_fast != 0) {
  160. clear_fastchunks(av);
  161. unsorted_bin = unsorted_chunks(av);
  162. /*
  163. Remove each chunk from fast bin and consolidate it, placing it
  164. then in unsorted bin. Among other reasons for doing this,
  165. placing in unsorted bin avoids needing to calculate actual bins
  166. until malloc is sure that chunks aren't immediately going to be
  167. reused anyway.
  168. */
  169. maxfb = &(av->fastbins[fastbin_index(av->max_fast)]);
  170. fb = &(av->fastbins[0]);
  171. do {
  172. if ( (p = *fb) != 0) {
  173. *fb = 0;
  174. do {
  175. check_inuse_chunk(p);
  176. nextp = p->fd;
  177. /* Slightly streamlined version of consolidation code in free() */
  178. size = p->size & ~PREV_INUSE;
  179. nextchunk = chunk_at_offset(p, size);
  180. nextsize = chunksize(nextchunk);
  181. if (!prev_inuse(p)) {
  182. prevsize = p->prev_size;
  183. size += prevsize;
  184. p = chunk_at_offset(p, -((long) prevsize));
  185. unlink(p, bck, fwd);
  186. }
  187. if (nextchunk != av->top) {
  188. nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
  189. set_head(nextchunk, nextsize);
  190. if (!nextinuse) {
  191. size += nextsize;
  192. unlink(nextchunk, bck, fwd);
  193. }
  194. first_unsorted = unsorted_bin->fd;
  195. unsorted_bin->fd = p;
  196. first_unsorted->bk = p;
  197. set_head(p, size | PREV_INUSE);
  198. p->bk = unsorted_bin;
  199. p->fd = first_unsorted;
  200. set_foot(p, size);
  201. }
  202. else {
  203. size += nextsize;
  204. set_head(p, size | PREV_INUSE);
  205. av->top = p;
  206. }
  207. } while ( (p = nextp) != 0);
  208. }
  209. } while (fb++ != maxfb);
  210. }
  211. else {
  212. malloc_init_state(av);
  213. check_malloc_state();
  214. }
  215. }
  216. /* ------------------------------ free ------------------------------ */
  217. void free(void* mem)
  218. {
  219. mstate av;
  220. mchunkptr p; /* chunk corresponding to mem */
  221. size_t size; /* its size */
  222. mfastbinptr* fb; /* associated fastbin */
  223. mchunkptr nextchunk; /* next contiguous chunk */
  224. size_t nextsize; /* its size */
  225. int nextinuse; /* true if nextchunk is used */
  226. size_t prevsize; /* size of previous contiguous chunk */
  227. mchunkptr bck; /* misc temp for linking */
  228. mchunkptr fwd; /* misc temp for linking */
  229. /* free(0) has no effect */
  230. if (mem == NULL)
  231. return;
  232. LOCK;
  233. av = get_malloc_state();
  234. p = mem2chunk(mem);
  235. size = chunksize(p);
  236. check_inuse_chunk(p);
  237. /*
  238. If eligible, place chunk on a fastbin so it can be found
  239. and used quickly in malloc.
  240. */
  241. if ((unsigned long)(size) <= (unsigned long)(av->max_fast)
  242. #if TRIM_FASTBINS
  243. /* If TRIM_FASTBINS set, don't place chunks
  244. bordering top into fastbins */
  245. && (chunk_at_offset(p, size) != av->top)
  246. #endif
  247. ) {
  248. set_fastchunks(av);
  249. fb = &(av->fastbins[fastbin_index(size)]);
  250. p->fd = *fb;
  251. *fb = p;
  252. }
  253. /*
  254. Consolidate other non-mmapped chunks as they arrive.
  255. */
  256. else if (!chunk_is_mmapped(p)) {
  257. set_anychunks(av);
  258. nextchunk = chunk_at_offset(p, size);
  259. nextsize = chunksize(nextchunk);
  260. /* consolidate backward */
  261. if (!prev_inuse(p)) {
  262. prevsize = p->prev_size;
  263. size += prevsize;
  264. p = chunk_at_offset(p, -((long) prevsize));
  265. unlink(p, bck, fwd);
  266. }
  267. if (nextchunk != av->top) {
  268. /* get and clear inuse bit */
  269. nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
  270. set_head(nextchunk, nextsize);
  271. /* consolidate forward */
  272. if (!nextinuse) {
  273. unlink(nextchunk, bck, fwd);
  274. size += nextsize;
  275. }
  276. /*
  277. Place the chunk in unsorted chunk list. Chunks are
  278. not placed into regular bins until after they have
  279. been given one chance to be used in malloc.
  280. */
  281. bck = unsorted_chunks(av);
  282. fwd = bck->fd;
  283. p->bk = bck;
  284. p->fd = fwd;
  285. bck->fd = p;
  286. fwd->bk = p;
  287. set_head(p, size | PREV_INUSE);
  288. set_foot(p, size);
  289. check_free_chunk(p);
  290. }
  291. /*
  292. If the chunk borders the current high end of memory,
  293. consolidate into top
  294. */
  295. else {
  296. size += nextsize;
  297. set_head(p, size | PREV_INUSE);
  298. av->top = p;
  299. check_chunk(p);
  300. }
  301. /*
  302. If freeing a large space, consolidate possibly-surrounding
  303. chunks. Then, if the total unused topmost memory exceeds trim
  304. threshold, ask malloc_trim to reduce top.
  305. Unless max_fast is 0, we don't know if there are fastbins
  306. bordering top, so we cannot tell for sure whether threshold
  307. has been reached unless fastbins are consolidated. But we
  308. don't want to consolidate on each free. As a compromise,
  309. consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
  310. is reached.
  311. */
  312. if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
  313. if (have_fastchunks(av))
  314. __malloc_consolidate(av);
  315. if ((unsigned long)(chunksize(av->top)) >=
  316. (unsigned long)(av->trim_threshold))
  317. __malloc_trim(av->top_pad, av);
  318. }
  319. }
  320. /*
  321. If the chunk was allocated via mmap, release via munmap()
  322. Note that if HAVE_MMAP is false but chunk_is_mmapped is
  323. true, then user must have overwritten memory. There's nothing
  324. we can do to catch this error unless DEBUG is set, in which case
  325. check_inuse_chunk (above) will have triggered error.
  326. */
  327. else {
  328. int ret;
  329. size_t offset = p->prev_size;
  330. av->n_mmaps--;
  331. av->mmapped_mem -= (size + offset);
  332. ret = munmap((char*)p - offset, size + offset);
  333. /* munmap returns non-zero on failure */
  334. assert(ret == 0);
  335. }
  336. UNLOCK;
  337. }