コード例 #1
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_FreeTags
//
void (Z_FreeTags)(int lowtag, int hightag, const char *file, int line)
{
   memblock_t *block;

   // haleyjd 03/30/2011: delete ZoneObjects of the same tags as well
   ZoneObject::FreeTags(lowtag, hightag);
   
   if(lowtag <= PU_FREE)
      lowtag = PU_FREE+1;

   if(hightag > PU_CACHE)
      hightag = PU_CACHE;
   
   for(; lowtag <= hightag; ++lowtag)
   {
      for(block = blockbytag[lowtag], blockbytag[lowtag] = NULL; block;)
      {
         memblock_t *next = block->next;

         Z_IDCheck(IDBOOL(block->id != ZONEID),
                   "Z_FreeTags: Changed a tag without ZONEID", 
                   block, file, line);

         (Z_Free)((byte *)block + header_size, file, line);
         block = next;               // Advance to next block
      }
   }

   Z_LogPrintf("* Z_FreeTags(lowtag=%d, hightag=%d, file=%s:%d)\n",
               lowtag, hightag, file, line);
}
コード例 #2
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void (Z_CheckHeap)(const char *file, int line) {
    memblock_t *block;
    memblock_t *prev;
    int i;

    //
    // Check all chains
    //
    for(i = 0; i < PU_MAX; ++i) {
        prev = NULL;

        for(block = allocated_blocks[i]; block != NULL; block = block->next) {
            if(block->id != ZONEID) {
                I_Error("Z_CheckHeap: Block without a ZONEID! (%s:%d)", file, line);
            }

            if(block->prev != prev) {
                I_Error("Z_CheckHeap: Doubly-linked list corrupted! (%s:%d)", file, line);
            }

            prev = block;
        }
    }

#ifdef ZONEFILE
    Z_LogPrintf("* Z_CheckHeap(file=%s:%d)\n", file, line);
#endif
}
コード例 #3
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_FreeTags
//
void (Z_FreeTags)(int lowtag, int hightag, __string file, int line)
{
   register memblock_t __near *block = zone;

   if(lowtag <= PU_FREE)
      lowtag = (int)PU_FREE + 1;

   // 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)
      {
         register memblock_t __near *prev = block->prev, *cur = block;
         (Z_Free)((char __near *)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);

   Z_LogPrintf("* Z_FreeTags(lowtag=%d, hightag=%d, file=%s:%d)\n",
               lowtag, hightag, file, line);
}
コード例 #4
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_ChangeTag
//
void (Z_ChangeTag)(void *ptr, int tag, __string file, int line)
{
   register memblock_t __near *block = VoidToBlock(ptr);

   DEBUG_CHECKHEAP();

   Z_IDCheck(IDBOOL(block->id != ZONEID),
             "Z_ChangeTag: Changed a tag without ZONEID", block, file, line);

   Z_IDCheck(IDBOOL(tag >= PU_PURGELEVEL && !block->user),
             "Z_ChangeTag: an owner is required for purgable blocks",
             block, file, line);

#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
   block->tag = tag;

   Z_LogPrintf("* Z_ChangeTag(p=%p, tag=%d, file=%s:%d)\n", ptr, tag, file, line);
}
コード例 #5
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_Init
//
void (Z_Init)(__string file, int line)
{
   register size_t size;

   // Allocate the memory
   // davidph 06/17/12: For DS, memory is a static allocation.
   zonebase = (memblock_t __near *)heap;
   zonebase_size = HEAPSIZE;

   // Align on cache boundary
   // davidph 08/03/12 FIXME: This causes invalid codegen.
 //zone = (memblock_t *)(((uintptr_t)zonebase + (CACHE_ALIGN - 1)) & ~(CACHE_ALIGN - 1));
   zone = zonebase;

   size = zonebase_size - ((char __near *)zone - (char __near *)zonebase);

   rover = zone;                    // Rover points to base of zone mem
   zone->next = zone->prev = zone;  // Single node
   zone->size = size - HEADER_SIZE; // All memory in one block
   zone->tag = PU_FREE;             // A free block

#ifdef ZONEIDCHECK
   zone->id  = 0;
#endif

   INSTRUMENT(free_memory = zone->size);
   INSTRUMENT(inactive_memory = zonebase_size - zone->size);
   INSTRUMENT(active_memory = purgable_memory = 0);

   Z_OpenLogFile();
   Z_LogPrintf("Initialized zone heap with size of %u bytes (zonebase = %p)\n",
               zonebase_size, (void *)zonebase);
}
コード例 #6
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_CheckHeap
//
void (Z_CheckHeap)(__string file, int line)
{
   register memblock_t __near *block = zone;   // Start at base of zone mem

   do                          // Consistency check (last node treated special)
   {
      if((block->next != zone &&
          (memblock_t __near *)((char __near *)block + HEADER_SIZE + block->size) != block->next) ||
         block->next->prev != block || block->prev->next != block)
      {
         zonef("Z_CheckHeap: Block size does not touch the next block\nSource: %s:%d\n"
#ifdef INSTRUMENTED
               "Source of offending block: %s:%d\n"
               , file, line, block->file, block->line
#else
               , file, line
#endif
               );
         abort();
      }
   }
   while((block = block->next) != zone);

#ifndef CHECKHEAP
   Z_LogPrintf("* Z_CheckHeap(file=%s:%d)\n", file, line);
#endif
}
コード例 #7
0
ファイル: zone.c プロジェクト: svkaiser/TurokEX
char *(Z_Strdup)(const char *s, int tag, void *user, const char *file, int line)
{
#ifdef ZONEFILE
    Z_LogPrintf("* Z_Strdup(file=%s:%d)\n", file, line);
#endif
	return strcpy((Z_Malloc)(strlen(s)+1, tag, user, file, line), s);
}
コード例 #8
0
ファイル: zone.c プロジェクト: svkaiser/TurokEX
void *(Z_Calloc)(int n1, int tag, void *user, const char *file, int line)
{
#ifdef ZONEFILE
    Z_LogPrintf("* Z_Calloc(file=%s:%d)\n", file, line);
#endif
	return memset((Z_Malloc)(n1, tag, user, file, line), 0, n1);
}
コード例 #9
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void (Z_ChangeTag)(void *ptr, int tag, const char *file, int line) {
    memblock_t*    block;

    block = (memblock_t*)((byte *)ptr - sizeof(memblock_t));

    if(block->id != ZONEID)
        I_Error("Z_ChangeTag: block without a ZONEID! (%s:%d)",
                file, line);

    if(tag >= PU_PURGELEVEL && block->user == NULL) {
        I_Error("Z_ChangeTag: an owner is required for purgable blocks (%s:%d)", file, line);
    }

    //
    // Remove the block from its current list, and rehook it into
    // its new list.
    //
    Z_RemoveBlock(block);
    block->tag = tag;
    Z_InsertBlock(block);

#ifdef ZONEFILE
    Z_LogPrintf("* Z_ChangeTag(ptr=%p, tag=%d, file=%s:%d)\n",
                ptr, tag, file, line);
#endif
}
コード例 #10
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_Malloc
//
// You can pass a NULL user if the tag is < PU_PURGELEVEL.
//
void *(Z_Malloc)(size_t size, int tag, void **user, const char *file, int line)
{
   memblock_t *block;
   byte *ret;

   DEBUG_CHECKHEAP();

   Z_IDCheckNB(IDBOOL(tag >= PU_PURGELEVEL && !user),
               "Z_Malloc: an owner is required for purgable blocks", 
               file, line);

   if(!size)
      return user ? *user = NULL : NULL;          // malloc(0) returns NULL
   
   if(!(block = (memblock_t *)(malloc(size + header_size))))
   {
      if(blockbytag[PU_CACHE])
      {
         Z_FreeTags(PU_CACHE, PU_CACHE);
         block = (memblock_t *)(malloc(size + header_size));
      }
   }

   if(!block)
   {
      I_FatalError(I_ERR_KILL, "Z_Malloc: Failure trying to allocate %u bytes\n"
                               "Source: %s:%d\n", (unsigned int)size, file, line);
   }
   
   block->size = size;
   
   if((block->next = blockbytag[tag]))
      block->next->prev = &block->next;
   blockbytag[tag] = block;
   block->prev = &blockbytag[tag];
           
   INSTRUMENT(memorybytag[tag] += block->size);
   INSTRUMENT(block->file = file);
   INSTRUMENT(block->line = line);
         
   IDCHECK(block->id = ZONEID); // signature required in block header
   
   block->tag  = tag;           // tag
   block->user = user;          // user
   
   ret = ((byte *) block + header_size);
   if(user)                     // if there is a user
      *user = ret;              // set user to point to new block
   
   // scramble memory -- weed out any bugs
   SCRAMBLER(ret, size);

   Z_LogPrintf("* %p = Z_Malloc(size=%lu, tag=%d, user=%p, source=%s:%d)\n", 
               ret, size, tag, user, file, line);

   return ret;
}
コード例 #11
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void Z_Init(void) {
    dmemset(allocated_blocks, 0, sizeof(allocated_blocks));

#ifdef ZONEFILE
    atexit(Z_CloseLogFile); // exit handler
    Z_OpenLogFile();

    Z_LogPrintf("* Z_Init\n");
#endif
}
コード例 #12
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void (Z_Touch)(void *ptr, const char *file, int line) {
    memblock_t *block;

    block = (memblock_t*)((byte*)ptr - sizeof(memblock_t));

    if(block->id != ZONEID) {
        I_Error("Z_Touch: touched a pointer without ZONEID (%s:%d)", file, line);
    }

#ifdef ZONEFILE
    Z_LogPrintf("* Z_Touch(ptr=%p, file=%s:%d)\n", ptr, file, line);
#endif
}
コード例 #13
0
ファイル: z_zone.c プロジェクト: MP2E/kexplus
void *(Z_Malloc) (int size, int tag, void *user, const char *file, int line) {
	memblock_t *newblock;
	unsigned char *data;
	void *result;

	if (tag < 0 || tag >= PU_MAX)
		I_Error("Z_Malloc: tag out of range: %i (%s:%d)", tag, file,
			line);

	if (user == NULL && tag >= PU_PURGELEVEL)
		I_Error
		    ("Z_Malloc: an owner is required for purgable blocks (%s:%d)",
		     file, line);

	// Malloc a block of the required size

	newblock = NULL;

	if (!(newblock = (memblock_t *) malloc(sizeof(memblock_t) + size))) {
		if (Z_ClearCache(sizeof(memblock_t) + size))
			newblock =
			    (memblock_t *) malloc(sizeof(memblock_t) + size);
	}

	if (!newblock)
		I_Error("Z_Malloc: failed on allocation of %u bytes (%s:%d)",
			size, file, line);

	// Hook into the linked list for this tag type

	newblock->tag = tag;
	newblock->id = ZONEID;
	newblock->user = user;
	newblock->size = size;

	Z_InsertBlock(newblock);

	data = (unsigned char *)newblock;
	result = data + sizeof(memblock_t);

	if (user != NULL)
		*newblock->user = result;

#ifdef ZONEFILE
	Z_LogPrintf
	    ("* %p = Z_Malloc(size=%lu, tag=%d, user=%p, source=%s:%d)\n",
	     result, size, tag, user, file, line);
#endif

	return result;
}
コード例 #14
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_Free
//
void (Z_Free)(void *p, const char *file, int line)
{
   DEBUG_CHECKHEAP();

   if(p)
   {
      memblock_t *block = (memblock_t *)((byte *) p - header_size);

      Z_IDCheck(IDBOOL(block->id != ZONEID),
                "Z_Free: freed a pointer without ZONEID", block, file, line);

      // haleyjd: permanent blocks are never freed even if the code tries.
      if(block->tag == PU_PERMANENT)
         return;
      
      IDCHECK(block->id = 0); // Nullify id so another free fails

      // haleyjd 01/20/09: check invalid tags
      // catches double frees and possible selective heap corruption
      if(block->tag == PU_FREE || block->tag >= PU_MAX)
      {
         I_FatalError(I_ERR_KILL,
                      "Z_Free: freed a pointer with invalid tag %d\n"
                      "Source: %s:%d\n"
#if defined(ZONEVERBOSE) && defined(INSTRUMENTED)
                      "Source of malloc: %s:%d\n"
                      , block->tag, file, line, block->file, block->line
#else
                      , block->tag, file, line
#endif
                     );
      }
      INSTRUMENT(memorybytag[block->tag] -= block->size);
      block->tag = PU_FREE;       // Mark block freed

      // scramble memory -- weed out any bugs
      SCRAMBLER(p, block->size);

      if(block->user)            // Nullify user if one exists
         *block->user = NULL;

      if((*block->prev = block->next))
         block->next->prev = block->prev;
         
      free(block);
         
      Z_LogPrintf("* Z_Free(p=%p, file=%s:%d)\n", p, file, line);
   }
}
コード例 #15
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_Alloca
//
// haleyjd 12/06/06:
// Implements a portable garbage-collected alloca on the zone heap.
//
void *(Z_Alloca)(size_t n, const char *file, int line)
{
   void *ptr;

   if(n == 0)
      return NULL;

   // allocate it
   ptr = (Z_Calloc)(n, 1, PU_AUTO, NULL, file, line);

   Z_LogPrintf("* %p = Z_Alloca(n = %lu, file = %s, line = %d)\n", 
               ptr, n, file, line);

   return ptr;
}
コード例 #16
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_Realloc
//
// haleyjd 05/29/08: *Something* is wrong with my Z_Realloc routine, and I
// cannot figure out what! So we're back to using Old Faithful for now.
//
// davidph 12/09/12: You fool, you threw away gold! Gold, I say!
//
void *(Z_Realloc)(void *ptr, size_t n, int tag, void **user, __string file, int line)
{
   register void *p = (Z_Malloc)(n, tag, user, file, line);

   if(ptr)
   {
      memblock_t *block = VoidToBlock(ptr);
      if(p) // haleyjd 09/18/06: allow to return NULL without crashing
         memcpy_near((void __near *p, (void __near *)ptr, n <= block->size ? n : block->size);
      (Z_Free)(ptr, file, line);
      if(user) // in case Z_Free nullified same user
         *user=p;
   }

   Z_LogPrintf("* %p = Z_Realloc(ptr=%p, n=%u, tag=%d, user=%p, source=%s:%d)\n",
               p, ptr, n, tag, user, file, line);

   return p;
}
コード例 #17
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_ChangeTag
//
void (Z_ChangeTag)(void *ptr, int tag, const char *file, int line)
{
   memblock_t *block;
   
   DEBUG_CHECKHEAP();
   
   if(!ptr)
   {
      I_FatalError(I_ERR_KILL, 
                   "Z_ChangeTag: can't change a NULL pointer at %s:%d\n",
                   file, line);
   }
   
   block = (memblock_t *)((byte *) ptr - header_size);

   Z_IDCheck(IDBOOL(block->id != ZONEID),
             "Z_ChangeTag: Changed a tag without ZONEID", block, file, line);

   // haleyjd: permanent blocks are not re-tagged even if the code tries.
   if(block->tag == PU_PERMANENT)
      return;

   Z_IDCheck(IDBOOL(tag >= PU_PURGELEVEL && !block->user),
             "Z_ChangeTag: an owner is required for purgable blocks",
             block, file, line);

   if((*block->prev = block->next))
      block->next->prev = block->prev;
   if((block->next = blockbytag[tag]))
      block->next->prev = &block->next;
   block->prev = &blockbytag[tag];
   blockbytag[tag] = block;

   INSTRUMENT(memorybytag[block->tag] -= block->size);
   INSTRUMENT(memorybytag[tag] += block->size);

   block->tag = tag;

   Z_LogPrintf("* Z_ChangeTag(p=%p, tag=%d, file=%s:%d)\n",
               ptr, tag, file, line);
}
コード例 #18
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_CheckHeap
//
void (Z_CheckHeap)(const char *file, int line)
{
#ifdef ZONEIDCHECK
   memblock_t *block;
   int lowtag;

   for(lowtag = PU_FREE+1; lowtag < PU_MAX; ++lowtag)
   {
      for(block = blockbytag[lowtag]; block; block = block->next)
      {
         Z_IDCheck(IDBOOL(block->id != ZONEID),
                   "Z_CheckHeap: Block found without ZONEID", 
                   block, file, line);
      }
   }
#endif

#ifndef CHECKHEAP
   Z_LogPrintf("* Z_CheckHeap(file=%s:%d)\n", file, line);
#endif
}
コード例 #19
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_Alloca
//
// haleyjd 12/06/06:
// Implements a portable garbage-collected alloca on the zone heap.
//
void *(Z_Alloca)(size_t n, __string file, int line)
{
   register alloca_header_t __near *hdr;
   register void *ptr;

   if(n == 0)
      return NULL;

   // add an alloca_header_t to the requested allocation size
   ptr = (Z_Malloc)(n + sizeof(alloca_header_t), PU_STATIC, NULL, file, line);

   Z_LogPrintf("* %p = Z_Alloca(n = %u, file = %s, line = %d)\n", ptr, n, file, line);

   // add to linked list
   hdr = (alloca_header_t __near *)ptr;
   hdr->next = alloca_root;
   alloca_root = hdr;

   // return a pointer to the actual allocation
   return (void *)((char __near *)ptr + sizeof(alloca_header_t));
}
コード例 #20
0
ファイル: z_zone.c プロジェクト: MP2E/kexplus
void (Z_Free) (void *ptr, const char *file, int line) {
	memblock_t *block;

	block = (memblock_t *) ((byte *) ptr - sizeof(memblock_t));

	if (block->id != ZONEID)
		I_Error("Z_Free: freed a pointer without ZONEID (%s:%d)", file,
			line);

	// clear the user's mark
	if (block->user != NULL)
		*block->user = NULL;

	Z_RemoveBlock(block);

	// Free back to system
	free(block);

#ifdef ZONEFILE
	Z_LogPrintf("* Z_Free(ptr=%p, file=%s:%d)\n", ptr, file, line);
#endif
}
コード例 #21
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void (Z_FreeTags)(int lowtag, int hightag, const char *file, int line) {
    int i;

    for(i = lowtag; i <= hightag; ++i) {
        memblock_t *block;
        memblock_t *next;

        // Free all in this chain

        for(block = allocated_blocks[i]; block != NULL;) {
            next = block->next;

            if(block->id != ZONEID) {
                I_Error("Z_FreeTags: Changed a tag without ZONEID (%s:%d)", file, line);
            }

            // Free this block

            if(block->user != NULL) {
                *block->user = NULL;
            }

            free(block);

            // Jump to the next in the chain

            block = next;
        }

        // This chain is empty now
        allocated_blocks[i] = NULL;
    }

#ifdef ZONEFILE
    Z_LogPrintf("* Z_FreeTags(lowtag=%d, hightag=%d, file=%s:%d)\n",
                lowtag, hightag, file, line);
#endif
}
コード例 #22
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_Realloca
//
// haleyjd 07/08/10: realloc for automatic allocations.
//
void *(Z_Realloca)(void *ptr, size_t n, const char *file, int line)
{
   void *ret;

   if(ptr)
   {
      // get zone block
      memblock_t *block = (memblock_t *)((byte *)ptr - header_size);

      Z_IDCheck(IDBOOL(block->id != ZONEID),
         "Z_Realloca: block found without ZONEID", block, file, line);

      if(block->tag != PU_AUTO)
         I_FatalError(I_ERR_KILL, "Z_Realloca: strange block tag %d\n", block->tag);
   }
   
   ret = (Z_Realloc)(ptr, n, PU_AUTO, NULL, file, line);

   Z_LogPrintf("* %p = Z_Realloca(ptr = %p, n = %lu, file = %s, line = %d)\n", 
               ret, ptr, n, file, line);

   return ret;
}
コード例 #23
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
char *(Z_Strdupa)(const char *s, const char *file, int line) {
#ifdef ZONEFILE
    Z_LogPrintf("* Z_Strdupa(file=%s:%d)\n", file, line);
#endif
    return dstrcpy((Z_Alloca)(strlen(s)+1, file, line), s);
}
コード例 #24
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_Realloc
//
// haleyjd 09/18/06: Rewritten to be an actual realloc routine. The
// various cases are as follows:
//
// 1. If the block is NULL, is in virtual memory, or we're trying to set it to
//    zero-byte size, we use Z_ReallocOld above.
// 2. If the block is smaller than the new size, we need to expand it. If the
//    next block on the zone heap is free, check to see if it together with the
//    current block is large enough. If so, merge the blocks. Now test to make
//    sure the internal fragmentation does not exceed the split limit. If it
//    does, resplit the blocks at the new boundary. If the next block wasn't
//    free, we have to call Z_ReallocOld to move the entire block elsewhere.
// 3. If the block is larger than the new size, we can shrink it, but we only
//    need to shrink it if the wasted space is larger than the split limit.
//    If so, the block is split at its new boundary. If the next block on the
//    zone heap is free, it is then necessary to merge the new free block with
//    the next block on the heap. In the event the block is not shrunk, only the
//    INSTRUMENTED data needs to be updated to reflect the new internal fragmen-
//    tation.
// 4. If the block is already the same size as "n", we don't need to do anything
//    aside from adjusting the INSTRUMENTED block data for debugging purposes.
//
void *(Z_Realloc)(void *ptr, size_t n, int tag, void **user, __string file, int line)
{
   register memblock_t __near *block, *other;
   register size_t curr_size = 0;

   // davidph 12/09/12: Handle null and size 0 right here instead of in Z_ReallocOld.
   if(n == 0) { (Z_Free)(ptr, file, line); return NULL; }

   if(!ptr)
      return (Z_Malloc)(n, tag, user, file, line);

   // get current size of block
   block = VoidToBlock(ptr);

   Z_IDCheck(IDBOOL(block->id != ZONEID),
             "Z_Realloc: Reallocated a block without ZONEID\n",
             block, file, line);

   other = block->next; // save pointer to next block
   curr_size = block->size;

   // round new size to CHUNK_SIZE
   n = (n + CHUNK_SIZE - 1) & ~(CHUNK_SIZE - 1);

   if(n > curr_size) // is new allocation size larger than current?
   {
      register size_t extra;

      // haleyjd 10/03/06: free adjacent purgable blocks
      while(other != zone && other != block &&
            (other->tag == PU_FREE || other->tag >= PU_PURGELEVEL))
      {
         if(other->tag >= PU_PURGELEVEL)
         {
            (Z_Free)(BlockToVoid(other), file, line);

            // reset pointer to next block
            other = block->next;
         }

         // use current size of block; note it may have increased if it was
         // merged with an adjacent free block

         // if we've freed enough, stop
         if(curr_size + other->size + HEADER_SIZE >= n)
            break;

         // move to next block
         other = other->next;
      }

      // reset pointer
      other = block->next;

      // check to see if it can fit if we merge with the next block
      if(other != zone && other->tag == PU_FREE &&
         curr_size + other->size + HEADER_SIZE >= n)
      {
         // merge the blocks
         if(rover == other)
            rover = block;
         (block->next = other->next)->prev = block;
         block->size += other->size + HEADER_SIZE;

#ifdef INSTRUMENTED
         // lost a block...
         inactive_memory -= HEADER_SIZE;
         // lost a free block...
         free_memory -= other->size;
         // increased active or purgable
         if(block->tag >= PU_PURGELEVEL)
            purgable_memory += other->size + HEADER_SIZE;
         else
            active_memory += other->size + HEADER_SIZE;
#endif

         // check to see if there's enough extra to warrant splitting off
         // a new free block
         extra = block->size - n;

         if(extra >= MIN_BLOCK_SPLIT + HEADER_SIZE)
         {
            register memblock_t __near *newb =
               (memblock_t __near *)((char __near *)block + HEADER_SIZE + n);

            (newb->next = block->next)->prev = newb;
            (newb->prev = block)->next = newb;
            block->size = n;
            newb->size = extra - HEADER_SIZE;
            newb->tag = PU_FREE;

            if(rover == block)
               rover = newb;

#ifdef INSTRUMENTED
            // added a block...
            inactive_memory += HEADER_SIZE;
            // added a free block...
            free_memory += newb->size;
            // decreased active or purgable
            if(block->tag >= PU_PURGELEVEL)
               purgable_memory -= newb->size + HEADER_SIZE;
            else
               active_memory -= newb->size + HEADER_SIZE;
#endif
         }

         // subtract old internal fragmentation and add new
         INSTRUMENT(inactive_memory -= block->extra);
         INSTRUMENT(inactive_memory += (block->extra = block->size - n));
      }
      else // else, do old realloc (make new, copy old, free old)
      {
         // davidph 12/10/12: This was the only place Z_ReallocOld was called.
         //   And we know that ptr != NULL and n != 0 and n > curr_size.

         register void *p = (Z_Malloc)(n, tag, user, file, line);

         memcpy_near((void __near *)p, (void __near *)ptr, curr_size);
         (Z_Free)(ptr, file, line);
         if(user) // in case Z_Free nullified same user
            *user = p;

         return p;
      }
   }
   else if(n < curr_size) // is new allocation size smaller than current?
   {
      // check to see if there's enough extra to warrant splitting off
      // a new free block
      size_t extra = curr_size - n;

      if(extra >= MIN_BLOCK_SPLIT + HEADER_SIZE)
      {
         register memblock_t __near *newb =
            (memblock_t __near *)((char __near *)block + HEADER_SIZE + n);

         (newb->next = block->next)->prev = newb;
         (newb->prev = block)->next = newb;
         block->size = n;
         newb->size = extra - HEADER_SIZE;
         newb->tag = PU_FREE;

#ifdef INSTRUMENTED
         // added a block...
         inactive_memory += HEADER_SIZE;
         // added a free block...
         free_memory += newb->size;
         // decreased purgable or active
         if(block->tag >= PU_PURGELEVEL)
            purgable_memory -= newb->size + HEADER_SIZE;
         else
            active_memory -= newb->size + HEADER_SIZE;
#endif

         // may need to merge new block with next block
         if(other && other->tag == PU_FREE && other != zone)
         {
            if(rover == other) // Move back rover if it points at next block
               rover = newb;
            (newb->next = other->next)->prev = newb;
            newb->size += other->size + HEADER_SIZE;

            // deleted a block...
            INSTRUMENT(inactive_memory -= HEADER_SIZE);
            // space between blocks is now free
            INSTRUMENT(free_memory += HEADER_SIZE);
         }
      }
      // else, leave block the same size

      // subtract old internal fragmentation and add new
      INSTRUMENT(inactive_memory -= block->extra);
      INSTRUMENT(inactive_memory += (block->extra = block->size - n));
   }
   // else new allocation size is same as current, don't change it

   // modify the block
   INSTRUMENT(block->file = file);
   INSTRUMENT(block->line = line);

   // reset ptr for consistency
   ptr = BlockToVoid(block);

   if(block->user != user)
   {
      if(block->user)           // nullify old user if any
         *(block->user) = NULL;
      block->user = user;       // set block's new user
      if(user)                  // if non-null, set user to allocation
         *user = ptr;
   }

   // let Z_ChangeTag handle changing the tag
   if(block->tag != tag)
      (Z_ChangeTag)(ptr, tag, file, line);

   Z_PrintStats();           // print memory allocation stats
   Z_LogPrintf("* Z_Realloc(ptr=%p, n=%u, tag=%d, user=%p, source=%s:%d)\n",
               ptr, n, tag, user, file, line);

   return ptr;
}
コード例 #25
0
ファイル: z_zone.c プロジェクト: DavidPH/DH-acc
//
// Z_Free
//
void (Z_Free)(void *p, __string file, int line)
{
   register memblock_t __near *other, *block;

   if(!p) return;

   DEBUG_CHECKHEAP();

   block = VoidToBlock(p);

   Z_IDCheck(IDBOOL(block->id != ZONEID),
             "Z_Free: freed a pointer without ZONEID", block, file, line);

   IDCHECK(block->id = 0); // Nullify id so another free fails

   // haleyjd 01/20/09: check invalid tags
   // catches double frees and possible selective heap corruption
   if(block->tag == PU_FREE || block->tag >= PU_MAX)
   {
      zonef("Z_Free: freed a pointer with invalid tag %d\nSource: %s:%d\n"
#ifdef INSTRUMENTED
            "Source of malloc: %s:%d\n"
            , block->tag, file, line, block->file, block->line
#else
            , block->tag, file, line
#endif
            );
      abort();
   }

   SCRAMBLER(p, block->size);

   if(block->user)            // Nullify user if one exists
      *block->user = NULL;

#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;

         INSTRUMENT(inactive_memory -= HEADER_SIZE);
         INSTRUMENT(free_memory += HEADER_SIZE);
      }
   }

   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;

      INSTRUMENT(inactive_memory -= HEADER_SIZE);
      INSTRUMENT(free_memory += HEADER_SIZE);
   }

   Z_PrintStats(); // print memory allocation stats
   Z_LogPrintf("* Z_Free(p=%p, file=%s:%d)\n", p, file, line);
}
コード例 #26
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
//
// Z_Realloc
//
// For the native heap, this can easily behave as a real realloc, and not
// just an ignorant copy-and-free.
//
void *(Z_Realloc)(void *ptr, size_t n, int tag, void **user,
                  const char *file, int line)
{
   void *p;
   memblock_t *block, *newblock, *origblock;

   // if not allocated at all, defer to Z_Malloc
   if(!ptr)
      return (Z_Malloc)(n, tag, user, file, line);

   // size == 0 is a special case that cannot be handled below
   if(n == 0)
   {
      (Z_Free)(ptr, file, line);
      return NULL;
   }

   DEBUG_CHECKHEAP();

   block = origblock = (memblock_t *)((byte *)ptr - header_size);

   Z_IDCheck(IDBOOL(block->id != ZONEID),
             "Z_Realloc: Reallocated a block without ZONEID\n", 
             block, file, line);

   // haleyjd: realloc cannot change the tag of a permanent block
   if(block->tag == PU_PERMANENT)
      tag = PU_PERMANENT;

   // nullify current user, if any
   if(block->user)
      *(block->user) = NULL;

   // detach from list before reallocation
   if((*block->prev = block->next))
      block->next->prev = block->prev;

   block->next = NULL;
   block->prev = NULL;

   INSTRUMENT(memorybytag[block->tag] -= block->size);

   if(!(newblock = (memblock_t *)(realloc(block, n + header_size))))
   {
      // haleyjd 07/09/10: Note that unlinking the block above makes this safe 
      // even if the current block is PU_CACHE; Z_FreeTags won't find it.
      if(blockbytag[PU_CACHE])
      {
         Z_FreeTags(PU_CACHE, PU_CACHE);
         newblock = (memblock_t *)(realloc(block, n + header_size));
      }
   }

   if(!(block = newblock))
   {
      if(origblock->size >= n)
      {
         block = origblock; // restore original block if size was equal or smaller
         n = block->size;   // keep same size in this event
      }
      else
      {
         I_FatalError(I_ERR_KILL, "Z_Realloc: Failure trying to allocate %u bytes\n"
                                  "Source: %s:%d\n", (unsigned int)n, file, line);
      }
   }

   block->size = n;
   block->tag  = tag;

   p = (byte *)block + header_size;

   // set new user, if any
   block->user = user;
   if(user)
      *user = p;

   // reattach to list at possibly new address, new tag
   if((block->next = blockbytag[tag]))
      block->next->prev = &block->next;
   blockbytag[tag] = block;
   block->prev = &blockbytag[tag];

   INSTRUMENT(memorybytag[tag] += block->size);
   INSTRUMENT(block->file = file);
   INSTRUMENT(block->line = line);

   Z_LogPrintf("* %p = Z_Realloc(ptr=%p, n=%lu, tag=%d, user=%p, source=%s:%d)\n", 
               p, ptr, n, tag, user, file, line);

   return p;
}
コード例 #27
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void *(Z_Realloc)(void *ptr, int size, int tag, void *user, const char *file, int line) {
    memblock_t *block;
    memblock_t *newblock;
    unsigned char *data;
    void *result;

    if(!ptr) {
        return (Z_Malloc)(size, tag, user, file, line);
    }

    if(size == 0) {
        (Z_Free)(ptr, file, line);
        return NULL;
    }

    if(tag < 0 || tag >= PU_MAX) {
        I_Error("Z_Realloc: tag out of range: %i (%s:%d)", tag, file, line);
    }

    if(user == NULL && tag >= PU_PURGELEVEL) {
        I_Error("Z_Realloc: an owner is required for purgable blocks (%s:%d)", file, line);
    }

    block = (memblock_t*)((byte *)ptr - sizeof(memblock_t));

    newblock = NULL;

    if(block->id != ZONEID) {
        I_Error("Z_Realloc: Reallocated a pointer without ZONEID (%s:%d)", file, line);
    }

    Z_RemoveBlock(block);

    block->next = NULL;
    block->prev = NULL;

    if(block->user) {
        *block->user = NULL;
    }

    if(!(newblock = (memblock_t*)realloc(block, sizeof(memblock_t) + size))) {
        if(Z_ClearCache(sizeof(memblock_t) + size)) {
            newblock = (memblock_t*)realloc(block, sizeof(memblock_t) + size);
        }
    }

    if(!newblock) {
        I_Error("Z_Realloc: failed on allocation of %u bytes (%s:%d)", size, file, line);
    }

    newblock->tag = tag;
    newblock->id = ZONEID;
    newblock->user = user;
    newblock->size = size;

    Z_InsertBlock(newblock);

    data = (unsigned char*)newblock;
    result = data + sizeof(memblock_t);

    if(user != NULL) {
        *newblock->user = result;
    }

#ifdef ZONEFILE
    Z_LogPrintf("* %p = Z_Realloc(ptr=%p, n=%lu, tag=%d, user=%p, source=%s:%d)\n",
                result, ptr, size, tag, user, file, line);
#endif

    return result;
}
コード例 #28
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void (Z_FreeAlloca)(const char *file, int line) {
#ifdef ZONEFILE
    Z_LogPrintf("* Z_FreeAlloca(file=%s:%d)\n", file, line);
#endif
    (Z_FreeTags)(PU_AUTO, PU_AUTO, file, line);
}
コード例 #29
0
ファイル: z_zone.c プロジェクト: gabrielbaez/Doom64EX
void *(Z_Alloca)(int n, const char *file, int line) {
#ifdef ZONEFILE
    Z_LogPrintf("* Z_Alloca(file=%s:%d)\n", file, line);
#endif
    return n == 0 ? NULL : (Z_Calloc)(n, PU_AUTO, NULL, file, line);
}
コード例 #30
0
ファイル: z_native.cpp プロジェクト: Altazimuth/eternity
void Z_Init(void)
{   
   atexit(Z_Close);            // exit handler

   Z_LogPrintf("Initialized zone heap (using native implementation)\n");
}