/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include #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 } //------------------------------------------------------------------------------