6#include "gsPlatformUtil.h"
18 typedef gsi_u64 gsi_uint;
19 #define PTR_ALIGNMENT 32
24 typedef gsi_u32 gsi_uint;
25 #define PTR_ALIGNMENT 16
30 typedef gsi_u32 gsi_uint;
31 #define PTR_ALIGNMENT 16
41#define MEM_PROFILE (1)
42#if defined(MEM_PROFILE)
43 #define IF_MEM_PROFILE_ISON(a) a
45 #define IF_MEM_PROFILE_ISON(a)
53 #pragma warning ( disable: 4127 )
58 #define MEM_MANAGER_CALL _cdecl
60 #define MEM_MANAGER_CALL
69 void* (MEM_MANAGER_CALL *malloc )(
size_t size);
70 void (MEM_MANAGER_CALL *free )(
void* ptr);
71 void* (MEM_MANAGER_CALL *realloc )(
void* ptr,
size_t size);
72 void* (MEM_MANAGER_CALL *memalign)(
size_t boundary,
size_t size);
75static void* MEM_MANAGER_CALL _gsi_malloc(
size_t size)
80static void MEM_MANAGER_CALL _gsi_free(
void* ptr)
85static void* MEM_MANAGER_CALL _gsi_realloc(
void* ptr,
size_t size)
87 return realloc(ptr, size);
90#if defined(_PS2) || defined(_PSP) || defined(_PS3)
91 static void* _gsi_memalign(
size_t boundary,
size_t size)
93 return memalign(boundary, size);
98 extern void* __cdecl _aligned_malloc(
size_t size,
int boundary);
100 static void* __cdecl _gsi_memalign(
size_t boundary,
size_t size)
102 return _aligned_malloc(size, (
int)boundary);
106 static void* _gsi_memalign(
size_t boundary,
size_t size)
108 void *ptr = calloc((size)/(boundary), (boundary));
110 GS_ASSERT((((gsi_u32)ptr)% boundary)==0);
117#ifdef MEM_MANAGER_DIRECT
121 #if defined(_PS2) || defined(_PSP) || defined(_PS3)
135void gsiMemoryCallbacksSet(gsMallocCB p_malloc, gsFreeCB p_free, gsReallocCB p_realloc, gsMemalignCB p_memalign)
138 memmanagercallbacks.malloc = p_malloc;
139 memmanagercallbacks.free = p_free;
140 memmanagercallbacks.realloc = p_realloc;
141 memmanagercallbacks.memalign = p_memalign;
150void* gsimalloc (
size_t size)
152 return (*memmanagercallbacks.malloc)(size);
154void* gsirealloc (
void* ptr,
size_t size)
156 return (*memmanagercallbacks.realloc)(ptr,size);
158void gsifree (
void* ptr)
162 (*memmanagercallbacks.free)(ptr);
164void* gsimemalign (
size_t boundary,
size_t size)
166 return (*memmanagercallbacks.memalign)(boundary,size);
171#ifdef GSI_MEM_MANAGED
186#define MEM_CONTEXT_STACK_MAX 10
187static gsMemMgrContext MemTypeStack [MEM_CONTEXT_STACK_MAX] = {gsMemMgrContext_Default};
188static gsi_u32 MemTypeStackIndex = 0;
189extern gsMemMgrContext gsMemMgrContextCurrent;
192#define MEM_TAG_STACK_MAX 10
193static gsi_u8 MemTagStack [MEM_TAG_STACK_MAX] = {0};
194static gsi_u32 MemTagStackIndex = 0;
207#define MEM_IS_POWER_OF_2(x) (((x) & ((x)-1)) == 0)
208#define MEMALIGN_POWEROF2(x,a) (((gsi_uint)(x)+(a-1)) &~ ( ((gsi_uint)(a)) -1))
211 #define MP_ASSERT(x) GS_ASSERT(x)
217#define MEM_TYPES_MAX 127
225 gsi_u32 MemUsed_At_HighWater;
229 gsi_u32 ChunksFreeCount;
230 gsi_u32 ChunksFreeLargestAvail;
232 gsi_u32 ChunksUsedCount;
233 gsi_u32 ChunksUsedCount_At_HighWater;
236 gsi_u32 MemType_ChunksCount [MEM_TYPES_MAX];
237 gsi_u32 MemType_MemUsed [MEM_TYPES_MAX];
238 gsi_u32 MemType_MemUsed_At_HighWater [MEM_TYPES_MAX];
243void MEM_STATSAddAll (MEM_STATS *_this,
const MEM_STATS *ms);
244void MEM_STATSClear (MEM_STATS *_this);
246void MEM_STATSClearAll (MEM_STATS *_this);
250typedef struct tMEM_CHUNK
280 struct tMEM_CHUNK *prev;
281 struct tMEM_CHUNK *next;
283 struct tMEM_CHUNK *NextFree;
290void MEM_CHUNKAlloc (MEM_CHUNK *_this, gsi_u8 _MemType,
size_t _UsedSize)
292 _UsedSize = MEMALIGN_POWEROF2(_UsedSize,4);
293 GS_ASSERT_STR(_UsedSize < 0x3FFFFFC,
"Alloc Memory size is too big.");
294 _this->MEM_UsageStat.MemUsed = _UsedSize<<6;
295 _this->MEM_UsageStat.MEM_TypeStruct.MemType = _MemType;
297void MEM_CHUNKFree (MEM_CHUNK *_this)
299 _this->MEM_UsageStat.MemUsed = 0;
304gsi_bool MEM_CHUNKIsFree (MEM_CHUNK *_this)
306 return (_this->MEM_UsageStat.MemUsed == 0);
310gsi_u32 MEM_CHUNKTotalSizeGet(MEM_CHUNK *_this)
315 return PTR_ALIGNMENT +
sizeof(MEM_CHUNK);
317 return (gsi_uint) _this->next - (gsi_uint) _this;
321gsi_u32 MEM_CHUNKChunkSizeGet(MEM_CHUNK *_this)
325 return PTR_ALIGNMENT;;
326 return (gsi_uint) _this->next - (gsi_uint) _this -
sizeof(MEM_CHUNK);
329gsi_u32 MEM_CHUNKMemUsedGet (MEM_CHUNK *_this)
331 return (_this->MEM_UsageStat.MemUsed & ~0xFF)>>6;
334void MEM_CHUNKMemUsedSet (MEM_CHUNK *_this, gsi_u32 size)
336 _this->MEM_UsageStat.MemUsed = (MEMALIGN_POWEROF2(size,4)<<6) + _this->MEM_UsageStat.MEM_TypeStruct.MemType;
339gsi_u32 MEM_CHUNKMemAvailGet(MEM_CHUNK *_this)
341 return MEM_CHUNKChunkSizeGet(_this) - MEM_CHUNKMemUsedGet(_this);
344char MEM_CHUNKMemTypeGet (MEM_CHUNK *_this)
346 return _this->MEM_UsageStat.MEM_TypeStruct.MemType;
349void MEM_CHUNKMemTypeSet (MEM_CHUNK *_this,
char _MemType)
351 GS_ASSERT(_MemType < MEM_TYPES_MAX);
352 _this->MEM_UsageStat.MEM_TypeStruct.MemType = _MemType;
355void* MEM_CHUNKMemPtrGet (MEM_CHUNK *_this)
357 return (
void*)((gsi_uint) _this +
sizeof(MEM_CHUNK));
360MEM_CHUNK *Ptr_To_MEM_CHUNK(
void *ptr)
362 return ((MEM_CHUNK *)ptr)-1;
367typedef struct MEM_CHUNK_POOL
372 MEM_CHUNK *HeaderStart;
373 MEM_CHUNK *HeaderEnd;
374 MEM_CHUNK *pFirstFree;
383MEM_CHUNK *MEM_CHUNK_POOLFindPreviousFreeChunk (MEM_CHUNK_POOL *_this, MEM_CHUNK *header);
384MEM_CHUNK *MEM_CHUNK_POOLFindNextFreeChunk (MEM_CHUNK_POOL *_this, MEM_CHUNK *header);
385void MEM_CHUNK_POOLSplitChunk (MEM_CHUNK_POOL *_this, MEM_CHUNK *header,gsi_bool ReAlloc);
386void MEM_CHUNK_POOLFreeChunk (MEM_CHUNK_POOL *_this, MEM_CHUNK *header);
387MEM_CHUNK *MEM_CHUNK_POOLAllocChunk (MEM_CHUNK_POOL *_this,
size_t Size,
int Alignment , gsi_bool Backwards );
390void MEM_CHUNK_POOLChunkMove (MEM_CHUNK_POOL *_this, MEM_CHUNK *oldpos, MEM_CHUNK *newpos);
394void MEM_CHUNK_POOLCreate (MEM_CHUNK_POOL *_this,
const char *szName,
char *ptr, gsi_u32 _size);
395void MEM_CHUNK_POOLDestroy (MEM_CHUNK_POOL *_this) ;
396gsi_bool MEM_CHUNK_POOLIsValid (MEM_CHUNK_POOL *_this)
398 return _this->HeapSize > 0;
403void *MEM_CHUNK_POOLmalloc (MEM_CHUNK_POOL *_this,
size_t Size, gsi_i32 Alignment );
405void *MEM_CHUNK_POOLmalloc_backwards (MEM_CHUNK_POOL *_this,
size_t Size, gsi_i32 Alignment );
406void *MEM_CHUNK_POOLrealloc (MEM_CHUNK_POOL *_this,
void *oldmem,
size_t newSize);
407void MEM_CHUNK_POOLfree (MEM_CHUNK_POOL *_this,
void *mem);
410void MEM_CHUNK_POOLCheckValidity (MEM_CHUNK_POOL *_this );
411void MEM_CHUNK_POOLMemStatsGet (MEM_CHUNK_POOL *_this, MEM_STATS *stats);
412gsi_u32 MEM_CHUNK_POOLWalkForType (MEM_CHUNK_POOL *_this,
int _MemType, gsi_bool _LogUse);
415gsi_bool MEM_CHUNK_POOLIsHeapPtr (MEM_CHUNK_POOL *_this,
void * mem);
419void MEM_CHUNK_POOLFillMemoryTable (MEM_CHUNK_POOL *_this,
char *Table,
const int TableSize, gsi_u32 _HeapStart, gsi_u32 _HeapSize);
423gsi_bool MEM_CHUNK_POOLItemIsInPoolMemory (MEM_CHUNK_POOL *_this,
void *ptr)
425 GS_ASSERT(MEM_CHUNK_POOLIsValid(_this));
426 return (((gsi_uint)ptr >= (gsi_uint)MEM_CHUNKMemPtrGet(_this->HeaderStart)) &&((gsi_uint)ptr <= (gsi_uint)MEM_CHUNKMemPtrGet(_this->HeaderEnd)));
438void MEM_STATSAddAll(MEM_STATS *_this,
const MEM_STATS *ms)
441 _this->MemTotal += ms->MemTotal ;
442 _this->MemAvail += ms->MemAvail ;
443 _this->MemUsed += ms->MemUsed ;
444 _this->MemUsed_At_HighWater += ms->MemUsed_At_HighWater ;
445 _this->MemWasted += ms->MemWasted ;
446 _this->ChunksCount += ms->ChunksCount ;
447 _this->ChunksFreeCount += ms->ChunksFreeCount ;
448 _this->ChunksFreeLargestAvail += ms->ChunksFreeLargestAvail ;
449 _this->ChunksUsedCount += ms->ChunksUsedCount ;
450 _this->ChunksUsedCount_At_HighWater += ms->ChunksUsedCount_At_HighWater;
451 for (i =0; i<MEM_TYPES_MAX;i++)
453 _this->MemType_ChunksCount[i] +=ms->MemType_ChunksCount[i];
454 _this->MemType_MemUsed[i] +=ms->MemType_MemUsed[i] ;
459void MEM_STATSClear(MEM_STATS *_this )
465 _this->MemWasted = 0;
466 _this->ChunksCount = 0;
467 _this->ChunksFreeCount = 0;
468 _this->ChunksFreeLargestAvail = 0;
469 _this->ChunksUsedCount = 0;
471 memset(_this->MemType_ChunksCount, 0,4 * MEM_TYPES_MAX);
472 memset(_this->MemType_MemUsed, 0,4 * MEM_TYPES_MAX);
476void MEM_STATSClearAll(MEM_STATS *_this )
479 MEM_STATSClear(_this);
480 _this->MemUsed_At_HighWater = 0;
481 for (i=0;i< MEM_TYPES_MAX;i++ )
482 _this->MemType_MemUsed_At_HighWater[i] = 0;
483 _this->ChunksUsedCount_At_HighWater = 0;
489void MEM_CHUNK_POOLChunkMove (MEM_CHUNK_POOL *_this, MEM_CHUNK *oldpos, MEM_CHUNK *newpos)
492 MEM_CHUNK *firstfree;
494 MEM_CHUNK temp = *oldpos;
497 MP_ASSERT(oldpos->prev)
498 MP_ASSERT(oldpos->next)
501 MP_ASSERT((gsi_uint) newpos <= (gsi_uint)oldpos->next - MEM_CHUNKMemUsedGet(oldpos) - sizeof(MEM_CHUNK))
502 MP_ASSERT((gsi_uint) newpos >= (gsi_uint)oldpos->prev + MEM_CHUNKMemUsedGet(oldpos->prev) + sizeof(MEM_CHUNK))
505 MP_ASSERT((((gsi_uint) newpos) % sizeof(MEM_CHUNK)) == 0)
510 newpos->prev->next = newpos;
511 newpos->next->prev = newpos;
514 if (MEM_CHUNKIsFree(newpos))
517 if (_this->pFirstFree == oldpos)
518 _this->pFirstFree = newpos;
521 firstfree = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,newpos->prev);
522 if (firstfree != newpos)
523 firstfree->NextFree = newpos;
527 _this->pFirstFree = newpos;
530 MP_ASSERT((newpos->NextFree==NULL) || ((gsi_uint)newpos->NextFree > (gsi_uint)newpos))
537void MEM_CHUNK_POOLDestroy(MEM_CHUNK_POOL *_this)
539 memset(_this, 0,
sizeof (MEM_CHUNK_POOL));
542void MEM_CHUNK_POOLCreate(MEM_CHUNK_POOL *_this,
const char * szNameIn,
char *ptr, gsi_u32 size)
546 MEM_CHUNK *HeaderMid;
547 MP_ASSERT(((gsi_uint)ptr & 15 )==0)
550 len = strlen(szNameIn)+1;
551 if (len > 20) len = 20;
552 memcpy(_this->Name,szNameIn, len);
553 _this->Name[19]=
'\0';
556 MP_ASSERT(size > 48 + 3 * sizeof(MEM_CHUNK))
558 _this->HeaderStart = (MEM_CHUNK *) (ptr);
559 HeaderMid = (MEM_CHUNK *) (ptr + 2 * sizeof(MEM_CHUNK));
560 _this->HeaderEnd = (MEM_CHUNK *) (ptr + size - 2 * sizeof(MEM_CHUNK));
563 _this->HeaderStart->prev = NULL;
564 _this->HeaderStart->next = HeaderMid;
565 _this->HeaderStart->NextFree = HeaderMid;
566 MEM_CHUNKAlloc (_this->HeaderStart,0,sizeof(MEM_CHUNK));
569 HeaderMid->prev = _this->HeaderStart;
570 HeaderMid->next = _this->HeaderEnd;
571 HeaderMid->NextFree = 0;
572 MEM_CHUNKFree(HeaderMid);
575 _this->HeaderEnd->prev = HeaderMid;
576 _this->HeaderEnd->next = NULL;
577 _this->HeaderEnd->NextFree = NULL;
578 MEM_CHUNKAlloc (_this->HeaderEnd,0,sizeof(MEM_CHUNK));
580 _this->HeapSize = size;
581 _this->pFirstFree = HeaderMid;
587MEM_CHUNK *MEM_CHUNK_POOLFindPreviousFreeChunk(MEM_CHUNK_POOL *_this, MEM_CHUNK *header)
592 while ((header) && (!MEM_CHUNKIsFree(header)))
595 header = header->prev;
603MEM_CHUNK *MEM_CHUNK_POOLFindNextFreeChunk(MEM_CHUNK_POOL *_this, MEM_CHUNK *header_in)
607 MEM_CHUNK *header = header_in;
608 while ((header) && (!MEM_CHUNKIsFree(header)))
610 header = header->next;
612 if (header == header_in)
623void MEM_CHUNK_POOLSplitChunk(MEM_CHUNK_POOL *_this, MEM_CHUNK *header, gsi_bool ReAlloc)
629 MEM_CHUNK *NewHeader;
632 NewHeader = (MEM_CHUNK *) ((gsi_u8*)header + MEM_CHUNKMemUsedGet(header) +
sizeof(MEM_CHUNK));
633 NewHeader = (MEM_CHUNK *)MEMALIGN_POWEROF2(NewHeader,
sizeof(MEM_CHUNK));
636 MP_ASSERT ((gsi_uint)NewHeader + 2 *
sizeof(MEM_CHUNK) <= (gsi_uint)header->next)
644 _this->MemUsed -= MEM_CHUNKChunkSizeGet(header);
646 GS_ASSERT(_this->MemUsed >= 0);
654 NewHeader->prev = header;
655 NewHeader->next = header->next;
656 MEM_CHUNKFree(NewHeader);
660 NewHeader->next->prev = NewHeader;
663 header->next = NewHeader;
668 if (MEM_CHUNKIsFree(NewHeader->next))
673 next = NewHeader->next->next;
674 next->prev = NewHeader;
676 NewHeader->NextFree = NewHeader->next->NextFree;
677 NewHeader->next = next;
684 NewHeader->NextFree = MEM_CHUNK_POOLFindNextFreeChunk(_this,NewHeader->next);
687 NewHeader->NextFree = header->NextFree;
690 if (_this->pFirstFree == header)
693 _this->pFirstFree = NewHeader;
698 PrevFree = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,header);
700 PrevFree->NextFree = NewHeader;
703 _this->pFirstFree = NewHeader;
709 _this->MemUsed += MEM_CHUNKMemUsedGet(header);
711 if(_this->MemUsed > _this->HWMemUsed)
712 _this->HWMemUsed = _this->MemUsed;
714 GS_ASSERT(_this->MemUsed <= _this->HeapSize);
719 header->NextFree = NULL;
726gsi_bool MEM_CHUNK_POOLIsHeapPtr(MEM_CHUNK_POOL *_this,
void * mem)
729 MEM_CHUNK *headertofind = Ptr_To_MEM_CHUNK(mem);
730 MEM_CHUNK *header = _this->HeaderStart;
734 header = header->next;
735 if (headertofind == header)
750MEM_CHUNK *MEM_CHUNK_POOLAllocChunk(MEM_CHUNK_POOL *_this,
size_t Size, gsi_i32 Alignment, gsi_bool Backwards)
761 MEM_CHUNK *PrevFree ;
764 MEM_CHUNK *alignedheader;
768 gsi_u32 SizeNeeded = Size +
sizeof(MEM_CHUNK);
769 SizeNeeded = MEMALIGN_POWEROF2(SizeNeeded,
sizeof(MEM_CHUNK));
772 MP_ASSERT(MEM_IS_POWER_OF_2(Alignment))
773 MP_ASSERT(Alignment >= PTR_ALIGNMENT)
779 header = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,_this->HeaderEnd);
781 header = _this->pFirstFree;
788 MP_ASSERT (MEM_CHUNKIsFree(header))
791 total_size = MEM_CHUNKTotalSizeGet(header);
792 MemRemain = total_size - SizeNeeded;
798 Ptr = (gsi_uint)MEM_CHUNKMemPtrGet(header);
799 AlignedPtr = MEMALIGN_POWEROF2(Ptr,Alignment);
800 delta = AlignedPtr - Ptr;
804 if (MemRemain < delta)
807 header = header->NextFree;
812 alignedheader = Ptr_To_MEM_CHUNK((
void*)(gsi_uint)AlignedPtr);
813 MEM_CHUNK_POOLChunkMove (_this,header,alignedheader);
814 header = alignedheader;
823 MEM_CHUNKAlloc(header,MemTagStack[MemTagStackIndex],Size);
826 if (MemRemain >
sizeof(MEM_CHUNK)*2)
830 MEM_CHUNK_POOLSplitChunk(_this,header, gsi_false);
835 if (_this->pFirstFree == header)
838 _this->pFirstFree = header->NextFree;
844 PrevFree = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,header);
846 PrevFree->NextFree = header->NextFree;
848 _this->pFirstFree = header->NextFree;
854 _this->MemUsed += MEM_CHUNKMemUsedGet(header);
856 if(_this->MemUsed > _this->HWMemUsed)
857 _this->HWMemUsed = _this->MemUsed;
859 GS_ASSERT(_this->MemUsed <= _this->HeapSize);
866 header = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,header);
868 header = header->NextFree;
871 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Misc, GSIDebugLevel_Notice,
" Could not allocate %i bytes\n", Size);
872 GS_ASSERT_STR(0,
"Out of memory");
882void MEM_CHUNK_POOLFreeChunk(MEM_CHUNK_POOL *_this,MEM_CHUNK *header)
889 MEM_CHUNK *prev = header;
890 MEM_CHUNK *next = header;
894 _this->MemUsed -= MEM_CHUNKMemUsedGet(header);
895 GS_ASSERT(_this->MemUsed >= 0);
898 while (next->next && (MEM_CHUNKIsFree(next->next)))
903 while (prev->prev && (MEM_CHUNKIsFree(prev->prev)))
912 prev->next = next->next;
915 next->next->prev = prev;
922 PrevFree = MEM_CHUNK_POOLFindPreviousFreeChunk(_this,prev);
923 if (PrevFree == NULL)
926 _this->pFirstFree = prev;
932 PrevFree->NextFree = prev;
937 prev->NextFree = MEM_CHUNK_POOLFindNextFreeChunk(_this,next->next);
939 prev->NextFree = NULL;
946 gsi_u32 destptr = (gsi_u32)prev->prev + prev->prev->MemAvailGet() +
sizeof(MEM_CHUNK);
947 destptr = MEMALIGN_POWEROF2(destptr,
sizeof(MEM_CHUNK));
950 if (destptr < (gsi_u32)prev )
951 ChunkMove(prev,(MEM_CHUNK *)destptr);
959void *MEM_CHUNK_POOLmalloc(MEM_CHUNK_POOL *_this,
size_t Size, gsi_i32 Alignment)
965 MEM_CHUNK *header = MEM_CHUNK_POOLAllocChunk( _this,Size, Alignment, gsi_false);
970 mem = MEM_CHUNKMemPtrGet(header);
979void *MEM_CHUNK_POOLmalloc_backwards(MEM_CHUNK_POOL *_this,
size_t Size, gsi_i32 Alignment)
985 MEM_CHUNK *header = MEM_CHUNK_POOLAllocChunk( _this,Size, Alignment, gsi_true);
990 mem = MEM_CHUNKMemPtrGet(header);
999void MEM_CHUNK_POOLfree(MEM_CHUNK_POOL *_this,
void *mem)
1004 MEM_CHUNK *header = Ptr_To_MEM_CHUNK(mem);
1005 MEM_CHUNK_POOLFreeChunk(_this,header);
1010void *MEM_CHUNK_POOLrealloc(MEM_CHUNK_POOL *_this,
void *oldmem,
size_t newSize)
1013 MEM_CHUNK *oldheader;
1014 MEM_CHUNK *NewHeader;
1022 return MEM_CHUNK_POOLmalloc( _this, newSize,PTR_ALIGNMENT);
1026 oldheader = Ptr_To_MEM_CHUNK(oldmem);
1027 OldSize = MEM_CHUNKMemUsedGet(oldheader);
1029 if (newSize == OldSize)
1032 if (newSize < OldSize )
1035 if ((newSize + 2 *
sizeof(MEM_CHUNK))> OldSize )
1042 MEM_CHUNKMemUsedSet(oldheader,newSize);
1043 MEM_CHUNK_POOLSplitChunk(_this,oldheader, gsi_true);
1044 return MEM_CHUNKMemPtrGet(oldheader);
1049 MemType = MEM_CHUNKMemTypeGet(oldheader);
1050 MEM_CHUNK_POOLFreeChunk(_this,oldheader);
1051 NewHeader = MEM_CHUNK_POOLAllocChunk( _this,newSize,PTR_ALIGNMENT,gsi_false);
1052 MEM_CHUNKMemTypeSet(NewHeader,MemType);
1054 memmove(MEM_CHUNKMemPtrGet(NewHeader),oldmem,OldSize);
1056 return MEM_CHUNKMemPtrGet(NewHeader);
1062void MEM_CHUNK_POOLMEM_CHUNK_POOL(MEM_CHUNK_POOL *_this)
1066 _this->HeaderEnd = NULL;
1067 _this->HeaderStart = NULL;
1068 _this->HeapSize = 0;
1069 _this->pFirstFree = NULL;
1077gsi_u32 MEM_CHUNK_POOLWalkForType(MEM_CHUNK_POOL *_this,
int type, gsi_bool _LogUse)
1082 header = _this->HeaderStart;
1086 MP_ASSERT((header->next == NULL) || ((gsi_uint)header < (gsi_uint)header->next ))
1087 MP_ASSERT((header->prev == NULL) || ((gsi_uint)header->prev < (gsi_uint)header ))
1088 MP_ASSERT((header->prev == NULL) || (header->prev->next == header))
1089 MP_ASSERT((header->next == NULL) || (header->next->prev == header))
1090 MP_ASSERT( MEM_CHUNKMemUsedGet(header) <= MEM_CHUNKChunkSizeGet(header) )
1092 if (!MEM_CHUNKIsFree(header) && (MEM_CHUNKMemTypeGet(header) == type))
1095 if ((header != _this->HeaderStart) && (header != _this->HeaderEnd))
1098 Total += MEM_CHUNKTotalSizeGet(header);
1101 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Misc, GSIDebugLevel_Notice,
"MemFound ptr:0x%8x size:%8u %s\n", MEM_CHUNKMemPtrGet(header),
1102 MEM_CHUNKMemUsedGet(header),MemMgrBufferGetName((gsMemMgrContext) type));
1109 MP_ASSERT (header->next || (header == _this->HeaderEnd))
1110 header = header->next;
1118void MEM_CHUNK_POOLMemStatsGet(MEM_CHUNK_POOL *_this,MEM_STATS *pS)
1120 int ChunksFreeLostCount ;
1123 MEM_CHUNK *NextFree;
1127 header = _this->HeaderStart;
1128 NextFree = _this->pFirstFree;
1135 MP_ASSERT((header->next == NULL) || ((gsi_uint)header < (gsi_uint)header->next ))
1136 MP_ASSERT((header->prev == NULL) || ((gsi_uint)header->prev < (gsi_uint)header ))
1137 MP_ASSERT((header->prev == NULL) || (header->prev->next == header))
1138 MP_ASSERT((header->next == NULL) || (header->next->prev == header))
1139 MP_ASSERT( MEM_CHUNKMemUsedGet(header) <= MEM_CHUNKChunkSizeGet(header) )
1141 pS->MemTotal += MEM_CHUNKTotalSizeGet(header);
1142 if (!MEM_CHUNKIsFree(header))
1145 pS->ChunksUsedCount++;
1146 if (pS->ChunksUsedCount_At_HighWater < pS->ChunksUsedCount)
1147 pS->ChunksUsedCount_At_HighWater = pS->ChunksUsedCount;
1150 pS->MemWasted += MEM_CHUNKTotalSizeGet(header) - MEM_CHUNKMemUsedGet(header);
1151 pS->MemUsed += MEM_CHUNKTotalSizeGet(header);
1153 type = MEM_CHUNKMemTypeGet(header);
1154 pS->MemType_MemUsed[type] += MEM_CHUNKTotalSizeGet(header);
1155 pS->MemType_ChunksCount[type]++;
1161 MP_ASSERT((header->NextFree == NULL) || ((gsi_uint)header < (gsi_uint)header->NextFree ))
1164 MP_ASSERT((header->next == NULL) || (!MEM_CHUNKIsFree(header->next)))
1165 MP_ASSERT((header->prev == NULL) || (!MEM_CHUNKIsFree(header->prev)))
1168 MP_ASSERT(header == NextFree)
1169 NextFree = header->NextFree;
1172 pS->MemWasted += MEM_CHUNKTotalSizeGet(header) - MEM_CHUNKChunkSizeGet(header);
1173 pS->MemUsed += MEM_CHUNKTotalSizeGet(header) - MEM_CHUNKChunkSizeGet(header);
1175 pS->ChunksFreeCount++;
1176 if (pS->ChunksFreeLargestAvail < MEM_CHUNKChunkSizeGet(header))
1177 pS->ChunksFreeLargestAvail = MEM_CHUNKChunkSizeGet(header);
1183 MP_ASSERT (header->next || (header == _this->HeaderEnd))
1184 header = header->next;
1189 header = _this->HeaderStart;
1194 while(header && (!MEM_CHUNKIsFree(header)))
1195 header = header->next;
1198 MP_ASSERT(_this->pFirstFree == header)
1200 ChunksFreeLostCount = pS->ChunksFreeCount;
1204 ChunksFreeLostCount --;
1205 pS->MemAvail +=MEM_CHUNKChunkSizeGet(header);
1206 header = header->NextFree;
1212 if (pS->MemUsed_At_HighWater < pS->MemUsed)
1213 pS->MemUsed_At_HighWater = pS->MemUsed;
1215 for ( i=0;i< MEM_TYPES_MAX;i++ )
1217 if (pS->MemType_MemUsed_At_HighWater[i] < pS->MemType_MemUsed[i] )
1218 pS->MemType_MemUsed_At_HighWater[i] = pS->MemType_MemUsed[i];
1221 MP_ASSERT(ChunksFreeLostCount == 0)
1225void MEM_CHUNK_POOLCheckValidity(MEM_CHUNK_POOL *_this)
1228 MEM_CHUNK_POOLMemStatsGet(_this,&stats);
1234void MEM_CHUNK_POOLFillMemoryTable(MEM_CHUNK_POOL *_this,
char *Table,
const int TableSize, gsi_u32 _HeapStart, gsi_u32 _HeapSize)
1238 gsi_u32 start_address;
1239 gsi_u32 end_address ;
1240 MEM_CHUNK *pChunk = _this->HeaderStart;
1241 MP_ASSERT(_this->HeapSize)
1246 if (!MEM_CHUNKIsFree(pChunk))
1248 start_address = (gsi_uint)pChunk;
1249 end_address = ((gsi_uint)pChunk->next)-1;
1252 s= ((start_address - _HeapStart) * (TableSize>>4)) / (_HeapSize>>4);
1253 MP_ASSERT(s < TableSize)
1256 e= (( end_address - _HeapStart) * (TableSize>>4)) / (_HeapSize>>4);
1257 MP_ASSERT(e < TableSize)
1260 for ( j= s; j<= e; j++)
1265 Table[j] = MEM_CHUNKMemTypeGet(pChunk);
1269 pChunk = pChunk->next;
1277static MEM_CHUNK_POOL gChunkPool [gsMemMgrContext_Count] ;
1282gsMemMgrContext gsMemMgrContextCurrent = gsMemMgrContext_Default;
1287gsMemMgrContext gsMemMgrContextFind (
void *ptr)
1292 for (i=0; i< gsMemMgrContext_Count;i++)
1295 MEM_CHUNK_POOLIsValid(&gChunkPool[i]) &&
1296 MEM_CHUNK_POOLItemIsInPoolMemory(&gChunkPool[i],ptr)
1299 return (gsMemMgrContext) i;
1303 return gsMemMgrContext_Invalid;
1306void *gs_malloc(
size_t size)
1309 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[gsMemMgrContextCurrent]),
"malloc: context is invalid mempool");
1311 return MEM_CHUNK_POOLmalloc(&gChunkPool[gsMemMgrContextCurrent], size,PTR_ALIGNMENT);
1314void *gs_calloc(
size_t size,
size_t size2)
1318 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[gsMemMgrContextCurrent]),
"calloc: context is invalid mempool");
1320 return MEM_CHUNK_POOLmalloc(&gChunkPool[gsMemMgrContextCurrent], size*size2,PTR_ALIGNMENT);
1323void *gs_realloc(
void* ptr,
size_t size)
1326 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[gsMemMgrContextCurrent]),
"realloc: context is invalid mempool");
1328 return MEM_CHUNK_POOLrealloc(&gChunkPool[gsMemMgrContextCurrent],ptr, size);
1331void *gs_memalign(
size_t boundary,
size_t size)
1335 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[gsMemMgrContextCurrent]),
"memalign: context is invalid mempool");
1337 return MEM_CHUNK_POOLmalloc(&gChunkPool[gsMemMgrContextCurrent], size,boundary);
1340void gs_free(
void *ptr)
1342 gsMemMgrContext context;
1344 context = gsMemMgrContextFind(ptr);
1345 GS_ASSERT_STR(context != gsMemMgrContext_Invalid,
"Attempt to free invalid ptr")
1347 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"free: ptr context is invalid mempool");
1348 MEM_CHUNK_POOLfree(&gChunkPool[context],ptr);
1352const
char *MemMgrBufferGetName(gsMemMgrContext context)
1354 GS_ASSERT_STR(context != gsMemMgrContext_Invalid,
"Invalid Context");
1355 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"Context out of range");
1356 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context ]),
"Invalid mempool");
1358 return gChunkPool[context].Name;
1362void gsMemMgrContextSet(gsMemMgrContext context)
1364 GS_ASSERT_STR(context != gsMemMgrContext_Invalid,
"Invalid Context");
1365 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"Context out of range");
1366 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"Setting context to invalid mempool");
1368 gsMemMgrContextCurrent = context;
1385gsMemMgrContext gsMemMgrCreate (gsMemMgrContext context,
const char *PoolName,
void* thePoolBuffer,
size_t thePoolSize)
1387 char *ptr = (
char *)thePoolBuffer;
1389 GS_ASSERT_STR(thePoolSize,
"Cannnot create a pool of size 0")
1390 GS_ASSERT_STR(thePoolSize,
"thePoolBuffer ptr is inivalid");
1391 GS_ASSERT_STR(((((gsi_uint)thePoolSize) &15) ==0) ,
"PoolSize must be aligned to 16 bytes");
1392 GS_ASSERT_STR(((((gsi_uint)thePoolBuffer)&15) ==0) ,
"thePoolBuffer must be aligned to 16 bytes");
1395 while (MEM_CHUNK_POOLIsValid(&gChunkPool[context]))
1397 context = (gsMemMgrContext)(context + 1);
1399 if (context == gsMemMgrContext_Count)
1402 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1403 "Out of memory context handles!\n");
1405 return gsMemMgrContext_Invalid;
1408 MEM_CHUNK_POOLCreate(&gChunkPool[context],PoolName,ptr,thePoolSize);
1410 gsiMemoryCallbacksSet(gs_malloc, gs_free, gs_realloc, gs_memalign);
1416void gsMemMgrDestroy(gsMemMgrContext context)
1418 GS_ASSERT(gChunkPool[context].HeapSize != 0);
1419 MEM_CHUNK_POOLDestroy(&gChunkPool[context]);
1425 gsiMemoryCallbacksSet(malloc,free,realloc,memalign);
1428 gsiDeleteCriticalSection(&gMemCrit);
1440void gsMemMgrTagPush (gsi_u8 tag)
1442 GS_ASSERT(MemTagStackIndex < MEM_TAG_STACK_MAX-1)
1444 MemTagStack[MemTagStackIndex] = tag;
1447void gsMemMgrTagPop ()
1449 GS_ASSERT(MemTagStackIndex > 0)
1453gsi_u8 gsMemMgrTagGet (
void *ptr)
1456 return MEM_CHUNKMemTypeGet( Ptr_To_MEM_CHUNK(ptr));
1459gsi_u32 gsMemMgrMemUsedByTagGet(gsi_u8 tag)
1463 for ( i=0;i< gsMemMgrContext_Count;i++)
1465 used+= MEM_CHUNK_POOLWalkForType(&gChunkPool[i] ,tag, gsi_false);
1472void gsMemMgrContextPush(gsMemMgrContext NewType)
1475 GS_ASSERT(MemTypeStackIndex < MEM_CONTEXT_STACK_MAX)
1476 GS_ASSERT(NewType < gsMemMgrContext_Count)
1479 MemTypeStack[MemTypeStackIndex++] = gsMemMgrContextCurrent;
1480 gsMemMgrContextCurrent = NewType;
1484gsMemMgrContext gsMemMgrContextPop()
1487 GS_ASSERT(MemTypeStackIndex > 0)
1489 gsMemMgrContextCurrent = MemTypeStack[--MemTypeStackIndex];
1490 return gsMemMgrContextCurrent;
1496gsi_u32 gsMemMgrMemAvailGet (gsMemMgrContext context)
1499 MEM_STATSClearAll(&stats);
1500 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"gsMemMgrMemAvailGet: context out of range");
1501 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"gsMemMgrMemAvailGet: context is invalid mempool");
1502 MEM_CHUNK_POOLMemStatsGet (&gChunkPool[context], &stats);
1503 return stats.MemAvail;
1508gsi_u32 gsMemMgrMemUsedGet (gsMemMgrContext context)
1511 MEM_STATSClearAll(&stats);
1512 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"gsMemMgrMemUsedGet: context out of range");
1513 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"gsMemMgrMemUsedGet: context is invalid mempool");
1514 MEM_CHUNK_POOLMemStatsGet (&gChunkPool[context], &stats);
1515 return stats.MemUsed;
1523gsi_u32 gsMemMgrMemLargestAvailGet (gsMemMgrContext context)
1526 MEM_STATSClearAll(&stats);
1527 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"gsMemMgrMemLargestAvailGet: context out of range");
1528 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"gsMemMgrMemLargestAvailGet: context is invalid mempool");
1529 MEM_CHUNK_POOLMemStatsGet (&gChunkPool[context], &stats);
1530 return stats.ChunksFreeLargestAvail;
1534gsi_u32 gsMemMgrMemHighwaterMarkGet (gsMemMgrContext context)
1536 GS_ASSERT_STR(context < gsMemMgrContext_Count,
"gsMemMgrMemLargestAvailGet: context out of range");
1537 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[context]),
"gsMemMgrMemLargestAvailGet: context is invalid mempool");
1540 return gChunkPool[context].HWMemUsed;
1543 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1544 "gsMemMgrMemHighwaterMarkGet called without MEM_PROFILE enabled.");
1550void gsMemMgrValidateMemoryPool()
1552 GS_ASSERT_STR(MEM_CHUNK_POOLIsValid(&gChunkPool[gsMemMgrContextCurrent]),
"memalign: context is invalid mempool");
1553 MEM_CHUNK_POOLCheckValidity(&gChunkPool[gsMemMgrContextCurrent]);
1560void gsMemMgrDumpStats()
1566 struct GSIMemoryBlock* aTempPtr = NULL;
1568 gsiEnterCriticalSection(&gMemCrit);
1572 aTempPtr = gMemoryMgr->mFirstFreeBlock;
1573 while(aTempPtr != NULL)
1576 aTempPtr = aTempPtr->mNext;
1581 aTempPtr = gMemoryMgr->mFirstUsedBlock;
1582 while(aTempPtr != NULL)
1585 aTempPtr = aTempPtr->mNext;
1589 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1590 "BytesUsed: %d, BlocksUsed: %d, BlocksFree: %d\r\n",
1591 gMemoryMgr->mMemUsed, numUsed, numFree);
1593 gsiLeaveCriticalSection(&gMemCrit);
1600void gsMemMgrDumpAllocations()
1603 struct GSIMemoryBlock* aBlockPtr = NULL;
1604 gsi_time aStartTime = 0;
1605 gsi_i32 aNumAllocations = 0;
1606 gsi_i32 aNumBytesAllocated = 0;
1608 gsiEnterCriticalSection(&gMemCrit);
1610 aStartTime = current_time();
1611 aBlockPtr = (GSIMemoryBlock*)gMemoryMgr->mPoolStart;
1614 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1615 "Dumping allocations from pool - [0x%08x] %d bytes.\r\n",
1616 gMemoryMgr->mPoolStart, gMemoryMgr->mPoolSize);
1620 while(aBlockPtr != NULL)
1623 if (gsiMemBlockIsFlagged(aBlockPtr, BlockFlag_Used))
1625 int anObjectSize = gsiMemBlockGetObjectSize(aBlockPtr);
1627 aNumBytesAllocated += anObjectSize;
1629 if (aBlockPtr == gMemoryMgr->mPoolStart)
1631 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1632 "\t[0x%08x] Size: %d (memmgr instance)\r\n", (gsi_u32)aBlockPtr, anObjectSize);
1636 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1637 "\t[0x%08x] Size: %d\r\n", (gsi_u32)(gsiMemBlockGetObjectPtr(aBlockPtr)), anObjectSize);
1645 aBlockPtr = gsiMemBlockGetLinearNext(aBlockPtr);
1649 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1650 "\t--%d allocations, %d bytes allocated.\r\n", aNumAllocations, aNumBytesAllocated);
1651 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1652 "\t--%d peak memory usage\r\n", gMemoryMgr->mPeakMemoryUsage);
1654 gsDebugFormat(GSIDebugCat_App, GSIDebugType_Memory, GSIDebugLevel_Comment,
1655 "Memory dump complete. (%d ms)\r\n", current_time() - aStartTime);
1657 gsiLeaveCriticalSection(&gMemCrit);
1659 GSI_UNUSED(aStartTime);
1667#define PTR_TABLE_SIZE 2048
1668static int PtrTableCount = 0;
1669static void *PtrTable[2048];
1673 return Util_RandInt(0,x);
1676void gsMemMgrSelfText()
1681 static MEM_CHUNK_POOL gChunkPool;
1682 int size = 32 * 1024 * 1024;
1686 char *ptr = (
char *) ( ((gsi_uint)malloc(size-PTR_ALIGNMENT)+(PTR_ALIGNMENT-1))&~ (PTR_ALIGNMENT-1) ) ;
1687 MEM_CHUNK_POOLCreate(&gChunkPool,
"",ptr,size);
1693 if ((i==0) &&(PtrTableCount < 1024))
1697 k = 32<< (Random(4));
1700 PtrTable[PtrTableCount] = MEM_CHUNK_POOLmalloc(&gChunkPool, j,k);
1702 PtrTable[PtrTableCount] = MEM_CHUNK_POOLmalloc_backwards(&gChunkPool, j,k);
1704 if(PtrTable[PtrTableCount])
1715 if ((i==1) &&(PtrTableCount))
1718 j = Random(PtrTableCount);
1719 MP_ASSERT(j < PtrTableCount)
1722 MEM_CHUNK_POOLfree(&gChunkPool,PtrTable[j]);
1726 PtrTable[j] = PtrTable[PtrTableCount];
1730 if ((i==2) &&(PtrTableCount))
1732 j = Random(PtrTableCount);
1733 MP_ASSERT(j < PtrTableCount)
1736 k = Random(1024) +1;
1738 PtrTable[j] = MEM_CHUNK_POOLrealloc(&gChunkPool,PtrTable[j], k);
1741 PtrTable[j] = PtrTable[j];
1757 MEM_CHUNK_POOLCheckValidity(&gChunkPool);