X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=zone.h;h=af6ddfd586ed67476ad6af1eb8b1f29937af4ee4;hp=7655ad9c083284c12a9c6ced62b076625d5600eb;hb=97cb39635544fc0a29036daacb31f6778f312f0d;hpb=8dcce44300385b12c46d494c06aadcfa35a8bc14 diff --git a/zone.h b/zone.h index 7655ad9c..af6ddfd5 100644 --- a/zone.h +++ b/zone.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -17,115 +17,137 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* - memory allocation - - -H_??? The hunk manages the entire memory block given to quake. It must be -contiguous. Memory can be allocated from either the low or high end in a -stack fashion. The only way memory is released is by resetting one of the -pointers. - -Hunk allocations should be given a name, so the Hunk_Print () function -can display usage. - -Hunk allocations are guaranteed to be 16 byte aligned. - -The video buffers are allocated high to avoid leaving a hole underneath -server allocations when changing to a higher video mode. - - -Z_??? Zone memory functions used for small, dynamic allocations like text -strings from command input. There is only about 48K for it, allocated at -the very bottom of the hunk. - -Cache_??? Cache memory is for objects that can be dynamically loaded and -can usefully stay persistant between levels. The size of the cache -fluctuates from level to level. - -To allocate a cachable object - - -Temp_??? Temp memory is used for file loading and surface caching. The size -of the cache memory is adjusted so that there is a minimum of 512k remaining -for temp memory. - - ------- Top of Memory ------- - -high hunk allocations - -<--- high hunk reset point held by vid - -video buffer - -z buffer - -surface cache - -<--- high hunk used - -cachable memory - -<--- low hunk used - -client and server low hunk allocations - -<-- low hunk reset point held by host - -startup hunk allocations -Zone block - ------ Bottom of Memory ----- - - - -*/ - -void Memory_Init (void *buf, int size); - -void Z_Free (void *ptr); -void *Z_Malloc (int size); // returns 0 filled memory -void *Z_TagMalloc (int size, int tag); - -void Z_DumpHeap (void); -void Z_CheckHeap (void); -int Z_FreeMemory (void); - -void *Hunk_Alloc (int size); // returns 0 filled memory -void *Hunk_AllocName (int size, char *name); - -void *Hunk_HighAllocName (int size, char *name); - -int Hunk_LowMark (void); -void Hunk_FreeToLowMark (int mark); - -int Hunk_HighMark (void); -void Hunk_FreeToHighMark (int mark); - -void *Hunk_TempAlloc (int size); - -void Hunk_Check (void); - -typedef struct cache_user_s +#ifndef ZONE_H +#define ZONE_H + +// LordHavoc: this is pointless with a good C library +//#define MEMCLUMPING + +#define POOLNAMESIZE 128 +// if set this pool will be printed in memlist reports +#define POOLFLAG_TEMP 1 +#if MEMCLUMPING +// give malloc padding so we can't waste most of a page at the end +#define MEMCLUMPSIZE (65536 - 1536) +// smallest unit we care about is this many bytes +#define MEMUNIT 8 +#define MEMBITS (MEMCLUMPSIZE / MEMUNIT) +#define MEMBITINTS (MEMBITS / 32) +#define MEMCLUMP_SENTINEL 0xABADCAFE +#endif + +#define MEMHEADER_SENTINEL1 0xDEADF00D +#define MEMHEADER_SENTINEL2 0xDF + +typedef struct memheader_s { - void *data; -} cache_user_t; - -void Cache_Flush (void); - -void *Cache_Check (cache_user_t *c); -// returns the cached data, and moves to the head of the LRU list -// if present, otherwise returns NULL - -void Cache_Free (cache_user_t *c); - -void *Cache_Alloc (cache_user_t *c, int size, char *name); -// Returns NULL if all purgable data was tossed and there still -// wasn't enough room. - -void Cache_Report (void); - - + // next and previous memheaders in chain belonging to pool + struct memheader_s *next; + struct memheader_s *prev; + // pool this memheader belongs to + struct mempool_s *pool; +#if MEMCLUMPING + // clump this memheader lives in, NULL if not in a clump + struct memclump_s *clump; +#endif + // size of the memory after the header (excluding header and sentinel2) + size_t size; + // file name and line where Mem_Alloc was called + const char *filename; + int fileline; + // should always be MEMHEADER_SENTINEL1 + unsigned int sentinel1; + // immediately followed by data, which is followed by a MEMHEADER_SENTINEL2 byte +} +memheader_t; + +#if MEMCLUMPING +typedef struct memclump_s +{ + // contents of the clump + qbyte block[MEMCLUMPSIZE]; + // should always be MEMCLUMP_SENTINEL + unsigned int sentinel1; + // if a bit is on, it means that the MEMUNIT bytes it represents are + // allocated, otherwise free + int bits[MEMBITINTS]; + // should always be MEMCLUMP_SENTINEL + unsigned int sentinel2; + // if this drops to 0, the clump is freed + size_t blocksinuse; + // largest block of memory available (this is reset to an optimistic + // number when anything is freed, and updated when alloc fails the clump) + size_t largestavailable; + // next clump in the chain + struct memclump_s *chain; +} +memclump_t; +#endif + +typedef struct mempool_s +{ + // should always be MEMHEADER_SENTINEL1 + unsigned int sentinel1; + // chain of individual memory allocations + struct memheader_s *chain; +#if MEMCLUMPING + // chain of clumps (if any) + struct memclump_s *clumpchain; +#endif + // POOLFLAG_* + int flags; + // total memory allocated in this pool (inside memheaders) + size_t totalsize; + // total memory allocated in this pool (actual malloc total) + size_t realsize; + // updated each time the pool is displayed by memlist, shows change from previous time (unless pool was freed) + size_t lastchecksize; + // name of the pool + char name[POOLNAMESIZE]; + // linked into global mempool list + struct mempool_s *next; + // parent object (used for nested memory pools) + struct mempool_s *parent; + // file name and line where Mem_AllocPool was called + const char *filename; + int fileline; + // should always be MEMHEADER_SENTINEL1 + unsigned int sentinel2; +} +mempool_t; + +#define Mem_Alloc(pool,size) _Mem_Alloc(pool, size, __FILE__, __LINE__) +#define Mem_Free(mem) _Mem_Free(mem, __FILE__, __LINE__) +#define Mem_CheckSentinels(data) _Mem_CheckSentinels(data, __FILE__, __LINE__) +#define Mem_CheckSentinelsGlobal() _Mem_CheckSentinelsGlobal(__FILE__, __LINE__) +#define Mem_AllocPool(name, flags, parent) _Mem_AllocPool(name, flags, parent, __FILE__, __LINE__) +#define Mem_FreePool(pool) _Mem_FreePool(pool, __FILE__, __LINE__) +#define Mem_EmptyPool(pool) _Mem_EmptyPool(pool, __FILE__, __LINE__) + +void *_Mem_Alloc(mempool_t *pool, size_t size, const char *filename, int fileline); +void _Mem_Free(void *data, const char *filename, int fileline); +mempool_t *_Mem_AllocPool(const char *name, int flags, mempool_t *parent, const char *filename, int fileline); +void _Mem_FreePool(mempool_t **pool, const char *filename, int fileline); +void _Mem_EmptyPool(mempool_t *pool, const char *filename, int fileline); +void _Mem_CheckSentinels(void *data, const char *filename, int fileline); +void _Mem_CheckSentinelsGlobal(const char *filename, int fileline); +// if pool is NULL this searches ALL pools for the allocation +qboolean Mem_IsAllocated(mempool_t *pool, void *data); + +// used for temporary allocations +mempool_t *tempmempool; + +void Memory_Init (void); +void Memory_Shutdown (void); +void Memory_Init_Commands (void); + +extern mempool_t *zonemempool; +#define Z_Malloc(size) Mem_Alloc(zonemempool,size) +#define Z_Free(data) Mem_Free(data) + +extern struct cvar_s developer_memory; +extern struct cvar_s developer_memorydebug; + +#endif