ref: d29e73f05afa62a514e1156afa2fb40abae6346e
parent: 53a7ee34035f3d6cf151c87f54f1bf15f04a2460
author: Simon Howard <fraggle@gmail.com>
date: Thu Sep 22 08:58:46 EDT 2005
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
--- 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 @@
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 @@
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 @@
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 @@
memblock_t* rover;
memblock_t* newblock;
memblock_t* base;
+ void *result;
size = (size + 3) & ~3;
@@ -219,8 +221,8 @@
// 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;
@@ -227,35 +229,39 @@
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
extra = base->size - size;
@@ -262,43 +268,39 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
}
--- a/src/z_zone.h
+++ b/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 @@
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 @@
//-----------------------------------------------------------------------------
//
// $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
//