282 lines
6.3 KiB
C++
282 lines
6.3 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include "alloc/ialloc.h"
|
|
#include "thread/mutex.h"
|
|
#include "log/log.h"
|
|
|
|
using namespace GS::Alloc;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void *DefaultAllocator::Alloc(size_t size, System sys)
|
|
{ __NSTAT_WRAPALLOC(malloc(size), sys) }
|
|
void DefaultAllocator::Delete(void *addr, System sys)
|
|
{ __NSTAT_WRAPDELETE(free(addr), sys) }
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
#if __ENABLE_ALLOCATION_STAT__
|
|
|
|
namespace GS {
|
|
namespace Alloc {
|
|
|
|
Stat system_stat[SystemCount];
|
|
SystemDesc system_desc[SystemCount] =
|
|
{
|
|
{ "General", "System" },
|
|
|
|
{ "Container", "List Item" },
|
|
{ "String", "String Buffer" },
|
|
|
|
{ "I/O", "Filesystem" },
|
|
{ "I/O", "Metatag" },
|
|
|
|
{ "Animation", "Curve" },
|
|
{ "Animation", "Motion" },
|
|
{ "Animation", "Animation Source" },
|
|
|
|
{ "Maths", "Vector" },
|
|
{ "Maths", "Matrix" },
|
|
|
|
{ "Physics", "Physics" },
|
|
|
|
{ "Scene 3D", "Item" },
|
|
|
|
{ "Resource", "Geometry" },
|
|
{ "Resource", "Material" },
|
|
{ "Resource", "Texture" },
|
|
{ "Resource", "Picture" },
|
|
|
|
{ "Mixer", "System" },
|
|
{ "Resource", "Sound" },
|
|
|
|
{ "Renderer", "System" },
|
|
{ "Renderer", "Render Job" },
|
|
{ "Renderer", "Terrain" },
|
|
|
|
{ "Renderer", "VBO" },
|
|
|
|
{ "Global", "Other" }
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
size_t GetAdjustedAllocationSize(size_t size)
|
|
{ return size + sizeof(Header); }
|
|
void *SetupAllocationStat(void *addr, size_t size)
|
|
{
|
|
Header *h = (Header *)addr;
|
|
h->size = size;
|
|
return (void *)(h + 1);
|
|
}
|
|
void *GetAllocationStat(void *addr, Header *&h)
|
|
{
|
|
h = ((Header *)addr) - 1;
|
|
return (void *)h;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
static Mutex stat_mutex;
|
|
|
|
//------------------------------------------------------------------------------
|
|
void UpdateStatAlloc(size_t size, System system)
|
|
{
|
|
MutexLock lock(&stat_mutex);
|
|
|
|
++system_stat[system].alloc_count;
|
|
++system_stat[system].alive_count;
|
|
if (system_stat[system].alive_count > system_stat[system].alive_count_peak)
|
|
system_stat[system].alive_count_peak = system_stat[system].alive_count;
|
|
system_stat[system].size += size;
|
|
if (system_stat[system].size > system_stat[system].size_peak)
|
|
system_stat[system].size_peak = system_stat[system].size;
|
|
}
|
|
void UpdateStatDelete(size_t size, System system)
|
|
{
|
|
MutexLock lock(&stat_mutex);
|
|
|
|
system_stat[system].alive_count--;
|
|
system_stat[system].size -= size;
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
} // Alloc
|
|
} // GS
|
|
|
|
|
|
#endif // __ENABLE_ALLOCATION_STAT__
|
|
|
|
|
|
#include "container/narray.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
class SmallBlockAllocatorPool
|
|
{
|
|
void *root;
|
|
char *pool, *pool_end;
|
|
|
|
public:
|
|
|
|
bool Owns(void *p) const
|
|
{ return (p >= (void *)pool) && (p < (void *)pool_end); }
|
|
|
|
void *Alloc()
|
|
{
|
|
if (!root)
|
|
return NULL;
|
|
|
|
void *p = root;
|
|
root = *((void **)root);
|
|
return p;
|
|
}
|
|
void Free(void *p)
|
|
{
|
|
*((void **)p) = root;
|
|
root = p;
|
|
}
|
|
|
|
bool Init(size_t block_size, uint block_count)
|
|
{
|
|
Uninit();
|
|
|
|
pool = (char *)malloc(block_size * block_count);
|
|
if (pool == NULL)
|
|
return false;
|
|
pool_end = pool + block_size * block_count;
|
|
|
|
for (uint n = 0; n < (block_count - 1); ++n)
|
|
*((void **)(pool + n * block_size)) = (void *)(pool + (n + 1) * block_size);
|
|
*((void **)(pool + (block_count - 1) * block_size)) = NULL;
|
|
|
|
root = (void *)pool;
|
|
return true;
|
|
}
|
|
void Uninit()
|
|
{
|
|
free(pool);
|
|
root = NULL;
|
|
}
|
|
|
|
SmallBlockAllocatorPool()
|
|
{
|
|
pool = pool_end = NULL;
|
|
root = NULL;
|
|
}
|
|
~SmallBlockAllocatorPool()
|
|
{
|
|
Uninit();
|
|
}
|
|
};
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
class MixedBlockAllocator
|
|
{
|
|
SmallBlockAllocatorPool allocator[4];
|
|
|
|
public:
|
|
|
|
void *operator new (size_t size)
|
|
{ return malloc(size); }
|
|
void operator delete(void *addr)
|
|
{ free(addr); }
|
|
|
|
void *Alloc(size_t size)
|
|
{
|
|
void *p = NULL;
|
|
|
|
if (size <= 8)
|
|
p = allocator[0].Alloc();
|
|
else if (size <= 16)
|
|
p = allocator[1].Alloc();
|
|
else if (size <= 32)
|
|
p = allocator[2].Alloc();
|
|
else if (size <= 64)
|
|
p = allocator[3].Alloc();
|
|
|
|
return p ? p : malloc(size);
|
|
}
|
|
void Free(void *p)
|
|
{
|
|
if (allocator[0].Owns(p))
|
|
allocator[0].Free(p);
|
|
else if (allocator[1].Owns(p))
|
|
allocator[1].Free(p);
|
|
else if (allocator[2].Owns(p))
|
|
allocator[2].Free(p);
|
|
else if (allocator[3].Owns(p))
|
|
allocator[3].Free(p);
|
|
else
|
|
free(p);
|
|
}
|
|
|
|
bool Init()
|
|
{
|
|
allocator[0].Init(8, 16000); // 128k
|
|
allocator[1].Init(16, 16000); // 256k
|
|
allocator[2].Init(32, 8000); // 256k
|
|
allocator[3].Init(64, 8000); // 512k
|
|
|
|
return true;
|
|
}
|
|
};
|
|
//------------------------------------------------------------------------------
|
|
|
|
#if __ENABLE_GLOBAL_SBA__
|
|
|
|
MixedBlockAllocator *mixed_allocator = NULL;
|
|
|
|
MixedBlockAllocator *GetMixedAllocator()
|
|
{
|
|
if (!mixed_allocator)
|
|
{
|
|
mixed_allocator = new MixedBlockAllocator;
|
|
mixed_allocator->Init();
|
|
}
|
|
return mixed_allocator;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
void *operator new(size_t size)
|
|
{
|
|
__NSTAT_WRAPALLOC(GetMixedAllocator()->Alloc(size), Alloc::Global)
|
|
}
|
|
void operator delete(void *addr)
|
|
{
|
|
__NSTAT_WRAPDELETE(GetMixedAllocator()->Free(addr), Alloc::Global)
|
|
}
|
|
void *operator new [] (size_t size)
|
|
{
|
|
__NSTAT_WRAPALLOC(GetMixedAllocator()->Alloc(size), Alloc::Global)
|
|
}
|
|
void operator delete [] (void *addr)
|
|
{
|
|
__NSTAT_WRAPDELETE(GetMixedAllocator()->Free(addr), Alloc::Global)
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
void *_align_alloc(size_t size, size_t align)
|
|
{
|
|
#ifdef _WIN32
|
|
return _aligned_malloc(size, align);
|
|
#else
|
|
return malloc(size);
|
|
#endif
|
|
}
|
|
void _align_free(void *p)
|
|
{
|
|
#ifdef _WIN32
|
|
_aligned_free(p);
|
|
#else
|
|
free(p);
|
|
#endif
|
|
}
|
|
//------------------------------------------------------------------------------
|