boomp
unknown
plain_text
a year ago
10 kB
8
Indexable
#define GSCVSID "$Header: /home/cvs/ficc/liberty/src/kool_ade/src/heap.c,v 1.44 2020/09/02 03:38:53 keyalm Exp $"
/****************************************************************
**
** heap.c
**
** Copyright 1993 - Goldman Sachs
**
** $Log: heap.c,v $
** Revision 1.44 2020/09/02 03:38:53 keyalm
** IS:6010-5787726 improve documentation of some core stuff
**
** Revision 1.43 2019/08/12 10:52:46 sharps
** IS:6010-4718773 Include cleanup. Prefer uint8_t to unsigned char. Predicate use of roundUp on REVERT_KOOL_ADE_HEAP_ROUND_UP
**
** Revision 1.42 2019/08/11 23:43:29 sharps
** IS:6010-4718773 Modernize. Fix walk. GSHeapGetAll only returns valid heaps
**
** Revision 1.41 2012/03/16 15:55:23 trifov
** IS:6012-200334 fixing sign conversion warnings
**
** Revision 1.40 2012/01/09 16:00:09 madsej
** IS:6012-200334 more 64 bit fixes (including hash sorting fix)
**
** Revision 1.39 2010/06/01 11:47:45 keatlj
** IS:6012-93680 show kool_ade on the heap
**
** Revision 1.38 2010/05/06 13:23:19 uschoj
** IS:6012-88940 Move heap.h to kool_ade dir to make gcc4 happy
**
** Revision 1.37 2009/05/05 11:16:32 uschoj
** IS:6012-37805 Win64 changes
**
** Revision 1.36 2007/08/09 20:24:53 madsej
** IS:1706 debug heap bad
**
** Revision 1.35 2007/03/24 15:00:33 goodfj
** IS:21989 Fix namespace/stl macros (review & prodver at will)
**
** Revision 1.34 2006/08/17 13:08:43 uschoj
** Backout 1.24
**
****************************************************************/
#define BUILDING_KOOL_ADE
// ficc/portable/src/portable
#include <portable.h>
// ficc/liberty/src/kool_ade
#include <kool_ade/heap.h>
#include <cstdlib> // getenv, calloc, malloc, free
#include <cstring> // memset
#include <algorithm> // std::find< InputIterator, T >
#include <vector> // std::vector< T >
#include <stdint.h> // intptr_t, uint8_t
#include <strings.h> // strcasecmp
#include <vccrtdbg.h>
static std::vector< HEAP* > s_heaps;
std::vector< HEAP* > const& GSHeapGetAll(
)
{
return s_heaps;
}
namespace {
inline size_t roundUp( size_t const size, size_t const unit )
{
if( size_t const rem = size % unit )
return size + ( unit - rem );
return size;
};
} // namespace
/****************************************************************
** Routine: GSHeapCreate
** Returns: New HEAP if created without error
** nullptr if HEAP couldn't be created
** Action : Create a new heap
****************************************************************/
HEAP* GSHeapCreate(
char const* Name, // Name of the heap
size_t ElementSize, // Size of elements to allocate from the heap
size_t BlockElements // Number of elements/large block
)
{
HEAP* const Heap = static_cast< HEAP* >( calloc( 1, sizeof( HEAP ) ) );
if( Heap )
{
Heap->Name = Name;
Heap->ElementSize = ElementSize;
static char const* const s_revertValue = getenv( "REVERT_KOOL_ADE_HEAP_ROUND_UP" );
static bool const s_revert = s_revertValue && strcasecmp( s_revertValue, "true" ) == 0;
if( s_revert )
Heap->ElementAllocSize = sizeof( void* ) * ( ( ElementSize + sizeof( void* ) - 1 ) / sizeof( void* ) );
else
Heap->ElementAllocSize = roundUp( ElementSize, sizeof( void* ) );
if( !BlockElements )
BlockElements = HEAP_DEFAULT_BLOCK_ELEMENTS;
Heap->BlockSize = sizeof( HEAP_BLOCK ) + ( Heap->ElementAllocSize * BlockElements );
s_heaps.push_back( Heap );
}
return Heap;
}
/****************************************************************
** Routine: GSHeapDestroy
** Returns: None
** Action : Destroy a heap
****************************************************************/
void GSHeapDestroy(
HEAP* Heap
)
{
while( Heap->BlockList )
{
HEAP_BLOCK* const HeapBlock = Heap->BlockList;
Heap->BlockList = HeapBlock->Next;
free( HeapBlock );
}
free( Heap );
std::vector< HEAP* >::iterator it = std::find( s_heaps.begin(), s_heaps.end(), Heap );
if( it != s_heaps.end() )
s_heaps.erase( it );
}
/****************************************************************
** Routine: GSHeapStatistics
** Returns: None
** Action : Return statistics about a heap
****************************************************************/
void GSHeapStatistics(
HEAP* Heap,
HEAP_STATS* HeapStats
)
{
memset( HeapStats, 0, sizeof( *HeapStats ) );
for( HEAP_BLOCK const* HeapBlock = Heap->BlockList; HeapBlock; HeapBlock = HeapBlock->Next )
{
HeapStats->BlockCount++;
HeapStats->TotalMemory += HeapBlock->Size;
HeapStats->TotalElementCount += ( HeapBlock->Size - sizeof( HEAP_BLOCK ) ) / Heap->ElementAllocSize;
}
for( HEAP_ELEMENT const* HeapElement = Heap->FreeElementList; HeapElement; HeapElement = HeapElement->Next )
HeapStats->FreeElementCount++;
HeapStats->FreeElementCount += static_cast< size_t >( Heap->BlockEnd - Heap->BlockPtr ) / Heap->ElementAllocSize;
HeapStats->FreeMemory = HeapStats->FreeElementCount * Heap->ElementAllocSize;
HeapStats->UsedMemory = HeapStats->TotalMemory - HeapStats->FreeMemory;
HeapStats->UsedElementCount = HeapStats->TotalElementCount - HeapStats->FreeElementCount;
}
/****************************************************************
** Routine: GSHeapMalloc
** Returns: Piece of memory or nullptr if error
** Action : Malloc a piece of memory from a heap
****************************************************************/
void* GSHeapMalloc(
HEAP* Heap
)
{
if( Heap->ElementSize == 0 )
return CC_NULLPTR;
HEAP_ELEMENT* HeapElement;
if( Heap->FreeElementList )
{
HeapElement = Heap->FreeElementList;
Heap->FreeElementList = HeapElement->Next;
}
else if( Heap->BlockPtr && Heap->BlockPtr < Heap->BlockEnd )
{
HeapElement = reinterpret_cast< HEAP_ELEMENT* >( Heap->BlockPtr );
Heap->BlockPtr += Heap->ElementAllocSize;
}
else if( ( Heap->BlockPtr = static_cast< uint8_t* >( malloc( Heap->BlockSize ) ) ) )
{
Heap->BlockEnd = Heap->BlockPtr + Heap->BlockSize;
HEAP_BLOCK* const HeapBlock = reinterpret_cast< HEAP_BLOCK* >( Heap->BlockPtr );
HeapBlock->Size = Heap->BlockSize;
HeapBlock->Next = Heap->BlockList;
Heap->BlockList = HeapBlock;
Heap->BlockPtr += sizeof( HEAP_BLOCK );
HeapElement = reinterpret_cast< HEAP_ELEMENT* >( Heap->BlockPtr );
Heap->BlockPtr += Heap->ElementAllocSize;
}
else
return CC_NULLPTR;
return HeapElement;
}
/****************************************************************
** Routine: GSHeapCalloc
** Returns: Piece of memory or nullptr if error
** Action : Calloc a piece of memory from a heap. The size of
** the memory is determined by the heap being used.
****************************************************************/
void* GSHeapCalloc(
HEAP* Heap
)
{
if( Heap->ElementSize == 0 )
return CC_NULLPTR;
HEAP_ELEMENT* HeapElement;
if( Heap->FreeElementList )
{
HeapElement = Heap->FreeElementList;
Heap->FreeElementList = HeapElement->Next;
}
else if( Heap->BlockPtr && Heap->BlockPtr < Heap->BlockEnd )
{
HeapElement = reinterpret_cast< HEAP_ELEMENT* >( Heap->BlockPtr );
Heap->BlockPtr += Heap->ElementAllocSize;
}
else if( ( Heap->BlockPtr = static_cast< uint8_t* >( malloc( Heap->BlockSize ) ) ) )
{
Heap->BlockEnd = Heap->BlockPtr + Heap->BlockSize;
HEAP_BLOCK* const HeapBlock = reinterpret_cast< HEAP_BLOCK* >( Heap->BlockPtr );
HeapBlock->Size = Heap->BlockSize;
HeapBlock->Next = Heap->BlockList;
Heap->BlockList = HeapBlock;
Heap->BlockPtr += sizeof( HEAP_BLOCK );
HeapElement = reinterpret_cast< HEAP_ELEMENT* >( Heap->BlockPtr );
Heap->BlockPtr += Heap->ElementAllocSize;
}
else
return CC_NULLPTR;
memset( HeapElement, 0, Heap->ElementAllocSize );
return HeapElement;
}
/****************************************************************
** Routine: GSHeapFree
** Returns: None
** Action : Free a piece of memory allocated from a heap
****************************************************************/
void GSHeapFree(
HEAP* Heap,
void* Element
)
{ /**
* Premise of this seems to be
* a) Element must be a previously GsHeapMalloc/GsHeapCalloc-ed thing
* b) We ensured that ElementSize can at least hold a ptr during allocation
* c) Since it is being free-d it's value doesnt matter and we can overwrite it partially to store the Next ptr
* d) Since the element was previously malloc-ed/calloc-ed , the alignment is good enough to store a ptr.
* ( malloc/calloc returns memory suitably aligned for any kind of fundamental type )
*/
if( Element )
{
static_cast< HEAP_ELEMENT* >( Element )->Next = Heap->FreeElementList;
Heap->FreeElementList = static_cast< HEAP_ELEMENT* >( Element );
}
}
/****************************************************************
** Routine: GSHeapWalk::GSHeapWalk
** Returns:
** Action :
****************************************************************/
GSHeapWalk::GSHeapWalk(
HEAP* heap
)
: m_heap( heap ), m_free_set( 0, 1 )
{
// run through free block list and enumerate all free blocks so we can tell while walking which ones are free
for( HEAP_ELEMENT const* el = m_heap->FreeElementList; el; el = el->Next )
m_free_set.insert( reinterpret_cast< intptr_t >( el ) );
}
/****************************************************************
** Routine: GSHeapWalk::walk
** Returns:
** Action :
****************************************************************/
bool GSHeapWalk::walk(
)
{
free_set_t::iterator const end_it = m_free_set.end();
for( HEAP_BLOCK* HeapBlock = m_heap->BlockList; HeapBlock; HeapBlock = HeapBlock->Next )
{
uint8_t const* const BlockEnd = reinterpret_cast< uint8_t* >( HeapBlock ) + m_heap->BlockSize;
for(
unsigned char* Elem = reinterpret_cast< uint8_t* >( HeapBlock ) + sizeof( HEAP_BLOCK );
Elem != reinterpret_cast< uint8_t* >( m_heap->BlockPtr ) && Elem < BlockEnd;
Elem += m_heap->ElementAllocSize
)
if( m_free_set.find( reinterpret_cast< intptr_t >( Elem ) ) == end_it )
{
if( !( *this )( Elem ) )
return false;
}
}
return true;
}
Editor is loading...
Leave a Comment