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
8 VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee)
10 Note: There may be an updated version of this malloc obtainable at
11 ftp://gee.cs.oswego.edu/pub/misc/malloc.c
12 Check before installing!
14 Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
20 /* ------------------------------ realloc ------------------------------ */
21 void* realloc(void* oldmem, size_t bytes)
25 size_t nb; /* padded request size */
27 mchunkptr oldp; /* chunk corresponding to oldmem */
28 size_t oldsize; /* its size */
30 mchunkptr newp; /* chunk to return */
31 size_t newsize; /* its size */
32 void* newmem; /* corresponding user mem */
34 mchunkptr next; /* next contiguous chunk after oldp */
36 mchunkptr remainder; /* extra space at end of newp */
37 unsigned long remainder_size; /* its size */
39 mchunkptr bck; /* misc temp for linking */
40 mchunkptr fwd; /* misc temp for linking */
42 unsigned long copysize; /* bytes to copy */
43 unsigned int ncopies; /* size_t words to copy */
44 size_t* s; /* copy source */
45 size_t* d; /* copy destination */
49 /* Check for special cases. */
58 av = get_malloc_state();
59 checked_request2size(bytes, nb);
61 oldp = mem2chunk(oldmem);
62 oldsize = chunksize(oldp);
64 check_inuse_chunk(oldp);
66 if (!chunk_is_mmapped(oldp)) {
68 if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
69 /* already big enough; split below */
75 next = chunk_at_offset(oldp, oldsize);
77 /* Try to expand forward into top */
78 if (next == av->top &&
79 (unsigned long)(newsize = oldsize + chunksize(next)) >=
80 (unsigned long)(nb + MINSIZE)) {
81 set_head_size(oldp, nb);
82 av->top = chunk_at_offset(oldp, nb);
83 set_head(av->top, (newsize - nb) | PREV_INUSE);
84 retval = chunk2mem(oldp);
88 /* Try to expand forward into next chunk; split off remainder below */
89 else if (next != av->top &&
91 (unsigned long)(newsize = oldsize + chunksize(next)) >=
92 (unsigned long)(nb)) {
94 unlink(next, bck, fwd);
97 /* allocate, copy, free */
99 newmem = malloc(nb - MALLOC_ALIGN_MASK);
101 retval = 0; /* propagate failure */
105 newp = mem2chunk(newmem);
106 newsize = chunksize(newp);
109 Avoid copy if newp is next chunk after oldp.
117 Unroll copy of <= 36 bytes (72 if 8byte sizes)
118 We know that contents have an odd number of
119 size_t-sized words; minimally 3.
122 copysize = oldsize - (sizeof(size_t));
123 s = (size_t*)(oldmem);
124 d = (size_t*)(newmem);
125 ncopies = copysize / sizeof(size_t);
126 assert(ncopies >= 3);
129 memcpy(d, s, copysize);
150 check_inuse_chunk(newp);
151 retval = chunk2mem(newp);
157 /* If possible, free extra space in old or extended chunk */
159 assert((unsigned long)(newsize) >= (unsigned long)(nb));
161 remainder_size = newsize - nb;
163 if (remainder_size < MINSIZE) { /* not enough extra to split off */
164 set_head_size(newp, newsize);
165 set_inuse_bit_at_offset(newp, newsize);
167 else { /* split remainder */
168 remainder = chunk_at_offset(newp, nb);
169 set_head_size(newp, nb);
170 set_head(remainder, remainder_size | PREV_INUSE);
171 /* Mark remainder as inuse so free() won't complain */
172 set_inuse_bit_at_offset(remainder, remainder_size);
173 free(chunk2mem(remainder));
176 check_inuse_chunk(newp);
177 retval = chunk2mem(newp);
186 size_t offset = oldp->prev_size;
187 size_t pagemask = av->pagesize - 1;
191 /* Note the extra (sizeof(size_t)) overhead */
192 newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
194 /* don't need to remap if still within same page */
195 if (oldsize == newsize - offset) {
200 cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
202 if (cp != (char*)MORECORE_FAILURE) {
204 newp = (mchunkptr)(cp + offset);
205 set_head(newp, (newsize - offset)|IS_MMAPPED);
207 assert(aligned_OK(chunk2mem(newp)));
208 assert((newp->prev_size == offset));
210 /* update statistics */
211 sum = av->mmapped_mem += newsize - oldsize;
212 if (sum > (unsigned long)(av->max_mmapped_mem))
213 av->max_mmapped_mem = sum;
214 sum += av->sbrked_mem;
215 if (sum > (unsigned long)(av->max_total_mem))
216 av->max_total_mem = sum;
218 retval = chunk2mem(newp);
222 /* Note the extra (sizeof(size_t)) overhead. */
223 if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
224 newmem = oldmem; /* do nothing */
226 /* Must alloc, copy, free. */
227 newmem = malloc(nb - MALLOC_ALIGN_MASK);
229 memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));