From d29e73f05afa62a514e1156afa2fb40abae6346e Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Thu, 22 Sep 2005 12:58:46 +0000 Subject: Use a new PU_FREE tag to mark free blocks, rather than the 'user' field (avoids using magic numbers to mark allocated blocks with no user) Subversion-branch: /trunk/chocolate-doom Subversion-revision: 119 --- src/z_zone.c | 191 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 97 insertions(+), 94 deletions(-) (limited to 'src/z_zone.c') diff --git a/src/z_zone.c b/src/z_zone.c index 1922a62a..3739a289 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: z_zone.c 8 2005-07-23 16:44:57Z fraggle $ +// $Id: z_zone.c 119 2005-09-22 12:58:46Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -22,6 +22,10 @@ // 02111-1307, USA. // // $Log$ +// Revision 1.3 2005/09/22 12:58:46 fraggle +// Use a new PU_FREE tag to mark free blocks, rather than the 'user' field +// (avoids using magic numbers to mark allocated blocks with no user) +// // Revision 1.2 2005/07/23 16:44:57 fraggle // Update copyright to GNU GPL // @@ -35,7 +39,7 @@ //----------------------------------------------------------------------------- static const char -rcsid[] = "$Id: z_zone.c 8 2005-07-23 16:44:57Z fraggle $"; +rcsid[] = "$Id: z_zone.c 119 2005-09-22 12:58:46Z fraggle $"; #include "z_zone.h" #include "i_system.h" @@ -92,8 +96,8 @@ void Z_ClearZone (memzone_t* zone) block->prev = block->next = &zone->blocklist; - // NULL indicates a free block. - block->user = NULL; + // a free block. + block->tag = PU_FREE; block->size = zone->size - sizeof(memzone_t); } @@ -122,8 +126,8 @@ void Z_Init (void) block->prev = block->next = &mainzone->blocklist; - // NULL indicates a free block. - block->user = NULL; + // free block + block->tag = PU_FREE; block->size = mainzone->size - sizeof(memzone_t); } @@ -142,45 +146,42 @@ void Z_Free (void* ptr) if (block->id != ZONEID) I_Error ("Z_Free: freed a pointer without ZONEID"); - if (block->user > (void **)0x100) + if (block->tag != PU_FREE && block->user != NULL) { - // smaller values are not pointers - // Note: OS-dependend? - - // clear the user's mark - *block->user = 0; + // clear the user's mark + *block->user = 0; } // mark as free - block->user = NULL; - block->tag = 0; + block->tag = PU_FREE; + block->user = NULL; block->id = 0; other = block->prev; - if (!other->user) + if (other->tag == PU_FREE) { - // merge with previous free block - other->size += block->size; - other->next = block->next; - other->next->prev = other; + // merge with previous free block + other->size += block->size; + other->next = block->next; + other->next->prev = other; - if (block == mainzone->rover) - mainzone->rover = other; + if (block == mainzone->rover) + mainzone->rover = other; - block = other; + block = other; } other = block->next; - if (!other->user) + if (other->tag == PU_FREE) { - // merge the next free block onto the end - block->size += other->size; - block->next = other->next; - block->next->prev = block; + // merge the next free block onto the end + block->size += other->size; + block->next = other->next; + block->next->prev = block; - if (other == mainzone->rover) - mainzone->rover = block; + if (other == mainzone->rover) + mainzone->rover = block; } } @@ -204,6 +205,7 @@ Z_Malloc memblock_t* rover; memblock_t* newblock; memblock_t* base; + void *result; size = (size + 3) & ~3; @@ -219,42 +221,46 @@ Z_Malloc // back up over them base = mainzone->rover; - if (!base->prev->user) - base = base->prev; + if (base->prev->tag == PU_FREE) + base = base->prev; rover = base; start = base->prev; do { - if (rover == start) - { - // scanned all the way around the list - I_Error ("Z_Malloc: failed on allocation of %i bytes", size); - } + if (rover == start) + { + // scanned all the way around the list + Z_FileDumpHeap(stdout); + I_Error ("Z_Malloc: failed on allocation of %i bytes", size); + } - if (rover->user) - { - if (rover->tag < PU_PURGELEVEL) - { - // hit a block that can't be purged, - // so move base past it - base = rover = rover->next; - } - else - { - // free the rover block (adding the size to base) - - // the rover can be the base block - base = base->prev; - Z_Free ((byte *)rover+sizeof(memblock_t)); - base = base->next; - rover = base->next; - } - } - else - rover = rover->next; - } while (base->user || base->size < size); + if (rover->tag != PU_FREE) + { + if (rover->tag < PU_PURGELEVEL) + { + // hit a block that can't be purged, + // so move base past it + base = rover = rover->next; + } + else + { + // free the rover block (adding the size to base) + + // the rover can be the base block + base = base->prev; + Z_Free ((byte *)rover+sizeof(memblock_t)); + base = base->next; + rover = base->next; + } + } + else + { + rover = rover->next; + } + + } while (base->tag != PU_FREE || base->size < size); // found a block big enough @@ -262,43 +268,39 @@ Z_Malloc if (extra > MINFRAGMENT) { - // there will be a free fragment after the allocated block - newblock = (memblock_t *) ((byte *)base + size ); - newblock->size = extra; + // there will be a free fragment after the allocated block + newblock = (memblock_t *) ((byte *)base + size ); + newblock->size = extra; - // NULL indicates free block. - newblock->user = NULL; - newblock->tag = 0; - newblock->prev = base; - newblock->next = base->next; - newblock->next->prev = newblock; - - base->next = newblock; - base->size = size; + newblock->tag = PU_FREE; + newblock->user = NULL; + newblock->prev = base; + newblock->next = base->next; + newblock->next->prev = newblock; + + base->next = newblock; + base->size = size; } - if (user) - { - // mark as an in use block - base->user = user; - *(void **)user = (void *) ((byte *)base + sizeof(memblock_t)); - } - else - { - if (tag >= PU_PURGELEVEL) + if (user == NULL && tag >= PU_PURGELEVEL) I_Error ("Z_Malloc: an owner is required for purgable blocks"); - // mark as in use, but unowned - base->user = (void *)2; - } + base->user = user; base->tag = tag; + result = (void *) ((byte *)base + sizeof(memblock_t)); + + if (base->user) + { + *base->user = result; + } + // next allocation will start looking here mainzone->rover = base->next; base->id = ZONEID; - return (void *) ((byte *)base + sizeof(memblock_t)); + return result; } @@ -322,7 +324,7 @@ Z_FreeTags next = block->next; // free block? - if (!block->user) + if (block->tag == PU_FREE) continue; if (block->tag >= lowtag && block->tag <= hightag) @@ -367,7 +369,7 @@ Z_DumpHeap if ( block->next->prev != block) printf ("ERROR: next block doesn't have proper back link\n"); - if (!block->user && !block->next->user) + if (block->tag == PU_FREE && block->next->tag == PU_FREE) printf ("ERROR: two consecutive free blocks\n"); } } @@ -399,7 +401,7 @@ void Z_FileDumpHeap (FILE* f) if ( block->next->prev != block) fprintf (f,"ERROR: next block doesn't have proper back link\n"); - if (!block->user && !block->next->user) + if (block->tag == PU_FREE && block->next->tag == PU_FREE) fprintf (f,"ERROR: two consecutive free blocks\n"); } } @@ -427,7 +429,7 @@ void Z_CheckHeap (void) if ( block->next->prev != block) I_Error ("Z_CheckHeap: next block doesn't have proper back link\n"); - if (!block->user && !block->next->user) + if (block->tag == PU_FREE && block->next->tag == PU_FREE) I_Error ("Z_CheckHeap: two consecutive free blocks\n"); } } @@ -448,10 +450,10 @@ Z_ChangeTag2 block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t)); if (block->id != ZONEID) - I_Error ("Z_ChangeTag: freed a pointer without ZONEID"); + I_Error ("Z_ChangeTag: freed a pointer without ZONEID"); - if (tag >= PU_PURGELEVEL && (unsigned)block->user < 0x100) - I_Error ("Z_ChangeTag: an owner is required for purgable blocks"); + if (tag >= PU_PURGELEVEL && block->user == NULL) + I_Error ("Z_ChangeTag: an owner is required for purgable blocks"); block->tag = tag; } @@ -469,12 +471,13 @@ int Z_FreeMemory (void) free = 0; for (block = mainzone->blocklist.next ; - block != &mainzone->blocklist; - block = block->next) + block != &mainzone->blocklist; + block = block->next) { - if (!block->user || block->tag >= PU_PURGELEVEL) - free += block->size; + if (block->tag == PU_FREE || block->tag >= PU_PURGELEVEL) + free += block->size; } + return free; } -- cgit v1.2.3