289 lines
6.3 KiB
C++
289 lines
6.3 KiB
C++
#include <stdlib.h>
|
|
#include <string.h> /* memmove() */
|
|
#include <iostream>
|
|
|
|
#include <SST/SST_Concurrency.h>
|
|
|
|
#include <ZUtil/ZAlloc.hpp>
|
|
|
|
SST_Mutex AllocLock = SST_Concurrency_CreateMutex();
|
|
|
|
#if ZALLOC_CHECK_ALLOC
|
|
|
|
static ZAllocInfo* AllocList = NULL;
|
|
|
|
int ZAllocInfo::CurrentAllocCount = 0;
|
|
int ZAllocInfo::CurrentCheckpoint = 0;
|
|
|
|
void ZAllocAddTrack(uintptr_t _address, size_t _size, const char *_file, int _line, int _checkpoint)
|
|
{
|
|
ZAllocInfo *info = (ZAllocInfo*)malloc(sizeof(ZAllocInfo));
|
|
size_t len = strlen(_file);
|
|
|
|
info->Address = _address;
|
|
info->Size = _size;
|
|
|
|
if(len > sizeof(info->File)-1)
|
|
len = sizeof(info->File)-1;
|
|
|
|
memcpy(info->File, _file, len);
|
|
info->File[len] = '\0';
|
|
|
|
info->Line = _line;
|
|
info->Checkpoint = _checkpoint;
|
|
|
|
info->Next = NULL;
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_LockMutex(AllocLock);
|
|
|
|
info->Next = AllocList;
|
|
AllocList = info;
|
|
|
|
#if ZALLOC_EXTRA_SPAMMY
|
|
std::cerr << "Inc Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount+1) << std::endl;
|
|
#endif
|
|
|
|
ZAllocInfo::CurrentAllocCount++;
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_UnlockMutex(AllocLock);
|
|
}
|
|
|
|
void ZAllocRemoveTrack(uintptr_t _address)
|
|
{
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_LockMutex(AllocLock);
|
|
|
|
ZAllocInfo *prev = NULL;
|
|
ZAllocInfo *cur = AllocList;
|
|
|
|
while (cur != NULL)
|
|
{
|
|
if (cur->Address == _address)
|
|
{
|
|
if (prev == NULL) //i.e. removing head
|
|
AllocList = cur->Next;
|
|
else
|
|
prev->Next = cur->Next; //Remove "this" from the chain. link parent's next pointer to this one's next pointer so nobody has a reference to "this".
|
|
|
|
free(cur);
|
|
|
|
#if ZALLOC_EXTRA_SPAMMY
|
|
std::cerr << "Dec Alloc Count " << ZAllocInfo::CurrentAllocCount << " -> " << (ZAllocInfo::CurrentAllocCount-1) << std::endl;
|
|
#endif
|
|
|
|
ZAllocInfo::CurrentAllocCount--;
|
|
|
|
break;
|
|
}
|
|
|
|
prev = cur;
|
|
cur = cur->Next;
|
|
}
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_UnlockMutex(AllocLock);
|
|
}
|
|
|
|
void ZAllocDumpUnfreed(ZMemState *_state)
|
|
{
|
|
SST_Concurrency_LockMutex(AllocLock);
|
|
|
|
size_t totalSize = 0;
|
|
int checkpoint = _state == NULL ? 0 : _state->Checkpoint;
|
|
|
|
std::cerr << "--- ZAlloc Unfreed Memory Dump ---" << std::endl << std::endl;
|
|
std::cerr << ZAllocInfo::CurrentAllocCount << " Current Unfreed Allocations:" << std::endl;
|
|
|
|
ZAllocInfo *cur = AllocList;
|
|
|
|
while (cur != NULL)
|
|
{
|
|
if (cur->Checkpoint >= checkpoint)
|
|
{
|
|
std::cerr << cur->File << "\n\tLINE: " << cur->Line << "\n\tADDRESS " << (void*)cur->Address << " (" << cur->Size << " bytes) unfreed!" << std::endl;
|
|
totalSize += cur->Size;
|
|
}
|
|
|
|
cur = cur->Next;
|
|
}
|
|
|
|
std::cerr << "-----------------------------------------------------------\n";
|
|
std::cerr << "Total Unfreed: " << totalSize << " bytes" << std::endl << std::endl;
|
|
|
|
std::cerr << "--- End Unfreed Memory Dump ---" << std::endl;
|
|
|
|
SST_Concurrency_UnlockMutex(AllocLock);
|
|
}
|
|
|
|
//Debug Operator New
|
|
void * operator new(size_t _size, const char *_file, int _line, int _checkpoint)
|
|
throw()
|
|
{
|
|
void *ptr = (void*)malloc(_size);
|
|
|
|
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
void * operator new[](size_t _size, const char* _file, int _line, int _checkpoint)
|
|
throw()
|
|
{
|
|
void *ptr = (void*)malloc(_size);
|
|
|
|
ZAllocAddTrack((uintptr_t)ptr, _size, _file, _line, _checkpoint);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
//Debug Delete
|
|
void operator delete(void *_ptr, const char* _file, int _line, int _checkpoint)
|
|
{
|
|
(void)_file;
|
|
(void)_line;
|
|
(void)_checkpoint;
|
|
|
|
ZAllocRemoveTrack((uintptr_t)_ptr);
|
|
|
|
free(_ptr);
|
|
}
|
|
|
|
void operator delete[](void *_ptr, const char* _file, int _line, int _checkpoint)
|
|
{
|
|
(void)_file;
|
|
(void)_line;
|
|
(void)_checkpoint;
|
|
|
|
ZAllocRemoveTrack((uintptr_t)_ptr);
|
|
|
|
free(_ptr);
|
|
}
|
|
#ifndef __sun /* TODO: some error with Solaris Studio C++ compiler. */
|
|
void operator delete(void *_ptr)
|
|
{
|
|
ZAllocRemoveTrack((uintptr_t)_ptr);
|
|
|
|
free(_ptr);
|
|
}
|
|
|
|
void operator delete[](void *_ptr)
|
|
{
|
|
ZAllocRemoveTrack((uintptr_t)_ptr);
|
|
|
|
free(_ptr);
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
|
|
/////////////////////////////////////
|
|
/* Static New Functions and Fields */
|
|
/////////////////////////////////////
|
|
|
|
//This contains all our statically allocated pointers
|
|
void **StaticAllocArray = NULL;
|
|
|
|
//This is how many we can hold
|
|
int StaticAllocCapacity = 0;
|
|
|
|
//This is how many we've got
|
|
int StaticAllocSize = 0;
|
|
|
|
//This iterates and deletes
|
|
void ZAllocDeleteStatic(void)
|
|
{
|
|
int i;
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_LockMutex(AllocLock);
|
|
|
|
//Iterate, delete, then delete our static alloc array
|
|
for (i = 0; i < StaticAllocSize; i++)
|
|
free(StaticAllocArray[i]);
|
|
|
|
free(StaticAllocArray);
|
|
|
|
StaticAllocArray = NULL;
|
|
StaticAllocCapacity = 0;
|
|
StaticAllocSize = 0;
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_UnlockMutex(AllocLock);
|
|
}
|
|
|
|
void ZAllocAddStaticPtr(void *_ptr)
|
|
{
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_LockMutex(AllocLock);
|
|
|
|
//If we need to, register with atexit to call ZAllocDeleteStatic
|
|
if (StaticAllocArray == NULL)
|
|
atexit(ZAllocDeleteStatic);
|
|
|
|
//Check to see if StaticAllocArray is full
|
|
if (StaticAllocSize >= StaticAllocCapacity )
|
|
{
|
|
//Allocate new one
|
|
size_t newCapacity = StaticAllocCapacity == 0 ? 128 : StaticAllocCapacity * 2;
|
|
void *temp = malloc(newCapacity * sizeof(void*));
|
|
|
|
//Make sure we don't need to crash hard here
|
|
if (temp == NULL)
|
|
{
|
|
std::cerr << "ZAlloc failed to allocate static tracking array!" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
//Copy the old data in
|
|
memmove(temp, StaticAllocArray, StaticAllocSize * sizeof(void*));
|
|
|
|
//Free the old pointer
|
|
free(StaticAllocArray);
|
|
|
|
//Reset our pointer
|
|
StaticAllocArray = (void**)temp;
|
|
}
|
|
|
|
//Add new void*
|
|
StaticAllocArray[StaticAllocSize] = _ptr;
|
|
|
|
//Increment size
|
|
StaticAllocSize++;
|
|
|
|
//Mutex may be NULL if doing pre-main() init
|
|
if (AllocLock)
|
|
SST_Concurrency_UnlockMutex(AllocLock);
|
|
}
|
|
|
|
//Static operator new
|
|
void * operator new(size_t _size, znew_static_t _staticAlloc)
|
|
{
|
|
URFP(_staticAlloc);
|
|
|
|
void *ptr = (void*)malloc(_size);
|
|
|
|
ZAllocAddStaticPtr(ptr);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
void * operator new[](size_t _size, znew_static_t _staticAlloc)
|
|
{
|
|
URFP(_staticAlloc);
|
|
|
|
void *ptr = (void*)malloc(_size);
|
|
|
|
ZAllocAddStaticPtr(ptr);
|
|
|
|
return ptr;
|
|
}
|