From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Sun, 27 May 2001 18:24:11 -0400 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: realloc patch Message-ID: <3B11464B.28287.D7FE4@localhost> X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com This patch should be done barring any problems discovered during this review. Index: malloc.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/malloc.c,v retrieving revision 1.8 diff -c -p -r1.8 malloc.c *** malloc.c 2001/01/20 04:09:57 1.8 --- malloc.c 2001/05/27 22:12:12 *************** malloc(size_t size) *** 217,228 **** RET(rv); } ! static inline BLOCK * ! merge(BLOCK *a, BLOCK *b, BLOCK *c) { int bu; BLOCK *bp, **bpp; #if DEBUG printf(" merge %u/%08x + %u/%08x = %u\n", a->size, a, b->size, b, a->size+b->size+8); --- 217,262 ---- RET(rv); } ! /* Remove block of memory from the free list. */ ! static inline void ! simple_snip_freelist (BLOCK *b) { int bu; BLOCK *bp, **bpp; + bu = b2bucket(b); + #if DEBUG + printf("bucket for %u/%08x is %d\n", b->size, b, bu); + #endif + bpp = freelist + bu; + for (bp = freelist[bu]; bp; bpp=&(bp->next), bp=bp->next) + { + #if DEBUG + printf(" %08x", bp); + #endif + if (bp == b) + { + #if DEBUG + printf("\n snipping %u/%08x from freelist[%d]\n", bp->size, bp, bu); + #endif + *bpp = bp->next; + break; + } + } + } + + /* Insert block of memory into free list. */ + static inline void + insert_freelist(BLOCK *block) + { + int bu = b2bucket(block); + block->next = freelist[bu]; + freelist[bu] = block; + } + + static inline BLOCK * + merge(BLOCK *a, BLOCK *b, BLOCK *c) + { #if DEBUG printf(" merge %u/%08x + %u/%08x = %u\n", a->size, a, b->size, b, a->size+b->size+8); *************** merge(BLOCK *a, BLOCK *b, BLOCK *c) *** 238,262 **** #endif slop = 0; } ! bu = b2bucket(c); ! #if DEBUG ! printf("bucket for %u/%08x is %d\n", c->size, c, bu); ! #endif ! bpp = freelist+bu; ! for (bp=freelist[bu]; bp; bpp=&(bp->next), bp=bp->next) ! { ! #if DEBUG ! printf(" %08x", bp); ! #endif ! if (bp == c) ! { ! #if DEBUG ! printf("\n snipping %u/%08x from freelist[%d]\n", bp->size, bp, bu); ! #endif ! *bpp = bp->next; ! break; ! } ! } CHECK(c); a->size += b->size + 8; --- 272,279 ---- #endif slop = 0; } ! else ! simple_snip_freelist(c); CHECK(c); a->size += b->size + 8; *************** merge(BLOCK *a, BLOCK *b, BLOCK *c) *** 270,276 **** void free(void *ptr) { - int b; BLOCK *block; if (ptr == 0) return; --- 287,292 ---- *************** free(void *ptr) *** 309,321 **** block = merge(block, AFTER(block), AFTER(block)); } CHECK(block); ! ! b = b2bucket(block); ! block->next = freelist[b]; ! freelist[b] = block; CHECK(block); } void * realloc(void *ptr, size_t size) { --- 325,397 ---- block = merge(block, AFTER(block), AFTER(block)); } CHECK(block); ! ! insert_freelist(block); CHECK(block); } + /* Try to increase the size of the allocated block. */ + static BLOCK * + realloc_inplace(BLOCK *cur, size_t old_size, size_t new_size) + { + BLOCK *after; + size_t after_sz, alloc_delta; + int extra_space; + char is_slop_ptr; + + after = AFTER(cur); + after_sz = after->size; + new_size = (new_size + (ALIGN-1)) & ~(ALIGN-1); + + /* Fail if the block following the one being extended is in use. */ + if (after_sz & 1) + return NULL; + + /* Size of block increase. */ + alloc_delta = new_size - old_size; + + /* Fail if the free block is not large enough. */ + if (alloc_delta > after_sz) + return NULL; + + extra_space = (after_sz - alloc_delta); + is_slop_ptr = (after == slop); + + if (!is_slop_ptr) + { + /* Remove the block from free list. */ + after->bucket = -1; + simple_snip_freelist(after); + } + + /* Expand the block by shrinking or mergin + with the free block that follows it. */ + if (extra_space > 8) + { + /* Take part of the free block (or slop) and + give to the block being expanded. */ + BLOCK *after2 = (BLOCK *)((char *)after + alloc_delta); + after2->size = after_sz - alloc_delta; + after2->bucket = -1; + ENDSZ(after2) = after2->size; + cur->size += alloc_delta; + ENDSZ(cur) = cur->size; + if (is_slop_ptr) + slop = after2; + else + insert_freelist(after2); + } + else + { + /* Merge the entire free block with the block being expanded. */ + cur->size += after_sz + 8; + ENDSZ(cur) = cur->size; + if (is_slop_ptr) + slop = 0; + } + return cur; + } + void * realloc(void *ptr, size_t size) { *************** realloc(void *ptr, size_t size) *** 337,342 **** --- 413,422 ---- return ptr; copysize = size; } + + /* Try to increase the size of the allocation by extending the block. */ + if (realloc_inplace(b, copysize, size)) + return ptr; newptr = (char *)malloc(size); #if DEBUG