From cee5eb47b591b2b0a333198243e632607fb9585f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustaf=20Alh=C3=A4ll?= <gustaf@hanicef.me>
Date: Wed, 19 Jul 2023 23:17:21 +0200
Subject: [PATCH] Clean up and simplify zone memory allocation

---
 src/z_zone.c | 225 +++++++++------------------------------------------
 1 file changed, 39 insertions(+), 186 deletions(-)

diff --git a/src/z_zone.c b/src/z_zone.c
index d23c43b7b5..5750f8ae01 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -51,27 +51,11 @@ static boolean Z_calloc = false;
 //#define ZDEBUG2
 #endif
 
-struct memblock_s;
-
-typedef struct
-{
-	struct memblock_s *block; // Describing this memory
-	UINT32 id; // Should be ZONEID
-} ATTRPACK memhdr_t;
-
-// Some code might want aligned memory. Assume it wants memory n bytes
-// aligned -- then we allocate n-1 extra bytes and return a pointer to
-// the first byte aligned as requested.
-// Thus, "real" is the pointer we get from malloc() and will free()
-// later, but "hdr" is where the memhdr_t starts.
-// For non-aligned allocations they will be the same.
 typedef struct memblock_s
 {
-	void *real;
-	memhdr_t *hdr;
-
 	void **user;
 	INT32 tag; // purgelevel
+	UINT32 id; // Should be ZONEID
 
 	size_t size; // including the header and blocks
 	size_t realsize; // size of real data only
@@ -82,7 +66,10 @@ typedef struct memblock_s
 #endif
 
 	struct memblock_s *next, *prev;
-} ATTRPACK memblock_t;
+} memblock_t;
+
+#define MEMORY(x) (void *)((uintptr_t)(x) + sizeof(memblock_t))
+#define MEMBLOCK(x) (memblock_t *)((uintptr_t)(x) - sizeof(memblock_t))
 
 // both the head and tail of the zone memory block list
 static memblock_t head;
@@ -128,64 +115,6 @@ void Z_Init(void)
 // Zone memory allocation
 // ----------------------
 
-/** Returns the corresponding memblock_t for a given memory block.
-  *
-  * \param ptr A pointer to allocated memory,
-  *             assumed to have been allocated with Z_Malloc/Z_Calloc.
-  * \param func A string containing the name of the function that called this,
-  *              to be printed if the function I_Errors
-  * \return A pointer to the memblock_t for the given memory.
-  * \sa Z_Free, Z_ReallocAlign
-  */
-#ifdef ZDEBUG
-#define Ptr2Memblock(s, f) Ptr2Memblock2(s, f, __FILE__, __LINE__)
-static memblock_t *Ptr2Memblock2(void *ptr, const char* func, const char *file, INT32 line)
-#else
-static memblock_t *Ptr2Memblock(void *ptr, const char* func)
-#endif
-{
-	memhdr_t *hdr;
-	memblock_t *block;
-
-	if (ptr == NULL)
-		return NULL;
-
-#ifdef ZDEBUG2
-	CONS_Printf("%s %s:%d\n", func, file, line);
-#endif
-
-	hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr);
-
-#ifdef VALGRIND_MAKE_MEM_DEFINED
-	VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr);
-#endif
-
-#ifdef VALGRIND_MEMPOOL_EXISTS
-	if (!VALGRIND_MEMPOOL_EXISTS(hdr->block))
-	{
-#ifdef ZDEBUG
-		I_Error("%s: bad memblock from %s:%d", func, file, line);
-#else
-		I_Error("%s: bad memblock", func);
-#endif
-	}
-#endif
-	if (hdr->id != ZONEID)
-	{
-#ifdef ZDEBUG
-		I_Error("%s: wrong id from %s:%d", func, file, line);
-#else
-		I_Error("%s: wrong id", func);
-#endif
-	}
-	block = hdr->block;
-#ifdef VALGRIND_MAKE_MEM_NOACCESS
-	VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr);
-#endif
-	return block;
-
-}
-
 /** Frees allocated memory.
   *
   * \param ptr A pointer to allocated memory,
@@ -207,10 +136,14 @@ void Z_Free(void *ptr)
 	CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line);
 #endif
 
+	block = MEMBLOCK(ptr);
+#ifdef PARANOIA
+	if (block->id != ZONEID)
 #ifdef ZDEBUG
-	block = Ptr2Memblock2(ptr, "Z_Free", file, line);
+		I_Error("Z_Free at %s:%d: wrong id", file, line);
 #else
-	block = Ptr2Memblock(ptr, "Z_Free");
+		I_Error("Z_Free: wrong id");
+#endif
 #endif
 
 #ifdef ZDEBUG
@@ -229,8 +162,6 @@ void Z_Free(void *ptr)
 	if (block->user != NULL)
 		*block->user = NULL;
 
-	// Free the memory and get rid of the block.
-	free(block->real);
 #ifdef VALGRIND_DESTROY_MEMPOOL
 	VALGRIND_DESTROY_MEMPOOL(block);
 #endif
@@ -287,35 +218,17 @@ void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits,
 void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
 #endif
 {
-	I_Assert(alignbits >= 0 && alignbits < (INT32)(sizeof(size_t) * 8));
-	size_t extrabytes = ((size_t)1<<alignbits) - 1;
-	size_t padsize = 0;
 	memblock_t *block;
 	void *ptr;
-	memhdr_t *hdr;
-	void *given;
-	size_t blocksize = extrabytes + sizeof *hdr + size;
+	(void)(alignbits); // no longer used, so silence warnings.
 
 #ifdef ZDEBUG2
 	CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line);
 #endif
 
-	if (blocksize < size)/* overflow check */
-		I_Error("You are allocating memory too large!");
-
-	block = xm(sizeof *block);
-#ifdef HAVE_VALGRIND
-	padsize += (1<<sizeof(size_t))*2;
-#endif
-	ptr = xm(blocksize + padsize*2);
-
-	// This horrible calculation makes sure that "given" is aligned
-	// properly.
-	given = (void *)((size_t)((UINT8 *)ptr + extrabytes + sizeof *hdr + padsize/2)
-		& ~extrabytes);
-
-	// The mem header lives 'sizeof (memhdr_t)' bytes before given.
-	hdr = (memhdr_t *)((UINT8 *)given - sizeof *hdr);
+	block = xm(sizeof (memblock_t) + size);
+	ptr = MEMORY(block);
+	I_Assert((intptr_t)ptr % sizeof (void *) == 0);
 
 #ifdef HAVE_VALGRIND
 	Z_calloc = false;
@@ -326,41 +239,31 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits)
 	head.next = block;
 	block->next->prev = block;
 
-	block->real = ptr;
-	block->hdr = hdr;
 	block->tag = tag;
 	block->user = NULL;
 #ifdef ZDEBUG
 	block->ownerline = line;
 	block->ownerfile = file;
 #endif
-	block->size = blocksize;
+	block->size = sizeof (memblock_t) + size;
 	block->realsize = size;
 
 #ifdef VALGRIND_CREATE_MEMPOOL
-	VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc);
+	VALGRIND_CREATE_MEMPOOL(block, size, Z_calloc);
 #endif
-//#ifdef VALGRIND_MEMPOOL_ALLOC
-//	VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr);
-//#endif
 
-	hdr->id = ZONEID;
-	hdr->block = block;
-
-#ifdef VALGRIND_MAKE_MEM_NOACCESS
-	VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr);
-#endif
+	block->id = ZONEID;
 
 	if (user != NULL)
 	{
 		block->user = user;
-		*(void **)user = given;
+		*(void **)user = ptr;
 	}
 	else if (tag >= PU_PURGELEVEL)
 		I_Error("Z_Malloc: attempted to allocate purgable block "
 			"(size %s) with no user", sizeu1(size));
 
-	return given;
+	return ptr;
 }
 
 /** The Z_CallocAlign function.
@@ -437,10 +340,14 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb
 #endif
 	}
 
+	block = MEMBLOCK(ptr);
+#ifdef PARANOIA
+	if (block->id != ZONEID)
 #ifdef ZDEBUG
-	block = Ptr2Memblock2(ptr, "Z_Realloc", file, line);
+		I_Error("Z_ReallocAlign at %s:%d: wrong id", file, line);
 #else
-	block = Ptr2Memblock(ptr, "Z_Realloc");
+		I_Error("Z_ReallocAlign: wrong id");
+#endif
 #endif
 
 	if (block == NULL)
@@ -491,9 +398,8 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag)
 	for (block = head.next; block != &head; block = next)
 	{
 		next = block->next; // get link before freeing
-
 		if (block->tag >= lowtag && block->tag <= hightag)
-			Z_Free((UINT8 *)block->hdr + sizeof *block->hdr);
+			Z_Free(MEMORY(block));
 	}
 }
 
@@ -516,7 +422,7 @@ void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *))
 
 		if (block->tag >= lowtag && block->tag <= hightag)
 		{
-			void *mem = (UINT8 *)block->hdr + sizeof *block->hdr;
+			void *mem = MEMORY(block);
 			boolean free = iterfunc(mem);
 			if (free)
 				Z_Free(mem);
@@ -561,15 +467,13 @@ void Z_CheckMemCleanup(void)
 void Z_CheckHeap(INT32 i)
 {
 	memblock_t *block;
-	memhdr_t *hdr;
 	UINT32 blocknumon = 0;
 	void *given;
 
 	for (block = head.next; block != &head; block = block->next)
 	{
 		blocknumon++;
-		hdr = block->hdr;
-		given = (UINT8 *)hdr + sizeof *hdr;
+		given = MEMORY(block);
 #ifdef ZDEBUG2
 		CONS_Debug(DBG_MEMORY, "block %u owned by %s:%d\n",
 			blocknumon, block->ownerfile, block->ownerline);
@@ -585,7 +489,7 @@ void Z_CheckHeap(INT32 i)
 #ifdef ZDEBUG
 				, block->ownerfile, block->ownerline
 #endif
-			        );
+				);
 		}
 #endif
 		if (block->user != NULL && *(block->user) != given)
@@ -598,7 +502,7 @@ void Z_CheckHeap(INT32 i)
 #ifdef ZDEBUG
 				, block->ownerfile, block->ownerline
 #endif
-			       );
+				);
 		}
 		if (block->next->prev != block)
 		{
@@ -610,7 +514,7 @@ void Z_CheckHeap(INT32 i)
 #ifdef ZDEBUG
 				, block->ownerfile, block->ownerline
 #endif
-			       );
+				);
 		}
 		if (block->prev->next != block)
 		{
@@ -622,25 +526,9 @@ void Z_CheckHeap(INT32 i)
 #ifdef ZDEBUG
 				, block->ownerfile, block->ownerline
 #endif
-			       );
+				);
 		}
-#ifdef VALGRIND_MAKE_MEM_DEFINED
-		VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr);
-#endif
-		if (hdr->block != block)
-		{
-			I_Error("Z_CheckHeap %d: block %u"
-#ifdef ZDEBUG
-				"(owned by %s:%d)"
-#endif
-				" doesn't have linkback from allocated memory",
-				i, blocknumon
-#ifdef ZDEBUG
-				, block->ownerfile, block->ownerline
-#endif
-					);
-		}
-		if (hdr->id != ZONEID)
+		if (block->id != ZONEID)
 		{
 			I_Error("Z_CheckHeap %d: block %u"
 #ifdef ZDEBUG
@@ -650,11 +538,8 @@ void Z_CheckHeap(INT32 i)
 #ifdef ZDEBUG
 				, block->ownerfile, block->ownerline
 #endif
-					);
+				);
 		}
-#ifdef VALGRIND_MAKE_MEM_NOACCESS
-	VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr);
-#endif
 	}
 }
 
@@ -676,35 +561,14 @@ void Z_ChangeTag(void *ptr, INT32 tag)
 #endif
 {
 	memblock_t *block;
-	memhdr_t *hdr;
 
 	if (ptr == NULL)
 		return;
 
-	hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr);
-
-#ifdef VALGRIND_MAKE_MEM_DEFINED
-	VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr);
-#endif
+	block = MEMBLOCK(ptr);
 
-#ifdef VALGRIND_MEMPOOL_EXISTS
-	if (!VALGRIND_MEMPOOL_EXISTS(hdr->block))
-	{
-#ifdef PARANOIA
-		I_Error("Z_CT at %s:%d: bad memblock", file, line);
-#else
-		I_Error("Z_CT: bad memblock");
-#endif
-	}
-#endif
 #ifdef PARANOIA
-	if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line);
-#endif
-
-	block = hdr->block;
-
-#ifdef VALGRIND_MAKE_MEM_NOACCESS
-	VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr);
+	if (block->id != ZONEID) I_Error("Z_ChangeTag at %s:%d: wrong id", file, line);
 #endif
 
 	if (tag >= PU_PURGELEVEL && block->user == NULL)
@@ -728,25 +592,14 @@ void Z_SetUser(void *ptr, void **newuser)
 #endif
 {
 	memblock_t *block;
-	memhdr_t *hdr;
 
 	if (ptr == NULL)
 		return;
 
-	hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr);
-
-#ifdef VALGRIND_MAKE_MEM_DEFINED
-	VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr);
-#endif
+	block = MEMBLOCK(ptr);
 
 #ifdef PARANOIA
-	if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line);
-#endif
-
-	block = hdr->block;
-
-#ifdef VALGRIND_MAKE_MEM_NOACCESS
-	VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr);
+	if (block->id != ZONEID) I_Error("Z_SetUser at %s:%d: wrong id", file, line);
 #endif
 
 	if (block->tag >= PU_PURGELEVEL && newuser == NULL)
-- 
GitLab