Пример #1
0
void *Z_Realloc(void *ptr, size_t n, int mallocTag)
{
    int     tag = ptr ? Z_GetTag(ptr) : mallocTag;
    void   *p;

    lockZone();

    n = ALIGNED(n);
    p = Z_Malloc(n, tag, 0);    // User always 0;

    if (ptr)
    {
        size_t bsize;

        // Has old data; copy it.
        memblock_t *block = Z_GetBlock(ptr);
#ifdef LIBDENG_FAKE_MEMORY_ZONE
        bsize = block->areaSize;
#else
        bsize = block->size - sizeof(memblock_t);
#endif
        memcpy(p, ptr, MIN_OF(n, bsize));
        Z_Free(ptr);
    }

    unlockZone();
    return p;
}
Пример #2
0
static int Z_GetAlign(const ZoneHeader* header)
{
	if (*header & (1 << 31))
	{
		unsigned char* ptr = (unsigned char*)header;
		memtag_t tag = Z_GetTag(header);

		// point to the first alignment block
		if (Z_IsTagTemp(tag))
		{
			ptr += sizeof(ZoneHeader) + Z_GetSize(header);
#ifdef _DEBUG
			ptr += sizeof(ZoneDebugHeader) + sizeof(ZoneDebugFooter);
#endif
		}
		else
		{
			if (Z_IsTagLinked(tag))
			{
				// skip the link header
				ptr -= sizeof(ZoneLinkHeader);
			}
			ptr -= 1;
		}

		return *ptr + 1;
	}
	return 0;
}
Пример #3
0
int Z_Size(void *pvAddress)
{
	assert(s_Initialized);

#ifdef _DEBUG
	ZoneDebugHeader* debug = (ZoneDebugHeader*)pvAddress - 1;

	if (*debug != ZONE_MAGIC)
	{
		Com_Error(ERR_FATAL, "Z_Size(): Not a valid zone header!");
		return 0;	// won't get here
	}

	pvAddress = (void*)debug;
#endif

	ZoneHeader* header = (ZoneHeader*)pvAddress - 1;

	if (Z_GetTag(header) == TAG_STATIC)
	{
		return 0;	// kind of
	}
	
	return Z_GetSize(header);
}
Пример #4
0
void Z_TagPointers(memtag_t eTag)
{
	assert(s_Initialized);

#ifndef _GAMECUBE
	WaitForSingleObject(s_Mutex, INFINITE);
#endif

	Sys_Log( "pointers.txt", va("Pointers for tag %d:\n", eTag) );

	for (ZoneLinkHeader* link = s_LinkBase; link;)
	{
		ZoneHeader* header = (ZoneHeader*)(link + 1);
		link = link->m_Next;

		if (eTag == TAG_ALL || Z_GetTag(header) == eTag)
		{
#ifdef _DEBUG
			Sys_Log( "pointers.txt",
					va("%x - %d\n", ((void*)((char*)header + 
							sizeof(ZoneHeader) + sizeof(ZoneDebugHeader))),
					Z_Size(((void*)((char*)header + 
							sizeof(ZoneHeader) + sizeof(ZoneDebugHeader))))));
#else
			Sys_Log( "pointers.txt",
					va("%x - %d\n", (void*)(header + 1),
					Z_Size((void*)(header + 1))));
#endif
		}
	}

#ifndef _GAMECUBE
	ReleaseMutex(s_Mutex);
#endif
}
Пример #5
0
void W_RemoveLumpsWithHandle(DFILE * handle)
{
	int     i, k, first, len;

	for(i = 0, first = -1; i < numlumps; i++)
	{
		if(first < 0 && lumpinfo[i].handle == handle)
		{
			// Start a region.
			first = i;
			continue;
		}
		// Does a region end?
		if(first >= 0)
			if(lumpinfo[i].handle != handle || i == numlumps - 1 ||
			   MarkerForGroup(lumpinfo[i].name, true) ||
			   MarkerForGroup(lumpinfo[i].name, false))
			{
				if(lumpinfo[i].handle == handle && i == numlumps - 1)
					i++;		// Also free the last one.
				// The length of the region.
				len = i - first;
				// Free the memory allocated for the region.
				for(k = first; k < i; k++)
				{
					//  Con_Message("removing lump: %s (%d)\n", lumpinfo[k].name, lumpinfo[k].handle);
					if(lumpcache[k])
					{

						// If the block has a user, it must be explicitly freed.
						/*if((unsigned int)Z_GetUser(lumpcache[k]) > 0x100)
						   Z_Free(lumpcache[k]);
						   else if(Z_GetTag(lumpcache[k]) < PU_LEVEL)
						   Z_ChangeTag(lumpcache[k], PU_LEVEL); */
						//Z_ChangeTag(lumpcache[k], PU_CACHE);
						//Z_ChangeUser(lumpcache[k], NULL);
						if(Z_GetTag(lumpcache[k]) < PU_LEVEL)
							Z_ChangeTag(lumpcache[k], PU_LEVEL);
						// Mark the memory pointer in use, but unowned.
						Z_ChangeUser(lumpcache[k], (void *) 0x2);
					}
				}
				// Move the data in the lump storage.
				W_MoveLumps(i, numlumps - i, -len);
				numlumps -= len;
				i -= len;
				// Make it possible to begin a new region.
				first = -1;
			}
	}
}
Пример #6
0
void Z_TagFree(memtag_t eTag)
{
	assert(s_Initialized);

	for (ZoneLinkHeader* link = s_LinkBase; link;)
	{
		ZoneHeader* header = (ZoneHeader*)(link + 1);
		link = link->m_Next;

		if (eTag == TAG_ALL || Z_GetTag(header) == eTag)
		{
#ifdef _DEBUG
			Z_Free((void*)((char*)header + sizeof(ZoneHeader) + 
				sizeof(ZoneDebugHeader)));
#else
			Z_Free((void*)(header + 1));
#endif
		}
	}
}
Пример #7
0
void *Z_Recalloc(void *ptr, size_t n, int callocTag)
{
    memblock_t     *block;
    void           *p;
    size_t          bsize;

    lockZone();

    n = ALIGNED(n);

    if (ptr)                     // Has old data.
    {
        p = Z_Malloc(n, Z_GetTag(ptr), NULL);
        block = Z_GetBlock(ptr);
#ifdef LIBDENG_FAKE_MEMORY_ZONE
        bsize = block->areaSize;
#else
        bsize = block->size - sizeof(memblock_t);
#endif
        if (bsize <= n)
        {
            memcpy(p, ptr, bsize);
            memset((char *) p + bsize, 0, n - bsize);
        }
        else
        {
            // New block is smaller.
            memcpy(p, ptr, n);
        }
        Z_Free(ptr);
    }
    else
    {   // Totally new allocation.
        p = Z_Calloc(n, callocTag, NULL);
    }

    unlockZone();

    return p;
}
Пример #8
0
qboolean Z_IsFromZone(void *pvAddress, memtag_t eTag)
{
	assert(s_Initialized);

#ifdef _DEBUG
	ZoneDebugHeader* debug = (ZoneDebugHeader*)pvAddress - 1;

	if (*debug != ZONE_MAGIC)
	{
		return qfalse;
	}

	pvAddress = (void*)debug;
#endif

	ZoneHeader* header = (ZoneHeader*)pvAddress - 1;

	if (Z_GetTag(header) != eTag)
	{
		return qfalse;
	}
	
	return Z_GetSize(header);
}
Пример #9
0
void Z_FindLeak(void)
{
	assert(s_Initialized);

	static int cycle_count = 0;
	const memtag_t tag = TAG_NEWDEL;

	struct PointerInfo
	{
		void* data;
		int counter;
		bool mark;
	};
	
	const int max_pointers = 32768;
	static PointerInfo pointers[max_pointers];
	static int num_pointers = 0;

	// Clear pointer existance
	for (int i = 0; i < num_pointers; ++i)
	{
		pointers[i].mark = false;
	}
	
	// Add all known pointers
	int start_num = num_pointers;
	for (ZoneLinkHeader* link = s_LinkBase; link;)
	{
		ZoneHeader* header = (ZoneHeader*)(link + 1);
		link = link->m_Next;
		
		if (Z_GetTag(header) == tag)
		{
			// See if the pointer already is in the array
			bool found = false;
			for (int k = start_num; k < num_pointers; ++k)
			{
				if (pointers[k].data == header)
				{
					++pointers[k].counter;
					pointers[k].mark = true;
					found = true;
					break;
				}
			}

			// If the pointer is not in the array, add it
			if (!found)
			{
				assert(num_pointers < max_pointers);
				pointers[num_pointers].data = header;
				pointers[num_pointers].counter = 0;
				pointers[num_pointers].mark = true;
				++num_pointers;
			}
		}
	}

	// Remove pointers that are no longer used
	for (int j = 0; j < num_pointers; ++j)
	{
		if (pointers[j].mark)
		{
			if (pointers[j].counter != cycle_count && 
				pointers[j].counter != cycle_count - 1 && 
				pointers[j].counter != 0)
			{
				Com_Printf("Memory leak: %p\n", pointers[j].data);
			}
		}
		else
		{
			int k;
			for (k = j; k < num_pointers; ++k)
			{
				if (pointers[k].mark) break;
			}

			if (k == num_pointers) break;

			memmove(pointers + j, pointers + k, (num_pointers - k) * sizeof(PointerInfo));
			num_pointers -= k - j;
		}
	}

	++cycle_count;
}
Пример #10
0
int Z_Free(void *pvAddress)
	#define Z_FREE_RETURN(x) return (x)
#endif
{
#ifdef _WINDOWS
	if (!s_Initialized) return;
#endif

	assert(s_Initialized);

#ifdef _DEBUG
	// check the header magic
	ZoneDebugHeader* debug_header = (ZoneDebugHeader*)pvAddress - 1;

	if (*debug_header != ZONE_MAGIC)
	{
		Com_Error(ERR_FATAL, "Z_Free(): Corrupt zone header!");
		Z_FREE_RETURN( 0 );
	}

	ZoneHeader* header = (ZoneHeader*)debug_header - 1;

	// check the footer magic
	ZoneDebugFooter* debug_footer = (ZoneDebugFooter*)((char*)pvAddress + 
		Z_GetSize(header));

	if (*debug_footer != ZONE_MAGIC)
	{
		Com_Error(ERR_FATAL, "Z_Free(): Corrupt zone footer!");
		Z_FREE_RETURN( 0 );
	}
#else
	ZoneHeader* header = (ZoneHeader*)pvAddress - 1;
#endif

	memtag_t tag = Z_GetTag(header);

	if (tag != TAG_STATIC)
	{
#ifndef _GAMECUBE
		WaitForSingleObject(s_Mutex, INFINITE);
#endif

		// Determine size of header and footer
		int header_size = sizeof(ZoneHeader);
		int align_size = Z_GetAlign(header);
		int footer_size = 0;
		int data_size = Z_GetSize(header);
		if (Z_IsTagLinked(tag))
		{
			header_size += sizeof(ZoneLinkHeader);
		}
		if (Z_IsTagTemp(tag))
		{
			footer_size += align_size;
		}
		else
		{
			header_size += align_size;
		}
#ifdef _DEBUG
		header_size += sizeof(ZoneDebugHeader);
		footer_size += sizeof(ZoneDebugFooter);
#endif
		int real_size = data_size + header_size + footer_size;
		
		// Update the stats
		s_Stats.m_SizeAlloc -= data_size;
		s_Stats.m_OverheadAlloc -= header_size + footer_size;
		s_Stats.m_SizesPerTag[tag] -= data_size;
		s_Stats.m_CountAlloc--;
		s_Stats.m_CountsPerTag[tag]--;
	
		// Delink block
		if (Z_IsTagLinked(tag))
		{
			ZoneLinkHeader* linked = (ZoneLinkHeader*)header - 1;
			
			if (linked == s_LinkBase)
			{
				s_LinkBase = linked->m_Next;
				if (s_LinkBase)
				{
					s_LinkBase->m_Prev = NULL;
				}
			}
			else
			{
				if (linked->m_Next)
				{
					linked->m_Next->m_Prev = linked->m_Prev;
				}
				linked->m_Prev->m_Next = linked->m_Next;
			}

			assert(Z_ValidateLinks());
		}

		// Clear the block header for safety
		*header = 0;

		// Add block to free list
		ZoneFreeBlock* nblock = NULL;
		if (real_size < sizeof(ZoneFreeBlock))
		{
			// Not enough space in block to put free information --
			// use overflow buffer.
			nblock = Z_GetOverflowBlock();

			if (nblock == NULL)
			{
				Z_Details_f();
				Com_Error(ERR_FATAL, "Zone free overflow buffer overflowed!");
			}
		}
		else
		{
			// Place free information in block
			nblock = (ZoneFreeBlock*)((char*)pvAddress - header_size);
		}

		nblock->m_Address = (unsigned int)pvAddress - header_size;
		nblock->m_Size = real_size;
		Z_LinkFreeBlock(nblock);

		// Coalesce any adjacent free blocks
		Z_Coalasce(nblock);
#ifndef _GAMECUBE
		ReleaseMutex(s_Mutex);
#endif
	}

	Z_FREE_RETURN( 0 );
}