OpenBarnyard
 
Loading...
Searching...
No Matches
TMemory Class Reference

Core memory management class that handles all memory allocations and deallocations. More...

#include <TMemory.h>

Classes

struct  HALMemInfo
 Hardware abstraction layer memory information. More...
 
struct  MemBlock
 Represents a contiguous block of memory that can be allocated from. More...
 
struct  MemBlockFooter
 Footer structure at the end of each memory block for validation. More...
 
struct  MemBlockSlot
 Slot for tracking memory blocks in the block list. More...
 
struct  MemInfo
 Structure containing memory usage statistics. More...
 
class  MemNode
 Represents a node in the memory allocation system. More...
 

Public Member Functions

 TMemory ()
 Constructor for TMemory class Initializes the memory management system.
 
 ~TMemory ()
 Destructor for TMemory class Cleans up the memory management system.
 
void * Alloc (TSIZE a_uiSize, TSIZE a_uiAlignment, MemBlock *a_pMemBlock, const TCHAR *a_szFileName, TINT a_iLineNum)
 Allocates memory with specified size and alignment.
 
TBOOL Free (const void *a_pMem)
 Frees previously allocated memory.
 
void * SysAlloc (TSIZE a_uiSize)
 Allocates memory from the system heap.
 
void SysFree (void *a_pMem)
 Frees memory back to the system heap.
 
MemBlockCreateMemBlock (TSIZE a_uiSize, const TCHAR *a_szName, MemBlock *a_pOwnerBlock, TINT a_iUnused)
 Creates a new memory block.
 
MemBlockCreateMemBlockInPlace (void *a_pMem, TSIZE a_uiSize, const TCHAR *a_szName)
 Creates a memory block at a specific location.
 
void DestroyMemBlock (MemBlock *a_pMemBlock)
 Destroys a memory block.
 
MemBlockGetGlobalBlock () const
 Gets the global memory block.
 
TMemory::MemBlockSetGlobalBlock (MemBlock *a_pMemBlock)
 Sets the global memory block.
 
TUINT GetGlobalFlags () const
 
void DumpMemInfo ()
 

Static Public Member Functions

static void GetMemInfo (MemInfo &a_rMemInfo, MemBlock *a_pMemBlock)
 
static void GetHALMemInfo (HALMemInfo &a_rHALMemInfo)
 
static TBOOL Initialise (TSIZE a_uiHeapSize, TSIZE a_uiReservedSize, TUINT a_uiUnused=0)
 Initializes the memory system.
 
static void Deinitialise ()
 Deinitializes the memory system.
 
static TUINT MapSizeToFreeList (TSIZE a_uiSize)
 
static void DebugPrintHALMemInfo (const TCHAR *a_szFormat,...)
 Debug print of HAL memory info.
 

Detailed Description

Core memory management class that handles all memory allocations and deallocations.

This class implements a custom memory allocator with the following features:

  • Memory block management with alignment support
  • Memory tracking and debugging capabilities
  • Support for memory pools and sub-heaps
  • Thread-safe operations

Definition at line 47 of file TMemory.h.

Constructor & Destructor Documentation

◆ TMemory()

TMemory::TMemory ( )

Constructor for TMemory class Initializes the memory management system.

Constructor for TMemory class Initializes the memory management system and sets up the global instance.

Definition at line 138 of file TMemory.cpp.

139{
140 TASSERT( g_pMemory == TNULL );
141 g_pMemory = this;
142
143 m_TotalAllocatedSize = 0;
144
145 for ( TINT i = 0; i < TMEMORY_NUM_BLOCK_SLOTS; i++ )
146 {
147 m_FreeBlocks.InsertTail( &m_aBlockSlots[ i ] );
148 }
149
150 m_bFlag1 = TFALSE;
151 m_bFlag2 = TTRUE;
152}
TOSHI_NAMESPACE_START class TMemory * g_pMemory
#define TMEMORY_NUM_BLOCK_SLOTS
Maximum number of memory block slots.
Definition TMemory.h:29
#define TASSERT(X,...)
Definition Defines.h:138
#define TNULL
Definition Typedefs.h:23
int TINT
Definition Typedefs.h:7
#define TFALSE
Definition Typedefs.h:24
#define TTRUE
Definition Typedefs.h:25

◆ ~TMemory()

TMemory::~TMemory ( )

Destructor for TMemory class Cleans up the memory management system.

Destructor for TMemory class Cleans up the memory management system and clears the global instance.

Definition at line 158 of file TMemory.cpp.

159{
161}

Member Function Documentation

◆ Alloc()

void * TMemory::Alloc ( TSIZE a_uiSize,
TSIZE a_uiAlignment,
MemBlock * a_pMemBlock,
const TCHAR * a_szFileName,
TINT a_iLineNum )

Allocates memory with specified size and alignment.

Parameters
a_uiSizeSize of memory to allocate
a_uiAlignmentAlignment requirement for the allocation
a_pMemBlockMemory block to allocate from (NULL for global block)
a_szFileNameSource file name for debugging
a_iLineNumSource line number for debugging
Returns
Pointer to allocated memory or NULL if allocation failed
Parameters
a_uiSizeSize of memory to allocate
a_uiAlignmentAlignment requirement for the allocation
a_pMemBlockMemory block to allocate from (NULL for global block)
a_szFileNameSource file name for debugging
a_iLineNumSource line number for debugging
Returns
Pointer to allocated memory or NULL if allocation failed

This function implements the core memory allocation logic:

  1. Validates input parameters
  2. Finds a suitable free hole in the memory block
  3. Splits the hole if necessary
  4. Updates memory block metadata
  5. Returns the allocated memory pointer

Definition at line 213 of file TMemory.cpp.

214{
215 //return CALL_THIS( 0x006b5230, TMemory*, void*, this, TUINT, a_uiSize, TINT, a_uiAlignment, MemBlock*, a_pMemBlock, const TCHAR*, a_szFileName, TINT, a_iLineNum );
216
217 TMUTEX_LOCK_SCOPE( ms_pGlobalMutex );
218
219 volatile TSIZE uiSize = a_uiSize;
220 volatile TSIZE uiAlignment = a_uiAlignment;
221 MemBlock* pMemBlock = a_pMemBlock;
222
223 if ( uiSize < 4 )
224 uiSize = 4;
225
226 if ( uiAlignment < 16 )
227 uiAlignment = 16;
228
229 if ( uiAlignment < TMEMORY_ROUNDUP )
230 {
231 TDebug_FinalPrintf( "MEMORY ERROR: CANT ALLOC Alignment(%d)<TMEMORY_ROUNDUP\n", uiAlignment );
232 DebugPrintHALMemInfo( "Out of Toshi Memory on block [%s]\n", pMemBlock->m_szName );
233 TASSERT( TFALSE );
234 return TNULL;
235 }
236
237 if ( !pMemBlock )
238 {
239 pMemBlock = m_pGlobalBlock;
240 }
241
242 volatile TSIZE uiAlignedSize = TAlignNumUp( uiSize );
243 volatile TSIZE uiRequiredSize = uiAlignedSize + sizeof( MemNode );
244
245 MemNode* pMemNode = TNULL;
246
247 volatile void* pAllocatedAddress;
248 volatile TUINTPTR uiDataRegionStart;
249 volatile TUINTPTR uiDataRegionEnd;
250 volatile TUINTPTR uiDataRegionSize;
251
252 volatile TUINT uiNodeId = MapSizeToFreeList( uiAlignedSize );
253
254 // Find a hole that can allocate the required number of bytes
255 for ( ; uiNodeId < TMEMORY_NUM_FREELISTS; uiNodeId++ )
256 {
257 pMemNode = pMemBlock->m_apHoles[ uiNodeId ];
258
259 while ( pMemNode != TNULL )
260 {
261 pAllocatedAddress = TAlignPointerUp( pMemNode->GetDataRegionStart(), uiAlignment );
262 uiDataRegionStart = TREINTERPRETCAST( TUINTPTR, pAllocatedAddress );
263 uiDataRegionEnd = TREINTERPRETCAST( TUINTPTR, pMemNode->GetDataRegionEnd() );
264 uiDataRegionSize = uiDataRegionEnd - uiDataRegionStart;
265
266 if ( uiDataRegionEnd > uiDataRegionStart && uiDataRegionSize >= uiAlignedSize )
267 break;
268
269 // This freelist can't be used, let's check for the next
270 pMemNode = pMemNode->pNextHole;
271 }
272
273 if ( pMemNode )
274 break;
275 }
276
277 if ( !pMemNode )
278 {
279 DebugPrintHALMemInfo( "Out of Toshi Memory on block [%s]\n", pMemBlock->m_szName );
280 DebugPrintHALMemInfo( "Requested memory block size: %d\n", uiAlignedSize );
281 DumpMemInfo();
282
283 TASSERT( TFALSE );
284 return TNULL;
285 }
286
287# ifdef TOSHI_PROFILER_MEMORY
288 // Create named zone to make it possible to know where the allocation occured
289 tracy::ScopedZone zone( TMemory__LINE__, TMemory__FILE__, T2String8::Length( TMemory__FILE__ ), "", 0, TMemory__FUNC__ ? TMemory__FUNC__ : "", TMemory__FUNC__ ? T2String8::Length( TMemory__FUNC__ ) : 0 );
290# endif
291
292 MemNode* pAllocNode = MEM_TO_NODE( pAllocatedAddress );
293
294 if ( volatile MemNode* pOwner = pMemNode->pOwner )
295 {
296 pOwner->uiSize = ( uiDataRegionStart - (TUINTPTR)pOwner - 24 ) | pOwner->uiSize & TMEMORY_FLAGS_MASK;
297 }
298 else if ( pAllocNode != pMemNode )
299 {
300 // Seems that due to alignment we have a gap between start of the
301 // data region and the actual address we gonna return so let's
302 // make sure we don't lost this pointer
303 pMemBlock->m_pFirstHole = pAllocNode;
304 }
305
306 // Check if we can split the hole in two
307 if ( uiDataRegionSize > uiRequiredSize )
308 {
309 // We can split it!
310
311 // Unlink the hole from the linked list
312 if ( volatile MemNode* pPrev = pMemNode->pPrevHole )
313 pPrev->pNextHole = pMemNode->pNextHole;
314 else
315 pMemBlock->m_apHoles[ uiNodeId ] = pMemNode->pNextHole;
316
317 // Remove reference to this hole from the next one
318 if ( volatile MemNode* pNext = pMemNode->pNextHole )
319 pNext->pPrevHole = pMemNode->pPrevHole;
320
321 if ( pMemNode != pAllocNode )
322 {
323 TSIZE uiNodeSize = GetNodeSize( pMemNode );
324 pAllocNode->pOwner = pMemNode->pOwner;
325 *(MemNode**)( (TUINTPTR)pMemNode->GetDataRegionStart() + uiNodeSize ) = pAllocNode;
326 }
327
328 // Create a new hole right after the allocated data
329 MemNode* pNewNode = TREINTERPRETCAST( MemNode*, uiDataRegionStart + uiAlignedSize );
330
331 SetProcess( pMemBlock, pAllocNode, uiDataRegionSize );
332 SetHoleSize( pNewNode, (TUINTPTR)pAllocNode + GetNodeSize( pAllocNode ) - uiDataRegionStart - uiAlignedSize );
333 SetProcess( pMemBlock, pAllocNode, uiAlignedSize + uiDataRegionStart - (TUINTPTR)pAllocNode - TMEMORY_ALLOC_RESERVED_SIZE );
334 pNewNode->pOwner = pAllocNode;
335
336 // Place the new hole in the memblock's list
337
338 TUINT uiNewHoleId = MapSizeToFreeList( GetNodeSize( pNewNode ) );
339
340 MemNode* pOldNode = pMemBlock->m_apHoles[ uiNewHoleId ];
341 pNewNode->pNextHole = pOldNode;
342
343 if ( pOldNode )
344 pOldNode->pPrevHole = pNewNode;
345
346 pNewNode->pPrevHole = TNULL;
347 pMemBlock->m_apHoles[ uiNewHoleId ] = pNewNode;
348
349 // Save pointer to the hole right at the end of the data region (probably for some validation)
350 *(MemNode* volatile*)pNewNode->GetDataRegionEnd() = pNewNode;
351
352# ifdef TOSHI_PROFILER_MEMORY
353 TracyAlloc( (void*)pAllocatedAddress, uiAlignedSize );
354# endif
355 return (void*)pAllocatedAddress;
356 }
357 else
358 {
359 // Damn, we can't split this one but it surely can fit the allocation
360
361 // Unlink the hole from the linked list
362 if ( volatile MemNode* pPrev = pMemNode->pPrevHole )
363 pPrev->pNextHole = pMemNode->pNextHole;
364 else
365 pMemBlock->m_apHoles[ uiNodeId ] = pMemNode->pNextHole;
366
367 // Remove reference to this hole from the next one
368 if ( volatile MemNode* pNext = pMemNode->pNextHole )
369 pNext->pPrevHole = pMemNode->pPrevHole;
370
371 if ( pMemNode != pAllocNode )
372 {
373 TSIZE uiNodeSize = GetNodeSize( pMemNode );
374 pAllocNode->pOwner = pMemNode->pOwner;
375 *(MemNode* volatile*)( (TUINTPTR)pMemNode->GetDataRegionStart() + uiNodeSize ) = pAllocNode;
376 }
377
378 SetProcess( pMemBlock, pAllocNode, uiDataRegionSize );
379
380# ifdef TOSHI_PROFILER_MEMORY
381 TracyAlloc( (void*)pAllocatedAddress, uiAlignedSize );
382# endif
383 return (void*)pAllocatedAddress;
384 }
385}
#define MEM_TO_NODE(PTR)
Definition TMemory.cpp:127
#define TMEMORY_NUM_FREELISTS
Number of free list buckets for different sizes.
Definition TMemory.h:28
#define TMEMORY_ROUNDUP
Minimum alignment for memory blocks.
Definition TMemory.h:25
#define TMEMORY_ALLOC_RESERVED_SIZE
Reserved space in allocations.
Definition TMemory.h:31
#define TMEMORY_FLAGS_MASK
Mask for memory block flags.
Definition TMemory.h:27
void TDebug_FinalPrintf(const TCHAR *a_szFormat,...)
#define TMUTEX_LOCK_SCOPE(mutex)
Definition TMutexLock.h:4
#define TREINTERPRETCAST(TYPE, VALUE)
Definition Defines.h:68
TFORCEINLINE constexpr T * TAlignPointerUp(T *a_pMem, TSIZE a_uiAlignment=sizeof(T *))
Definition Helpers.h:41
TFORCEINLINE constexpr T TAlignNumUp(T a_iValue, TSIZE a_uiAlignment=4)
Definition Helpers.h:66
unsigned int TUINT
Definition Typedefs.h:8
uintptr_t TUINTPTR
Definition Typedefs.h:18
size_t TSIZE
Definition Typedefs.h:9
static TUINT MapSizeToFreeList(TSIZE a_uiSize)
Definition TMemory.cpp:767
void DumpMemInfo()
Definition TMemory.cpp:809
static void DebugPrintHALMemInfo(const TCHAR *a_szFormat,...)
Debug print of HAL memory info.
Definition TMemory.cpp:845
Represents a node in the memory allocation system.
Definition TMemory.h:70
MemNode * pOwner
Owner node if this is a sub-allocation.
Definition TMemory.h:85
MemNode * pNextHole
Next free hole in the list.
Definition TMemory.h:89
MemNode * pPrevHole
Previous free hole in the list.
Definition TMemory.h:93
void * GetDataRegionEnd() const
Gets the end address of the data region for this node.
Definition TMemory.h:82
Represents a contiguous block of memory that can be allocated from.
Definition TMemory.h:101
static TSIZE Length(const TCHAR *str)

◆ CreateMemBlock()

TMemory::MemBlock * TMemory::CreateMemBlock ( TSIZE a_uiSize,
const TCHAR * a_szName,
MemBlock * a_pOwnerBlock,
TINT a_iUnused )

Creates a new memory block.

Parameters
a_uiSizeSize of the memory block
a_szNameName of the memory block
a_pOwnerBlockOwner block (NULL for global block)
a_iUnusedUnused parameter
Returns
Pointer to created memory block
Parameters
a_uiSizeSize of the memory block
a_szNameName of the memory block
a_pOwnerBlockOwner block (NULL for global block)
a_iUnusedUnused parameter
Returns
Pointer to created memory block

This function:

  1. Allocates memory for the block
  2. Initializes the block structure
  3. Sets up the initial free hole
  4. Returns the created block

Definition at line 488 of file TMemory.cpp.

489{
490 void* pMem = Alloc( a_uiSize, 16, a_pOwnerBlock, TNULL, -1 );
491 return CreateMemBlockInPlace( pMem, a_uiSize, a_szName );
492}
MemBlock * CreateMemBlockInPlace(void *a_pMem, TSIZE a_uiSize, const TCHAR *a_szName)
Creates a memory block at a specific location.
Definition TMemory.cpp:508
void * Alloc(TSIZE a_uiSize, TSIZE a_uiAlignment, MemBlock *a_pMemBlock, const TCHAR *a_szFileName, TINT a_iLineNum)
Allocates memory with specified size and alignment.
Definition TMemory.cpp:213

◆ CreateMemBlockInPlace()

TMemory::MemBlock * TMemory::CreateMemBlockInPlace ( void * a_pMem,
TSIZE a_uiSize,
const TCHAR * a_szName )

Creates a memory block at a specific location.

Parameters
a_pMemPointer to memory location
a_uiSizeSize of the memory block
a_szNameName of the memory block
Returns
Pointer to created memory block
Parameters
a_pMemPointer to memory location
a_uiSizeSize of the memory block
a_szNameName of the memory block
Returns
Pointer to created memory block

This function:

  1. Validates the input parameters
  2. Initializes the block structure in place
  3. Sets up the initial free hole
  4. Returns the created block

Definition at line 508 of file TMemory.cpp.

509{
510 TMUTEX_LOCK_SCOPE( ms_pGlobalMutex );
511
512 if ( a_pMem && a_uiSize != 0 && !m_FreeBlocks.IsEmpty() )
513 {
514 auto pBlock = TREINTERPRETCAST( MemBlock*, TAlignNumDown( TREINTERPRETCAST( TUINTPTR, a_pMem ) ) );
515 auto uiBlockTotalSize = ( TREINTERPRETCAST( TUINTPTR, a_pMem ) + TAlignNumDown( a_uiSize ) ) - TREINTERPRETCAST( TUINTPTR, pBlock );
516
517 if ( pBlock )
518 {
519 auto pSlot = m_FreeBlocks.RemoveHead();
520 m_UsedBlocks.InsertHead( pSlot );
521
522 pBlock->m_pSlot = pSlot;
523 pBlock->m_pSlot->m_pPtr = pBlock;
524 }
525
526 if ( uiBlockTotalSize != 0 )
527 {
528 constexpr TSIZE CHUNK_RESERVED_SIZE = ( sizeof( MemBlock ) + ( sizeof( MemNode ) - sizeof( void* ) ) );
529
530 pBlock->m_uiTotalSize1 = uiBlockTotalSize;
531 TUtil::MemClear( pBlock->m_apHoles, sizeof( pBlock->m_apHoles ) );
532 pBlock->m_pFirstHole = &pBlock->m_RootHole;
533
534 auto pHole = &pBlock->m_RootHole;
535 pHole->uiSize = uiBlockTotalSize - CHUNK_RESERVED_SIZE;
536 pHole->pNextHole = TNULL;
537 pHole->pPrevHole = TNULL;
538 pHole->pOwner = TNULL;
539
540 auto uiFreeListId = MapSizeToFreeList( uiBlockTotalSize - CHUNK_RESERVED_SIZE );
541 pBlock->m_apHoles[ uiFreeListId ] = pHole;
542
543 auto pBlockFooter = TREINTERPRETCAST( MemBlockFooter*, TREINTERPRETCAST( TUINTPTR, pBlock ) + uiBlockTotalSize ) - 1;
544 pBlockFooter->m_pBlockOwner = TNULL;
545 pBlockFooter->m_Unk4 = 0;
546 pBlockFooter->m_Unk1 = 0;
547 pBlockFooter->m_Unk2 = g_pMemory->m_uiGlobalFlags | TMEMORY_FLAGS_HOLE_PROCESS;
548 pBlockFooter->m_pBlockOwner = pBlock;
549
550 pBlock->m_pNextBlock = pBlock;
551 pBlock->m_uiTotalSize2 = uiBlockTotalSize;
552 TStringManager::String8Copy( pBlock->m_szSignature, "#MB_uID" );
553 TStringManager::String8Copy( pBlock->m_szName, a_szName );
554
555 return pBlock;
556 }
557 }
558
559 return TNULL;
560}
#define TMEMORY_FLAGS_HOLE_PROCESS
Flag indicating a memory block is in use.
Definition TMemory.h:26
TFORCEINLINE constexpr T TAlignNumDown(T a_iValue, TSIZE a_uiAlignment=4)
Definition Helpers.h:59
Footer structure at the end of each memory block for validation.
Definition TMemory.h:118
static TCHAR * String8Copy(TCHAR *dst, const TCHAR *src, TSIZE size=-1)
static void MemClear(void *ptr, TSIZE size)
Definition TUtil.h:91

◆ DebugPrintHALMemInfo()

void TMemory::DebugPrintHALMemInfo ( const TCHAR * a_szFormat,
... )
static

Debug print of HAL memory info.

Parameters
a_szFormatFormat string
...Variable arguments

Definition at line 845 of file TMemory.cpp.

846{
847 va_list args;
848 va_start( args, a_szFormat );
849 TDebug_FinalVPrintf( a_szFormat, args );
850 va_end( args );
851}
void TDebug_FinalVPrintf(const TCHAR *a_szFormat, va_list a_Args)

◆ Deinitialise()

void TMemory::Deinitialise ( )
static

Deinitializes the memory system.

This function:

  1. Cleans up all memory blocks
  2. Frees the main memory block
  3. Destroys the TMemory instance

Definition at line 743 of file TMemory.cpp.

744{
745 TASSERT( g_pMemory != TNULL );
746 auto pMainBlockMemory = g_pMemory->m_pMemory;
747
748 g_pMemory->m_UsedBlocks.RemoveAll();
749 g_pMemory->m_FreeBlocks.RemoveAll();
751
752 free( g_pMemory );
753 free( pMainBlockMemory );
754}
~TMemory()
Destructor for TMemory class Cleans up the memory management system.
Definition TMemory.cpp:158

◆ DestroyMemBlock()

void TMemory::DestroyMemBlock ( MemBlock * a_pMemBlock)

Destroys a memory block.

Parameters
a_pMemBlockPointer to memory block to destroy
a_pMemBlockPointer to memory block to destroy

This function:

  1. Frees all memory in the block
  2. Removes the block from tracking
  3. Frees the block structure itself

Definition at line 572 of file TMemory.cpp.

573{
574 FreeMemBlock( a_pMemBlock );
575 Free( a_pMemBlock );
576}
TBOOL Free(const void *a_pMem)
Frees previously allocated memory.
Definition TMemory.cpp:399

◆ DumpMemInfo()

void TMemory::DumpMemInfo ( )

Definition at line 809 of file TMemory.cpp.

810{
811 MemInfo memInfo;
812
813 for ( auto it = m_UsedBlocks.Tail(); it != m_UsedBlocks.End(); --it )
814 {
815 GetMemInfo( memInfo, it->m_pPtr );
816
817 DebugPrintHALMemInfo( "Pool: \'%s\'\n", it->m_pPtr->m_szName );
818 DebugPrintHALMemInfo( "\tLargest Hole : %d\n", memInfo.m_uiLargestHole );
819 DebugPrintHALMemInfo( "\tSmallest Hole : %d\n", memInfo.m_uiSmallestHole );
820 DebugPrintHALMemInfo( "\tLargest Process : %d\n", memInfo.m_uiLargestProcess );
821 DebugPrintHALMemInfo( "\tSmallest Process: %d\n", memInfo.m_uiSmallestProcess );
822 DebugPrintHALMemInfo( "\tTotal Free : %d\n", memInfo.m_uiTotalFree );
823 DebugPrintHALMemInfo( "\tTotal Used : %d\n", memInfo.m_uiTotalUsed );
824 DebugPrintHALMemInfo( "\tTotal Size : %d\n", memInfo.m_uiTotalSize );
825 DebugPrintHALMemInfo( "\tLogic Total Free: %d\n", memInfo.m_uiLogicTotalFree );
826 DebugPrintHALMemInfo( "\tLogic Total Used: %d\n", memInfo.m_uiLogicTotalUsed );
827 DebugPrintHALMemInfo( "\tLogic Total Size: %d\n", memInfo.m_uiLogicTotalSize );
828
829 TFLOAT fLogicTotalUsed = TMath::Abs( TFLOAT( memInfo.m_uiLogicTotalUsed ) );
830 TFLOAT fLogicTotalSize = TMath::Abs( TFLOAT( memInfo.m_uiLogicTotalSize ) );
831 DebugPrintHALMemInfo( "\t%%Logical Used : %f\n", ( fLogicTotalUsed / fLogicTotalSize ) * 100.0 );
832
833 TFLOAT fTotalUsed = TMath::Abs( TFLOAT( memInfo.m_uiTotalUsed ) );
834 TFLOAT fTotalSize = TMath::Abs( TFLOAT( memInfo.m_uiTotalSize ) );
835 DebugPrintHALMemInfo( "\t%%Used\t : %f\n", ( fTotalUsed / fTotalSize ) * 100.0 );
836 DebugPrintHALMemInfo( "------\n\n" );
837 }
838}
float TFLOAT
Definition Typedefs.h:4
TFORCEINLINE TFLOAT Abs(TFLOAT fVal)
Definition TMathInline.h:63
static void GetMemInfo(MemInfo &a_rMemInfo, MemBlock *a_pMemBlock)
Definition TMemory.cpp:864
Structure containing memory usage statistics.
Definition TMemory.h:139

◆ Free()

TBOOL TMemory::Free ( const void * a_pAllocated)

Frees previously allocated memory.

Parameters
a_pMemPointer to memory to free
Returns
TRUE if memory was successfully freed
Parameters
a_pAllocatedPointer to memory to free
Returns
TRUE if memory was successfully freed

This function implements the core memory deallocation logic:

  1. Validates the input pointer
  2. Converts the process node back to a hole
  3. Coalesces adjacent free holes if possible
  4. Updates memory block metadata

Definition at line 399 of file TMemory.cpp.

400{
401 //return CALL_THIS( 0x006b4a20, TMemory*, TBOOL, this, const void*, a_pAllocated );
402
403 TMUTEX_LOCK_SCOPE( ms_pGlobalMutex );
404
405 if ( !a_pAllocated || !TIsPointerAligned( a_pAllocated ) )
406 {
407 // Can't free TNULL or unaligned pointer
408 return TFALSE;
409 }
410
411# ifdef TOSHI_PROFILER_MEMORY
412 TracyFree( a_pAllocated );
413# endif
414
415 MemNode* pAllocationNode = MEM_TO_NODE( a_pAllocated );
416
417 TSIZE uiAllocationSize = GetNodeSize( pAllocationNode );
418 MemBlock* pMemBlock = GetProcessMemBlock( pAllocationNode );
419
420 SetHoleSize( pAllocationNode, uiAllocationSize );
421
422 MemNode* pNextLyingNode = (MemNode*)pAllocationNode->GetDataRegionEnd();
423 MemNode* pOwner = pAllocationNode->pOwner;
424
425 MemNode** ppNextNode = &pAllocationNode->pNextHole;
426
427 if ( pOwner && !IsProcess( pOwner ) )
428 {
429 pAllocationNode = pOwner;
430 TSIZE uiOwnerSize = GetNodeSize( pOwner );
431
432 ExtendNodeSize( pOwner, uiAllocationSize + uiOwnerSize + TMEMORY_ALLOC_RESERVED_SIZE );
433 pNextLyingNode->pOwner = pOwner;
434 ppNextNode = &pOwner->pNextHole;
435
436 if ( MemNode* pPrev = pOwner->pPrevHole )
437 pPrev->pNextHole = pOwner->pNextHole;
438 else
439 pMemBlock->m_apHoles[ MapSizeToFreeList( uiOwnerSize ) ] = pOwner->pNextHole;
440
441 if ( MemNode* pNext = pOwner->pNextHole )
442 pNext->pPrevHole = pOwner->pPrevHole;
443 }
444
445 if ( !IsProcess( pNextLyingNode ) )
446 {
447 TSIZE uiNextNodeSize = GetNodeSize( pNextLyingNode );
448
449 if ( MemNode* pPrev = pNextLyingNode->pPrevHole )
450 pPrev->pNextHole = pNextLyingNode->pNextHole;
451 else
452 pMemBlock->m_apHoles[ MapSizeToFreeList( uiNextNodeSize ) ] = pNextLyingNode->pNextHole;
453
454 if ( MemNode* pNext = pNextLyingNode->pNextHole )
455 pNext->pPrevHole = pNextLyingNode->pPrevHole;
456
457 ExtendNodeSize( pAllocationNode, GetNodeSize( pAllocationNode ) + GetNodeSize( pNextLyingNode ) + TMEMORY_ALLOC_RESERVED_SIZE );
458 *(MemNode**)pNextLyingNode->GetDataRegionEnd() = pAllocationNode;
459 }
460
461 TUINT uiId = MapSizeToFreeList( GetNodeSize( pAllocationNode ) );
462 pAllocationNode->pPrevHole = TNULL;
463 *ppNextNode = pMemBlock->m_apHoles[ uiId ];
464
465 if ( *ppNextNode )
466 ( *ppNextNode )->pPrevHole = pAllocationNode;
467
468 pMemBlock->m_apHoles[ uiId ] = pAllocationNode;
469
470 return TTRUE;
471}
TFORCEINLINE TBOOL TIsPointerAligned(const void *a_pPointer, TSIZE a_uiAlignment=sizeof(void *))
Definition Helpers.h:35

◆ GetGlobalBlock()

Toshi::TMemory::MemBlock * TMemory::GetGlobalBlock ( ) const

Gets the global memory block.

Returns
Pointer to global memory block

Definition at line 582 of file TMemory.cpp.

583{
584 return m_pGlobalBlock;
585}

◆ GetGlobalFlags()

TUINT TMemory::GetGlobalFlags ( ) const
inline

Definition at line 251 of file TMemory.h.

251{ return m_uiGlobalFlags; }

◆ GetHALMemInfo()

void TMemory::GetHALMemInfo ( HALMemInfo & a_rHALMemInfo)
static

Definition at line 956 of file TMemory.cpp.

957{
958 TUtil::MemClear( &a_rHALMemInfo, sizeof( a_rHALMemInfo ) );
959}

◆ GetMemInfo()

void TMemory::GetMemInfo ( MemInfo & a_rMemInfo,
MemBlock * a_pMemBlock )
static

Definition at line 864 of file TMemory.cpp.

865{
866 TMUTEX_LOCK_SCOPE( ms_pGlobalMutex );
867
868 if ( !a_pMemBlock )
869 {
870 a_pMemBlock = g_pMemory->m_pGlobalBlock;
871 }
872
873 a_rMemInfo.m_uiUnk3 = 28;
874 a_rMemInfo.m_uiUnk4 = 28;
875 a_rMemInfo.m_uiTotalSize = 0;
876 a_rMemInfo.m_uiLogicTotalSize = 0;
877 a_rMemInfo.m_uiLargestHole = 0;
878 a_rMemInfo.m_uiLargestProcess = 0;
879 a_rMemInfo.m_uiSmallestHole = 0;
880 a_rMemInfo.m_uiSmallestProcess = 0;
881 a_rMemInfo.m_uiTotalFree = 0;
882 a_rMemInfo.m_uiLogicTotalFree = 0;
883 a_rMemInfo.m_uiTotalUsed = 0;
884 a_rMemInfo.m_uiLogicTotalUsed = 0;
885 a_rMemInfo.m_iNumHoles = 0;
886 a_rMemInfo.m_iNumProcesses = 0;
887 a_rMemInfo.m_uiTotalSize = a_pMemBlock->m_uiTotalSize1;
888 a_rMemInfo.m_uiLogicTotalSize = a_pMemBlock->m_uiTotalSize1;
889 a_rMemInfo.m_uiSmallestProcess = -1;
890 a_rMemInfo.m_uiSmallestHole = -1;
891 a_rMemInfo.m_uiLargestProcess = 0;
892 a_rMemInfo.m_uiLargestHole = 0;
893
894 auto uiUnk = (TUINTPTR)a_pMemBlock->m_pFirstHole + ( -88 - (TUINTPTR)a_pMemBlock );
895 a_rMemInfo.m_uiUnk3 = uiUnk;
896 a_rMemInfo.m_uiUnk4 = uiUnk;
897
898 auto pHole = a_pMemBlock->m_pFirstHole;
899 TSIZE uiHoleSize = pHole->uiSize;
900
901 while ( TAlignNumDown( uiHoleSize ) != 0 )
902 {
903 a_rMemInfo.m_uiUnk3 += sizeof( MemNode ) - sizeof( void* );
904 uiHoleSize = TAlignNumDown( pHole->uiSize );
905
906 if ( ( pHole->uiSize & 1 ) == 0 )
907 {
908 a_rMemInfo.m_iNumHoles += 1;
909 a_rMemInfo.m_uiTotalFree += uiHoleSize;
910
911 if ( a_rMemInfo.m_uiLargestHole <= uiHoleSize && uiHoleSize != a_rMemInfo.m_uiLargestHole )
912 {
913 a_rMemInfo.m_uiLargestHole = uiHoleSize;
914 }
915
916 if ( uiHoleSize < a_rMemInfo.m_uiSmallestHole )
917 {
918 a_rMemInfo.m_uiSmallestHole = uiHoleSize;
919 }
920 }
921 else
922 {
923 a_rMemInfo.m_iNumProcesses += 1;
924 a_rMemInfo.m_uiTotalUsed += uiHoleSize;
925
926 if ( a_rMemInfo.m_uiLargestProcess <= uiHoleSize && uiHoleSize != a_rMemInfo.m_uiLargestProcess )
927 {
928 a_rMemInfo.m_uiLargestProcess = uiHoleSize;
929 }
930
931 if ( uiHoleSize < a_rMemInfo.m_uiSmallestProcess )
932 {
933 a_rMemInfo.m_uiSmallestProcess = uiHoleSize;
934 }
935 }
936
937 auto pOldHole = pHole;
938 pHole = (MemNode*)( (TUINTPTR)&pHole->pPrevHole + uiHoleSize );
939 uiHoleSize = pHole->uiSize;
940 }
941
942 a_rMemInfo.m_uiLogicTotalFree = a_rMemInfo.m_uiTotalFree;
943 a_rMemInfo.m_uiLogicTotalUsed = a_rMemInfo.m_uiTotalUsed + uiUnk;
944
945 if ( a_rMemInfo.m_uiSmallestHole == -1 )
946 {
947 a_rMemInfo.m_uiSmallestHole = 0;
948 }
949}

◆ Initialise()

TBOOL TMemory::Initialise ( TSIZE a_uiHeapSize,
TSIZE a_uiReservedSize,
TUINT a_uiUnused = 0 )
static

Initializes the memory system.

Parameters
a_uiHeapSizeSize of the heap
a_uiReservedSizeSize of reserved memory
a_uiUnusedUnused parameter
Returns
TRUE if initialization succeeded

This function:

  1. Creates the TMemory instance
  2. Initializes the global mutex
  3. Allocates the main memory block
  4. Sets up the global memory block

Definition at line 708 of file TMemory.cpp.

709{
710 auto tmemory = TSTATICCAST( TMemory, calloc( sizeof( TMemory ), 1 ) );
711 new ( tmemory ) TMemory();
712
713 tmemory->m_pMemory = TNULL;
714 tmemory->m_pGlobalBlock = TNULL;
715 tmemory->m_uiGlobalFlags = 0;
716 tmemory->m_Unknown2 = 0;
717
718 ms_pGlobalMutex = TSTATICCAST( TMutex, malloc( sizeof( TMutex ) ) );
719 new ( ms_pGlobalMutex ) TMutex();
720
721 tmemory->m_ReservedSize = a_uiReservedSize;
722 tmemory->m_TotalAllocatedSize = ( a_uiHeapSize == 0 ) ? 128 * 1024 * 1024 : a_uiHeapSize;
723 tmemory->m_MainBlockSize = tmemory->m_TotalAllocatedSize - a_uiReservedSize;
724 tmemory->m_pMemory = malloc( tmemory->m_TotalAllocatedSize );
725 tmemory->m_pGlobalBlock = tmemory->CreateMemBlockInPlace(
726 tmemory->m_pMemory,
727 tmemory->m_TotalAllocatedSize,
728 "Toshi"
729 );
730
731 return TTRUE;
732}
#define TSTATICCAST(POINTERTYPE, VALUE)
Definition Defines.h:69
TMemory()
Constructor for TMemory class Initializes the memory management system.
Definition TMemory.cpp:138

◆ MapSizeToFreeList()

TUINT TMemory::MapSizeToFreeList ( TSIZE a_uiSize)
static

Definition at line 767 of file TMemory.cpp.

768{
769 TFLOAT fSize = TFLOAT( TAlignNumUp( a_uiSize ) - 1 );
770 TUINT uiExponentSign = ( *(TINT*)&fSize ) >> 23;
771 TUINT uiResult = uiExponentSign - 127;
772
773 if ( uiResult & 1 )
774 uiResult = uiExponentSign - 126;
775
776 uiResult = uiResult >> 1;
777
778 if ( uiResult != 0 )
779 uiResult = uiResult - 1;
780
781 if ( uiResult >= TMEMORY_NUM_FREELISTS )
782 uiResult = TMEMORY_NUM_FREELISTS - 1;
783
784 return uiResult;
785}

◆ SetGlobalBlock()

TMemory::MemBlock * TMemory::SetGlobalBlock ( MemBlock * a_pMemBlock)

Sets the global memory block.

Parameters
a_pMemBlockNew global memory block
Returns
Pointer to the previous global memory block

Definition at line 793 of file TMemory.cpp.

794{
795 MemBlock* pOldMemBlock = m_pGlobalBlock;
796 m_pGlobalBlock = a_pMemBlock;
797 return pOldMemBlock;
798}

◆ SysAlloc()

void * TMemory::SysAlloc ( TSIZE a_uiSize)

Allocates memory from the system heap.

Parameters
a_uiSizeSize of memory to allocate
Returns
Pointer to allocated memory

Definition at line 13 of file TMemory_Win.cpp.

14{
15 void* pMem = GlobalAlloc( 64, a_uiSize );
16 TVALIDPTR( pMem );
17
18 return pMem;
19}
#define TVALIDPTR(PTR)
Definition Defines.h:139

◆ SysFree()

void TMemory::SysFree ( void * a_pMem)

Frees memory back to the system heap.

Parameters
a_pMemPointer to memory to free

Definition at line 21 of file TMemory_Win.cpp.

22{
23 TASSERT( TNULL != a_pMem );
24 GlobalFree( a_pMem );
25}

The documentation for this class was generated from the following files: