From 0e6e346b32c4b3f9337dad1568446ccd63d14505 Mon Sep 17 00:00:00 2001 From: Fabian Greffrath Date: Fri, 24 Jun 2022 09:01:49 +0200 Subject: [PATCH] simplify and adapt z_zone.c to DSDA-Doom (#620) * simplify and adapt z_zone.c to DSDA-Doom * remove the INSTRUMENTED macro * remove Z_Init() and Z_CheckHeap() * remove PU_LOCKED * eplicitly free all cached memory blocks on level setup * assure proper pointer alignment * fix headers * reorder struct memblock, decrease padding * add back historic changelogs --- CMakeLists.txt | 1 - setup/mainmenu.c | 2 - src/CMakeLists.txt | 3 - src/d_main.c | 2 - src/g_game.c | 11 - src/i_video.c | 4 - src/m_cheat.c | 17 -- src/mus2mid.c | 2 - src/p_setup.c | 3 +- src/z_zone.c | 724 +++++++-------------------------------------- src/z_zone.h | 43 +-- 11 files changed, 131 insertions(+), 681 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 209035e6..63f72857 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,7 +48,6 @@ if(NOT WIN32) endif() # Toggle-able defines added at compile-time. -option("${PROJECT_NAME}_INSTRUMENTED" "Enable memory allocation statistics" OFF) option("${PROJECT_NAME}_RANGECHECK" "Enable bounds-checking of performance-sensitive functions" ON) option("${PROJECT_NAME}_STRICT" "Prefer original MBF code paths over demo compatiblity with PrBoom+" OFF) diff --git a/setup/mainmenu.c b/setup/mainmenu.c index 584d5a95..0668c872 100644 --- a/setup/mainmenu.c +++ b/setup/mainmenu.c @@ -178,8 +178,6 @@ static void MissionSet(void) void D_DoomMain(void) { - Z_Init(); - //SetupMission(MissionSet); MissionSet(); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 66a465ce..619ec790 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -176,9 +176,6 @@ endif() # # Our defines are not namespaced, so we pass them at compile-time instead of # using config.h. -if("${${PROJECT_NAME}_INSTRUMENTED}") - target_compile_definitions(woof PRIVATE INSTRUMENTED) -endif() if("${${PROJECT_NAME}_RANGECHECK}") target_compile_definitions(woof PRIVATE RANGECHECK) endif() diff --git a/src/d_main.c b/src/d_main.c index 025c5378..257cf876 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1648,8 +1648,6 @@ void D_DoomMain(void) setbuf(stdout,NULL); - Z_Init(); // 1/18/98 killough: start up memory stuff first - I_AtExitPrio(I_QuitFirst, true, "I_QuitFirst", exit_priority_first); I_AtExitPrio(I_QuitLast, false, "I_QuitLast", exit_priority_last); I_AtExitPrio(I_Quit, true, "I_Quit", exit_priority_last); diff --git a/src/g_game.c b/src/g_game.c index 1225c95c..996d8036 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -716,7 +716,6 @@ static void G_DoLoadLevel(void) P_SetupLevel (gameepisode, gamemap, 0, gameskill); displayplayer = consoleplayer; // view the guy you are playing gameaction = ga_nothing; - Z_CheckHeap(); // clear cmd building stuff memset (gamekeydown, 0, sizeof(gamekeydown)); @@ -1759,17 +1758,11 @@ static void G_DoSaveGame(void) // killough 11/98: save revenant tracer state *save_p++ = (gametic-basetic) & 255; - // killough 3/22/98: add Z_CheckHeap after each call to ensure consistency - Z_CheckHeap(); P_ArchivePlayers(); - Z_CheckHeap(); P_ArchiveWorld(); - Z_CheckHeap(); P_ArchiveThinkers(); - Z_CheckHeap(); P_ArchiveSpecials(); P_ArchiveRNG(); // killough 1/18/98: save RNG information - Z_CheckHeap(); P_ArchiveMap(); // killough 1/22/98: save automap information *save_p++ = 0xe6; // consistancy marker @@ -1792,8 +1785,6 @@ static void G_DoSaveGame(void) length = save_p - savebuffer; - Z_CheckHeap(); - if (!M_WriteFile(name, savebuffer, length)) dprintf("%s", errno ? strerror(errno) : "Could not save game: Error unknown"); else @@ -1969,8 +1960,6 @@ static void G_DoLoadGame(void) // draw the pattern into the back screen R_FillBackScreen(); - Z_CheckHeap(); - // killough 12/98: support -recordfrom and -loadgame -playdemo if (!command_loadgame) singledemo = false; // Clear singledemo flag if loading from menu diff --git a/src/i_video.c b/src/i_video.c index c9a506bd..21797f14 100644 --- a/src/i_video.c +++ b/src/i_video.c @@ -1669,8 +1669,6 @@ void I_ResetScreen(void) WI_DrawBackground(); V_CopyRect(0, 0, 1, SCREENWIDTH, SCREENHEIGHT, 0, 0, 0); } - - Z_CheckHeap(); M_ResetSetupMenuVideo(); } @@ -1705,8 +1703,6 @@ void I_InitGraphics(void) I_InitGraphicsMode(); // killough 10/98 - Z_CheckHeap(); - M_ResetSetupMenuVideo(); } diff --git a/src/m_cheat.c b/src/m_cheat.c index b214aee1..9ee7748d 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -84,10 +84,6 @@ static void cheat_rate(); static void cheat_buddha(); static void cheat_spechits(); -#ifdef INSTRUMENTED -static void cheat_printstats(); // killough 8/23/98 -#endif - static void cheat_autoaim(); // killough 7/19/98 static void cheat_tst(); static void cheat_showfps(); // [FG] FPS counter widget @@ -274,11 +270,6 @@ struct cheat_s cheat[] = { {"nc", NULL, not_net | not_demo | beta_only, cheat_noclip }, -#ifdef INSTRUMENTED - {"stat", NULL, always, - cheat_printstats}, -#endif - // [FG] FPS counter widget {"showfps", NULL, always, cheat_showfps}, @@ -288,14 +279,6 @@ struct cheat_s cheat[] = { //----------------------------------------------------------------------------- -#ifdef INSTRUMENTED -static void cheat_printstats() // killough 8/23/98 -{ - if (!(printstats=!printstats)) - plyr->message = "Memory stats off"; -} -#endif - // [FG] FPS counter widget static void cheat_showfps() { diff --git a/src/mus2mid.c b/src/mus2mid.c index 24f6ff32..34b003c3 100644 --- a/src/mus2mid.c +++ b/src/mus2mid.c @@ -717,8 +717,6 @@ int main(int argc, char *argv[]) exit(-1); } - Z_Init(); - infile_len = M_ReadFile(argv[1], &infile); src = mem_fopen_read(infile, infile_len); diff --git a/src/p_setup.c b/src/p_setup.c index 8363c282..f3818440 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1528,7 +1528,8 @@ void P_SetupLevel(int episode, int map, int playermask, skill_t skill) // Make sure all sounds are stopped before Z_FreeTags. S_Start(); - Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1); + Z_FreeTag(PU_LEVEL); + Z_FreeTag(PU_CACHE); P_InitThinkers(); diff --git a/src/z_zone.c b/src/z_zone.c index cd0eba5b..6e827558 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -35,670 +35,176 @@ //----------------------------------------------------------------------------- #include "z_zone.h" -#include "doomstat.h" -#include "m_argv.h" - -// Uncomment this to see real-time memory allocation -// statistics, to and enable extra debugging features -//#define INSTRUMENTED - -// Uncomment this to exhaustively run memory checks -// while the game is running (this is EXTREMELY slow). -// Only useful if INSTRUMENTED is also defined. -//#define CHECKHEAP - -// Uncomment this to perform id checks on zone blocks, -// to detect corrupted and illegally freed blocks -#define ZONEIDCHECK - -// Tunables - -// Alignment of zone memory (benefit may be negated by HEADER_SIZE, CHUNK_SIZE) -#define CACHE_ALIGN 32 - -// size of block header -//#define HEADER_SIZE 32 +#include "i_system.h" // Minimum chunk size at which blocks are allocated -#define CHUNK_SIZE 32 - -// Minimum size a block must be to become part of a split -#define MIN_BLOCK_SPLIT (1024) - -// How much RAM to leave aside for other libraries -#define LEAVE_ASIDE (128*1024) - -// Minimum RAM machine is assumed to have -#define MIN_RAM (7*1024*1024) - -// [FG] allocate 64 MiB by default -#define DEF_RAM (64*1024*1024) - -// Amount to subtract when retrying failed attempts to allocate initial pool -#define RETRY_AMOUNT (256*1024) +#define CHUNK_SIZE sizeof(void *) // signature for block header #define ZONEID 0x931d4a11 -// Number of mallocs & frees kept in history buffer (must be a power of 2) -#define ZONE_HISTORY 4 - -// End Tunables - typedef struct memblock { - -#ifdef ZONEIDCHECK - unsigned id; -#endif - struct memblock *next,*prev; size_t size; void **user; - unsigned char tag,vm; - -#ifdef INSTRUMENTED - unsigned short extra; - const char *file; - int line; -#endif - + unsigned id; + int tag; } memblock_t; -/* size of block header - * cph - base on sizeof(memblock_t), which can be larger than CHUNK_SIZE on - * 64bit architectures */ static const size_t HEADER_SIZE = (sizeof(memblock_t)+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1); -static memblock_t *rover; // roving pointer to memory blocks -static memblock_t *zone; // pointer to first block -static memblock_t *zonebase; // pointer to entire zone memory -static size_t zonebase_size; // zone memory allocated size static memblock_t *blockbytag[PU_MAX]; -#ifdef INSTRUMENTED - -// statistics for evaluating performance -static size_t free_memory; -static size_t active_memory; -static size_t purgable_memory; -static size_t inactive_memory; -static size_t virtual_memory; - -int printstats; // killough 8/23/98 - -void Z_PrintStats(void) // Print allocation statistics -{ - if (printstats) - { - unsigned long total_memory = free_memory + active_memory + - purgable_memory + inactive_memory + - virtual_memory; - double s = 100.0 / total_memory; - - dprintf("%-5lu\t%6.01f%%\tstatic\n" - "%-5lu\t%6.01f%%\tpurgable\n" - "%-5lu\t%6.01f%%\tfree\n" - "%-5lu\t%6.01f%%\tfragmentary\n" - "%-5lu\t%6.01f%%\tvirtual\n" - "%-5lu\t\ttotal\n", - active_memory, - active_memory*s, - purgable_memory, - purgable_memory*s, - free_memory, - free_memory*s, - inactive_memory, - inactive_memory*s, - virtual_memory, - virtual_memory*s, - total_memory - ); - } -} -#endif - -#ifdef INSTRUMENTED - -// killough 4/26/98: Add history information - -enum {malloc_history, free_history, NUM_HISTORY_TYPES}; - -static const char *file_history[NUM_HISTORY_TYPES][ZONE_HISTORY]; -static int line_history[NUM_HISTORY_TYPES][ZONE_HISTORY]; -static int history_index[NUM_HISTORY_TYPES]; -static const char *const desc[NUM_HISTORY_TYPES] = {"malloc()'s", "free()'s"}; - -void Z_DumpHistory(char *buf) -{ - int i,j; - char s[1024]; - strcat(buf,"\n"); - for (i=0;i= sizeof(memblock_t) && MIN_RAM > LEAVE_ASIDE); - - I_AtExitPrio(Z_Close, true, "Z_Close", exit_priority_verylast); // exit handler - - size = (size+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1); // round to chunk size - - // Allocate the memory - - while (!(zonebase=malloc(zonebase_size=size + HEADER_SIZE + CACHE_ALIGN))) - if (size < (MIN_RAM-LEAVE_ASIDE < RETRY_AMOUNT ? RETRY_AMOUNT : - MIN_RAM-LEAVE_ASIDE)) - I_Error("Z_Init: failed on allocation of %lu bytes",(unsigned long) - zonebase_size); - else - size -= RETRY_AMOUNT; - - // Align on cache boundary - - zone = (memblock_t *) ((char *) zonebase + CACHE_ALIGN - - ((uintptr_t) zonebase & (CACHE_ALIGN-1))); - - rover = zone; // Rover points to base of zone mem - zone->next = zone->prev = zone; // Single node - zone->size = size; // All memory in one block - zone->tag = PU_FREE; // A free block - zone->vm = 0; - -#ifdef ZONEIDCHECK - zone->id = 0; -#endif - -#ifdef INSTRUMENTED - free_memory = size; - inactive_memory = zonebase_size - size; - active_memory = purgable_memory = 0; -#endif -} - // Z_Malloc -// You can pass a NULL user if the tag is < PU_PURGELEVEL. +// You can pass a NULL user if the tag is < PU_CACHE. -void *(Z_Malloc)(size_t size, int tag, void **user, const char *file, int line) +void *Z_Malloc(size_t size, int tag, void **user) { - register memblock_t *block; - memblock_t *start; - -#ifdef INSTRUMENTED - size_t size_orig = size; -#ifdef CHECKHEAP - Z_CheckHeap(); -#endif - - file_history[malloc_history][history_index[malloc_history]] = file; - line_history[malloc_history][history_index[malloc_history]++] = line; - history_index[malloc_history] &= ZONE_HISTORY-1; -#endif + memblock_t *block = NULL; -#ifdef ZONEIDCHECK - if(tag >= PU_PURGELEVEL && !user) - I_Error("Z_Malloc: an owner is required for purgable blocks\n" - "Source: %s:%d", file, line); -#endif + if (tag == PU_CACHE && !user) + I_Error ("Z_Malloc: An owner is required for purgable blocks"); - if(!size) - return user ? *user = NULL : NULL; // malloc(0) returns NULL - - size = (size+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1); // round to chunk size - - block = rover; - - if(block->prev->tag == PU_FREE) - block = block->prev; - - start = block; + if (!size) + return user ? *user = NULL : NULL; // malloc(0) returns NULL - // haleyjd 06/17/08: import from EE: - // the first if() inside the loop below contains cph's memory - // purging efficiency fix + while (!(block = malloc(size + HEADER_SIZE))) + { + if (!blockbytag[PU_CACHE]) + I_Error ("Z_Malloc: Failure trying to allocate %lu bytes", (unsigned long) size); + Z_FreeTag(PU_CACHE); + } - do - { - // Free purgable blocks; replacement is roughly FIFO - if(block->tag >= PU_PURGELEVEL) - { - start = block->prev; - Z_Free((char *) block + HEADER_SIZE); - /* cph - If start->next == block, we did not merge with the previous - * If !=, we did, so we continue from start. - * Important: we've reset start! - */ - if(start->next == block) - start = start->next; - else - block = start; - } - - if(block->tag == PU_FREE && block->size >= size) // First-fit - { - size_t extra = block->size - size; - if(extra >= MIN_BLOCK_SPLIT + HEADER_SIZE) - { - memblock_t *newb = - (memblock_t *)((char *) block + HEADER_SIZE + size); + if (!blockbytag[tag]) + { + blockbytag[tag] = block; + block->next = block->prev = block; + } + else + { + blockbytag[tag]->prev->next = block; + block->prev = blockbytag[tag]->prev; + block->next = blockbytag[tag]; + blockbytag[tag]->prev = block; + } - (newb->next = block->next)->prev = newb; - (newb->prev = block)->next = newb; // Split up block - block->size = size; - newb->size = extra - HEADER_SIZE; - newb->tag = PU_FREE; - newb->vm = 0; - -#ifdef INSTRUMENTED - inactive_memory += HEADER_SIZE; - free_memory -= HEADER_SIZE; -#endif - } + block->size = size; + block->id = ZONEID; // signature required in block header + block->tag = tag; // tag + block->user = user; // user + block = (memblock_t *)((char *) block + HEADER_SIZE); + if (user) // if there is a user + *user = block; // set user to point to new block - rover = block->next; // set roving pointer for next search - -#ifdef INSTRUMENTED - inactive_memory += block->extra = block->size - size_orig; - if(tag >= PU_PURGELEVEL) - purgable_memory += size_orig; - else - active_memory += size_orig; - free_memory -= block->size; -#endif - -allocated: - -#ifdef INSTRUMENTED - block->file = file; - block->line = line; -#endif - -#ifdef ZONEIDCHECK - block->id = ZONEID; // signature required in block header -#endif - block->tag = tag; // tag - block->user = user; // user - block = (memblock_t *)((char *) block + HEADER_SIZE); - if(user) // if there is a user - *user = block; // set user to point to new block - -#ifdef INSTRUMENTED - Z_PrintStats(); // print memory allocation stats - // scramble memory -- weed out any bugs - memset(block, gametic & 0xff, size); -#endif - return block; - } - } - while ((block = block->next) != start); // detect cycles as failure - - // We've run out of physical memory, or so we think. - // Although less efficient, we'll just use ordinary malloc. - // This will squeeze the remaining juice out of this machine - // and start cutting into virtual memory if it has it. - - while(!(block = malloc(size + HEADER_SIZE))) - { - if(!blockbytag[PU_CACHE]) - I_Error("Z_Malloc: Failure trying to allocate %lu bytes" - "\nSource: %s:%d",(unsigned long) size, file, line); - Z_FreeTags(PU_CACHE, PU_CACHE); - } - - if((block->next = blockbytag[tag])) - block->next->prev = (memblock_t *) &block->next; - blockbytag[tag] = block; - block->prev = (memblock_t *) &blockbytag[tag]; - block->vm = 1; - - // haleyjd: cph's virtual memory error fix -#ifdef INSTRUMENTED - virtual_memory += size + HEADER_SIZE; - - // haleyjd 06/17/08: Import from EE: - // Big problem: extra wasn't being initialized for vm - // blocks. This caused the memset used to randomize freed memory when - // INSTRUMENTED is defined to stomp all over the C heap. - block->extra = 0; -#endif - /* cph - the next line was lost in the #ifdef above, and also added an - * extra HEADER_SIZE to block->size, which was incorrect */ - block->size = size; - goto allocated; + return block; } -void (Z_Free)(void *p, const char *file, int line) +void Z_Free(void *p) { -#ifdef INSTRUMENTED -#ifdef CHECKHEAP - Z_CheckHeap(); -#endif - file_history[free_history][history_index[free_history]] = file; - line_history[free_history][history_index[free_history]++] = line; - history_index[free_history] &= ZONE_HISTORY-1; -#endif - - if(p) - { - memblock_t *other, *block = (memblock_t *)((char *) p - HEADER_SIZE); - -#ifdef ZONEIDCHECK - if(block->id != ZONEID) - I_Error("Z_Free: freed a pointer without ZONEID\n" - "Source: %s:%d" + memblock_t *block = (memblock_t *)((char *) p - HEADER_SIZE); -#ifdef INSTRUMENTED - "\nSource of malloc: %s:%d" - , file, line, block->file, block->line -#else - , file, line -#endif - ); - block->id = 0; // Nullify id so another free fails -#endif + if (!p) + return; -#ifdef INSTRUMENTED - // scramble memory -- weed out any bugs - memset(p, gametic & 0xff, block->size - block->extra); -#endif + if (block->id != ZONEID) + I_Error("Z_Free: freed a pointer without ZONEID"); + block->id = 0; // Nullify id so another free fails - if(block->user) // Nullify user if one exists - *block->user = NULL; - - if(block->vm) - { - if((*(memblock_t **) block->prev = block->next)) - block->next->prev = block->prev; + if (block->user) // Nullify user if one exists + *block->user = NULL; -#ifdef INSTRUMENTED - virtual_memory -= block->size; -#endif -// free(block); // [FG] TODO - } - else - { + if (block == block->next) + blockbytag[block->tag] = NULL; + else + if (blockbytag[block->tag] == block) + blockbytag[block->tag] = block->next; + block->prev->next = block->next; + block->next->prev = block->prev; -#ifdef INSTRUMENTED - free_memory += block->size; - inactive_memory -= block->extra; - if(block->tag >= PU_PURGELEVEL) - purgable_memory -= block->size - block->extra; - else - active_memory -= block->size - block->extra; -#endif - - block->tag = PU_FREE; // Mark block freed - - if(block != zone) - { - other = block->prev; // Possibly merge with previous block - if(other->tag == PU_FREE) - { - if(rover == block) // Move back rover if it points at block - rover = other; - (other->next = block->next)->prev = other; - other->size += block->size + HEADER_SIZE; - block = other; - -#ifdef INSTRUMENTED - inactive_memory -= HEADER_SIZE; - free_memory += HEADER_SIZE; -#endif - } - } - - other = block->next; // Possibly merge with next block - if(other->tag == PU_FREE && other != zone) - { - if(rover == other) // Move back rover if it points at next block - rover = block; - (block->next = other->next)->prev = block; - block->size += other->size + HEADER_SIZE; - -#ifdef INSTRUMENTED - inactive_memory -= HEADER_SIZE; - free_memory += HEADER_SIZE; -#endif - } - } - -#ifdef INSTRUMENTED - Z_PrintStats(); // print memory allocation stats -#endif - } + free(block); } -void (Z_FreeTags)(int lowtag, int hightag, const char *file, int line) +void Z_FreeTag(int tag) { - memblock_t *block = zone; - - if(lowtag <= PU_FREE) - lowtag = PU_FREE+1; + memblock_t *block, *end_block; - // haleyjd: code inside this do loop has been updated with - // cph's fix for memory wastage - - do // Scan through list, searching for tags in range - { - if(block->tag >= lowtag && block->tag <= hightag) - { - memblock_t *prev = block->prev, *cur = block;; - (Z_Free)((char *) block + HEADER_SIZE, file, line); - /* cph - be more careful here, we were skipping blocks! - * If the current block was not merged with the previous, - * cur is still a valid pointer, prev->next == cur, and cur is - * already free so skip to the next. - * If the current block was merged with the previous, - * the next block to analyse is prev->next. - * Note that the while() below does the actual step forward - */ - block = (prev->next == cur) ? cur : prev; - } - } - while((block = block->next) != zone); + if (tag < 0 || tag >= PU_MAX) + I_Error("Z_FreeTag: Tag %i does not exist", tag); - if(hightag > PU_CACHE) - hightag = PU_CACHE; - - for(; lowtag <= hightag; ++lowtag) - { - for(block = blockbytag[lowtag], blockbytag[lowtag] = NULL; block;) - { - memblock_t *next = block->next; - -#ifdef ZONEIDCHECK - if(block->id != ZONEID) - I_Error("Z_FreeTags: Changed a tag without ZONEID\n" - "Source: %s:%d" - -#ifdef INSTRUMENTED - "\nSource of malloc: %s:%d" - , file, line, block->file, block->line -#else - , file, line -#endif - ); - - block->id = 0; // Nullify id so another free fails -#endif - -#ifdef INSTRUMENTED - virtual_memory -= block->size; -#endif - - if(block->user) // Nullify user if one exists - *block->user = NULL; - - free(block); // Free the block - - block = next; // Advance to next block - } - } + block = blockbytag[tag]; + if (!block) + return; + end_block = block->prev; + while (1) + { + memblock_t *next = block->next; + Z_Free((char *) block + HEADER_SIZE); + if (block == end_block) + break; + block = next; // Advance to next block + } } -void (Z_ChangeTag)(void *ptr, int tag, const char *file, int line) +void Z_ChangeTag(void *ptr, int tag) { memblock_t *block = (memblock_t *)((char *) ptr - HEADER_SIZE); -#ifdef INSTRUMENTED -#ifdef CHECKHEAP - Z_CheckHeap(); -#endif -#endif + // proff - added sanity check, this can happen when an empty lump is locked + if (!ptr) + return; + + // proff - do nothing if tag doesn't differ + if (tag == block->tag) + return; -#ifdef ZONEIDCHECK if (block->id != ZONEID) - I_Error ("Z_ChangeTag: Changed a tag without ZONEID" - "\nSource: %s:%d" + I_Error ("Z_ChangeTag: freed a pointer without ZONEID"); -#ifdef INSTRUMENTED - "\nSource of malloc: %s:%d" - , file, line, block->file, block->line -#else - , file, line -#endif - ); + if (tag == PU_CACHE && !block->user) + I_Error ("Z_ChangeTag: an owner is required for purgable blocks\n"); - if (tag >= PU_PURGELEVEL && !block->user) - I_Error ("Z_ChangeTag: an owner is required for purgable blocks\n" - "Source: %s:%d" -#ifdef INSTRUMENTED - "\nSource of malloc: %s:%d" - , file, line, block->file, block->line -#else - , file, line -#endif - ); - -#endif // ZONEIDCHECK - - if (block->vm) - { - if ((*(memblock_t **) block->prev = block->next)) - block->next->prev = block->prev; - if ((block->next = blockbytag[tag])) - block->next->prev = (memblock_t *) &block->next; - block->prev = (memblock_t *) &blockbytag[tag]; - blockbytag[tag] = block; - } + if (block == block->next) + blockbytag[block->tag] = NULL; else - { -#ifdef INSTRUMENTED - if (block->tag < PU_PURGELEVEL && tag >= PU_PURGELEVEL) - { - active_memory -= block->size - block->extra; - purgable_memory += block->size - block->extra; - } - else - if (block->tag >= PU_PURGELEVEL && tag < PU_PURGELEVEL) - { - active_memory += block->size - block->extra; - purgable_memory -= block->size - block->extra; - } -#endif - } + if (blockbytag[block->tag] == block) + blockbytag[block->tag] = block->next; + block->prev->next = block->next; + block->next->prev = block->prev; + + if (!blockbytag[tag]) + { + blockbytag[tag] = block; + block->next = block->prev = block; + } + else + { + blockbytag[tag]->prev->next = block; + block->prev = blockbytag[tag]->prev; + block->next = blockbytag[tag]; + blockbytag[tag]->prev = block; + } + block->tag = tag; } -void *(Z_Realloc)(void *ptr, size_t n, int tag, void **user, - const char *file, int line) +void *Z_Realloc(void *ptr, size_t n, int tag, void **user) { - void *p = (Z_Malloc)(n, tag, user, file, line); - if(ptr) - { - memblock_t *block = (memblock_t *)((char *)ptr - HEADER_SIZE); - if(p) // haleyjd 06/17/08: allow to return NULL without crashing - memcpy(p, ptr, n <= block->size ? n : block->size); - (Z_Free)(ptr, file, line); - if(user) // in case Z_Free nullified same user - *user=p; - } - return p; + void *p = Z_Malloc(n, tag, user); + if (ptr) + { + memblock_t *block = (memblock_t *)((char *) ptr - HEADER_SIZE); + memcpy(p, ptr, n <= block->size ? n : block->size); + Z_Free(ptr); + if (user) // in case Z_Free nullified same user + *user=p; + } + return p; } -void *(Z_Calloc)(size_t n1, size_t n2, int tag, void **user, - const char *file, int line) +void *Z_Calloc(size_t n1, size_t n2, int tag, void **user) { - return (n1*=n2) ? memset((Z_Malloc)(n1, tag, user, file, line), 0, n1) : NULL; -} - -char *(Z_Strdup)(const char *s, int tag, void **user, - const char *file, int line) -{ - return strcpy((Z_Malloc)(strlen(s)+1, tag, user, file, line), s); -} - -void (Z_CheckHeap)(const char *file, int line) -{ - memblock_t *block = zone; // Start at base of zone mem - do // Consistency check (last node treated special) - { - if((block->next != zone && - (memblock_t *)((char *) block+HEADER_SIZE+block->size) != block->next) || - block->next->prev != block || block->prev->next != block) - { - I_Error("Z_CheckHeap: Block size does not touch the next block\n" - "Source: %s:%d" -#ifdef INSTRUMENTED - "\nSource of offending block: %s:%d" - , file, line, block->file, block->line -#else - , file, line -#endif - ); - } - } - while((block = block->next) != zone); + return + (n1*=n2) ? memset(Z_Malloc(n1, tag, user), 0, n1) : NULL; } //----------------------------------------------------------------------------- diff --git a/src/z_zone.h b/src/z_zone.h index 9d29915f..afc80932 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -47,43 +47,28 @@ // ZONE MEMORY // PU - purge tags. -enum {PU_FREE, PU_STATIC, PU_SOUND, PU_MUSIC, PU_LEVEL, PU_LEVSPEC, PU_CACHE, - /* Must always be last -- killough */ PU_MAX}; +enum { + PU_STATIC, + PU_LEVEL, + PU_CACHE, + /* Must always be last -- killough */ + PU_MAX +}; -#define PU_PURGELEVEL PU_CACHE /* First purgable tag's level */ +#define PU_LEVSPEC PU_LEVEL -void *(Z_Malloc)(size_t size, int tag, void **ptr, const char *, int); -void (Z_Free)(void *ptr, const char *, int); -void (Z_FreeTags)(int lowtag, int hightag, const char *, int); -void (Z_ChangeTag)(void *ptr, int tag, const char *, int); -void (Z_Init)(void); -void *(Z_Calloc)(size_t n, size_t n2, int tag, void **user, const char *, int); -void *(Z_Realloc)(void *p, size_t n, int tag, void **user, const char *, int); -char *(Z_Strdup)(const char *s, int tag, void **user, const char *, int); -void (Z_CheckHeap)(const char *,int); // killough 3/22/98: add file/line info -void Z_DumpHistory(char *); - -#define Z_Free(a) (Z_Free) (a, __FILE__,__LINE__) -#define Z_FreeTags(a,b) (Z_FreeTags) (a,b, __FILE__,__LINE__) -#define Z_ChangeTag(a,b) (Z_ChangeTag)(a,b, __FILE__,__LINE__) -#define Z_Malloc(a,b,c) (Z_Malloc) (a,b,c, __FILE__,__LINE__) -#define Z_Strdup(a,b,c) (Z_Strdup) (a,b,c, __FILE__,__LINE__) -#define Z_Calloc(a,b,c,d) (Z_Calloc) (a,b,c,d,__FILE__,__LINE__) -#define Z_Realloc(a,b,c,d) (Z_Realloc) (a,b,c,d,__FILE__,__LINE__) -#define Z_CheckHeap() (Z_CheckHeap)(__FILE__,__LINE__) +void *Z_Malloc(size_t size, int tag, void **ptr); +void Z_Free(void *ptr); +void Z_FreeTag(int tag); +void Z_ChangeTag(void *ptr, int tag); +void *Z_Calloc(size_t n, size_t n2, int tag, void **user); +void *Z_Realloc(void *p, size_t n, int tag, void **user); // dprintf() is already declared in , define it out of the way #define dprintf doomprintf // Doom-style printf void dprintf(const char *, ...) PRINTF_ATTR(1, 2); -void Z_ZoneHistory(char *); - -#ifdef INSTRUMENTED -extern int printstats; // killough 8/23/98 -void Z_PrintStats(void); // killough 8/23/98 -#endif - #endif //----------------------------------------------------------------------------