shithub: choc

Download patch

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
 //