From: "Mark E." To: djgpp-workers AT delorie DOT com Date: Thu, 24 May 2001 23:05:19 -0400 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Subject: Re: ehhanced realloc test program Message-ID: <3B0D93AF.27050.12431F@localhost> X-mailer: Pegasus Mail for Win32 (v3.12c) Reply-To: djgpp-workers AT delorie DOT com Belowis a revised version I finally got debugged that dispenses with 'split_block' and is much closer to a final version. /* Remove block of memory from the free list. */ static inline void remove_freelist (BLOCK *b) { int bu; BLOCK *bp, **bpp; bu = b2bucket (b); bpp = freelist + bu; for (bp = freelist[bu]; bp; bpp=&(bp->next), bp=bp->next) { if (bp == b) { *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; } /* 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, 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; remove_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) { BLOCK *b; char *newptr; size_t copysize; if (ptr == 0) return malloc(size); b = (BLOCK *)((char *)ptr-4); copysize = b->size & ~1; if (size <= copysize) { #if 0 if (copysize < 2*MIN_SAVE_EXTRA || (size >= copysize-512 && size >= copysize/2)) #endif return ptr; copysize = size; } #if 1 /* Try to increase the size of the allocation. */ if (realloc_inplace (b, copysize, size)) return ptr; #endif newptr = (char *)malloc(size); #if DEBUG printf("realloc %u %u/%08x %08x->%08, %u\n", size, b->size & ~1, b, ptr, newptr, copysize); #endif if (!newptr) return NULL; memcpy(newptr, ptr, copysize); free(ptr); return newptr; }