123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "malloc.h"
- void* realloc(void* oldmem, size_t bytes)
- {
- mstate av;
- size_t nb;
- mchunkptr oldp;
- size_t oldsize;
- mchunkptr newp;
- size_t newsize;
- void* newmem;
- mchunkptr next;
- mchunkptr remainder;
- unsigned long remainder_size;
- mchunkptr bck;
- mchunkptr fwd;
- unsigned long copysize;
- unsigned int ncopies;
- size_t* s;
- size_t* d;
- void *retval;
-
- if (! oldmem)
- return malloc(bytes);
- if (! bytes) {
- free (oldmem);
- return NULL;
- }
- checked_request2size(bytes, nb);
- __MALLOC_LOCK;
- av = get_malloc_state();
- oldp = mem2chunk(oldmem);
- oldsize = chunksize(oldp);
- check_inuse_chunk(oldp);
- if (!chunk_is_mmapped(oldp)) {
- if ((unsigned long)(oldsize) >= (unsigned long)(nb)) {
-
- newp = oldp;
- newsize = oldsize;
- }
- else {
- next = chunk_at_offset(oldp, oldsize);
-
- if (next == av->top &&
- (unsigned long)(newsize = oldsize + chunksize(next)) >=
- (unsigned long)(nb + MINSIZE)) {
- set_head_size(oldp, nb);
- av->top = chunk_at_offset(oldp, nb);
- set_head(av->top, (newsize - nb) | PREV_INUSE);
- retval = chunk2mem(oldp);
- goto DONE;
- }
-
- else if (next != av->top &&
- !inuse(next) &&
- (unsigned long)(newsize = oldsize + chunksize(next)) >=
- (unsigned long)(nb)) {
- newp = oldp;
- unlink(next, bck, fwd);
- }
-
- else {
- newmem = malloc(nb - MALLOC_ALIGN_MASK);
- if (newmem == 0) {
- retval = 0;
- goto DONE;
- }
- newp = mem2chunk(newmem);
- newsize = chunksize(newp);
-
- if (newp == next) {
- newsize += oldsize;
- newp = oldp;
- }
- else {
-
- copysize = oldsize - (sizeof(size_t));
- s = (size_t*)(oldmem);
- d = (size_t*)(newmem);
- ncopies = copysize / sizeof(size_t);
- assert(ncopies >= 3);
- if (ncopies > 9)
- memcpy(d, s, copysize);
- else {
- *(d+0) = *(s+0);
- *(d+1) = *(s+1);
- *(d+2) = *(s+2);
- if (ncopies > 4) {
- *(d+3) = *(s+3);
- *(d+4) = *(s+4);
- if (ncopies > 6) {
- *(d+5) = *(s+5);
- *(d+6) = *(s+6);
- if (ncopies > 8) {
- *(d+7) = *(s+7);
- *(d+8) = *(s+8);
- }
- }
- }
- }
- free(oldmem);
- check_inuse_chunk(newp);
- retval = chunk2mem(newp);
- goto DONE;
- }
- }
- }
-
- assert((unsigned long)(newsize) >= (unsigned long)(nb));
- remainder_size = newsize - nb;
- if (remainder_size < MINSIZE) {
- set_head_size(newp, newsize);
- set_inuse_bit_at_offset(newp, newsize);
- }
- else {
- remainder = chunk_at_offset(newp, nb);
- set_head_size(newp, nb);
- set_head(remainder, remainder_size | PREV_INUSE);
-
- set_inuse_bit_at_offset(remainder, remainder_size);
- free(chunk2mem(remainder));
- }
- check_inuse_chunk(newp);
- retval = chunk2mem(newp);
- goto DONE;
- }
-
- else {
- size_t offset = oldp->prev_size;
- size_t pagemask = av->pagesize - 1;
- char *cp;
- unsigned long sum;
-
- newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask;
-
- if (oldsize == newsize - offset) {
- retval = oldmem;
- goto DONE;
- }
- cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1);
- if (cp != (char*)MORECORE_FAILURE) {
- newp = (mchunkptr)(cp + offset);
- set_head(newp, (newsize - offset)|IS_MMAPPED);
- assert(aligned_OK(chunk2mem(newp)));
- assert((newp->prev_size == offset));
-
- sum = av->mmapped_mem += newsize - oldsize;
- if (sum > (unsigned long)(av->max_mmapped_mem))
- av->max_mmapped_mem = sum;
- sum += av->sbrked_mem;
- if (sum > (unsigned long)(av->max_total_mem))
- av->max_total_mem = sum;
- retval = chunk2mem(newp);
- goto DONE;
- }
-
- if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t))))
- newmem = oldmem;
- else {
-
- newmem = malloc(nb - MALLOC_ALIGN_MASK);
- if (newmem != 0) {
- memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t)));
- free(oldmem);
- }
- }
- retval = newmem;
- }
- DONE:
- __MALLOC_UNLOCK;
- return retval;
- }
|