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
This commit is contained in:
parent
53a7ee3403
commit
d29e73f05a
2 changed files with 110 additions and 101 deletions
187
src/z_zone.c
187
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)
|
||||
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->user || base->size < size);
|
||||
// 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;
|
||||
newblock->tag = PU_FREE;
|
||||
newblock->user = NULL;
|
||||
newblock->prev = base;
|
||||
newblock->next = base->next;
|
||||
newblock->next->prev = newblock;
|
||||
|
||||
base->next = newblock;
|
||||
base->size = size;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
24
src/z_zone.h
24
src/z_zone.h
|
|
@ -1,7 +1,7 @@
|
|||
// Emacs style mode select -*- C++ -*-
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $Id: z_zone.h 8 2005-07-23 16:44:57Z fraggle $
|
||||
// $Id: z_zone.h 119 2005-09-22 12:58:46Z fraggle $
|
||||
//
|
||||
// Copyright(C) 1993-1996 Id Software, Inc.
|
||||
// Copyright(C) 2005 Simon Howard
|
||||
|
|
@ -40,12 +40,14 @@
|
|||
// ZONE MEMORY
|
||||
// PU - purge tags.
|
||||
// Tags < 100 are not overwritten until freed.
|
||||
#define PU_STATIC 1 // static entire execution time
|
||||
#define PU_SOUND 2 // static while playing
|
||||
#define PU_MUSIC 3 // static while playing
|
||||
#define PU_DAVE 4 // anything else Dave wants static
|
||||
#define PU_LEVEL 50 // static until level exited
|
||||
#define PU_LEVSPEC 51 // a special thinker in a level
|
||||
#define PU_STATIC 1 /* static entire execution time */
|
||||
#define PU_SOUND 2 /* static while playing */
|
||||
#define PU_MUSIC 3 /* static while playing */
|
||||
#define PU_DAVE 4 /* anything else Dave wants static */
|
||||
#define PU_FREE 5 /* a free block */
|
||||
#define PU_LEVEL 50 /* static until level exited */
|
||||
#define PU_LEVSPEC 51 /* a special thinker in a level */
|
||||
|
||||
// Tags >= 100 are purgable whenever needed.
|
||||
#define PU_PURGELEVEL 100
|
||||
#define PU_CACHE 101
|
||||
|
|
@ -65,8 +67,8 @@ int Z_FreeMemory (void);
|
|||
typedef struct memblock_s
|
||||
{
|
||||
int size; // including the header and possibly tiny fragments
|
||||
void** user; // NULL if a free block
|
||||
int tag; // purgelevel
|
||||
void** user;
|
||||
int tag; // PU_FREE if this is free
|
||||
int id; // should be ZONEID
|
||||
struct memblock_s* next;
|
||||
struct memblock_s* prev;
|
||||
|
|
@ -89,6 +91,10 @@ typedef struct memblock_s
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// $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
|
||||
//
|
||||
|
|
|
|||
Loading…
Reference in a new issue