mirror of
https://github.com/ToyB-Chan/minimal-heap.git
synced 2026-07-13 21:51:16 +02:00
made all define configs configurable in runtime per heap
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
/* Version 1.6 */
|
/* Version 1.7 */
|
||||||
|
|
||||||
#ifndef __MINIMAL_HEAP_H__
|
#ifndef __MINIMAL_HEAP_H__
|
||||||
#define __MINIMAL_HEAP_H__
|
#define __MINIMAL_HEAP_H__
|
||||||
@@ -11,23 +11,7 @@
|
|||||||
#define MIHP_IMPLEMENTATION 0
|
#define MIHP_IMPLEMENTATION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE 0
|
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER 1
|
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM 2
|
|
||||||
|
|
||||||
/* Defines to be configured by the library user */
|
/* Defines to be configured by the library user */
|
||||||
#ifndef MIHP_HEAP_STRUCTURE_VALIDATION_TYPE
|
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIHP_MIN_TRAVERSELS_BEFORE_EXPANSION
|
|
||||||
#define MIHP_MIN_TRAVERSELS_BEFORE_EXPANSION 10000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIHP_MIN_EXPANSION_TRAVERSEL_RATIO_INT_PERCENT
|
|
||||||
#define MIHP_MIN_EXPANSION_TRAVERSEL_RATIO_INT_PERCENT 40
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef MIHP_ASSERT
|
#ifndef MIHP_ASSERT
|
||||||
#define MIHP_ASSERT(Condition) while(1) { if (Condition) break; *(volatile char*)(0x0) = 0; }
|
#define MIHP_ASSERT(Condition) while(1) { if (Condition) break; *(volatile char*)(0x0) = 0; }
|
||||||
#endif
|
#endif
|
||||||
@@ -40,27 +24,42 @@
|
|||||||
typedef void*(MIHP_PlatformReqeustMemoryFn)(const struct _MIHP_Heap* heap, size_t minRequestedSize, size_t* outActualSize);
|
typedef void*(MIHP_PlatformReqeustMemoryFn)(const struct _MIHP_Heap* heap, size_t minRequestedSize, size_t* outActualSize);
|
||||||
typedef bool (MIHP_PlatformFreeMemoryFn)(const struct _MIHP_Heap* heap, void* ptr, size_t actualSize);
|
typedef bool (MIHP_PlatformFreeMemoryFn)(const struct _MIHP_Heap* heap, void* ptr, size_t actualSize);
|
||||||
|
|
||||||
#define MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH 0
|
typedef enum _MIHP_HEAP_CORRUPTION_ERROR
|
||||||
#define MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH 1
|
{
|
||||||
#define MIHP_HEAP_CORRUPTION_TYPE_DOUBLE_FREE 2
|
MIHP_HCE_MemoryAreaChecksumMismatch = 0,
|
||||||
|
MIHP_HCE_SegmentChecksumMismatch = 1,
|
||||||
|
MIHP_HCE_DoubleFree = 2,
|
||||||
|
};
|
||||||
|
|
||||||
typedef void (MIHP_OnHeapCorruptionDetectedFn)(const struct _MIHP_Heap* heap, struct _MIHP_HeapCorruptionInfo corruptionInfo);
|
typedef void (MIHP_OnHeapCorruptionDetectedFn)(const struct _MIHP_Heap* heap, struct _MIHP_HeapCorruptionInfo corruptionInfo);
|
||||||
|
|
||||||
typedef void(MIHIP_LockHeapFn)(const struct _MIHP_Heap* heap, void* heapLock);
|
typedef void(MIHIP_LockHeapFn)(const struct _MIHP_Heap* heap, void* heapLock);
|
||||||
typedef void(MIHIP_UnlockHeapFn)(const struct _MIHP_Heap* heap, void* heapLock);
|
typedef void(MIHIP_UnlockHeapFn)(const struct _MIHP_Heap* heap, void* heapLock);
|
||||||
|
|
||||||
|
typedef enum _MIHP_HeapValidationMode
|
||||||
|
{
|
||||||
|
MIHP_HVM_None = 0,
|
||||||
|
MIHP_HVM_MagicNumber = 1,
|
||||||
|
MIHP_HVM_Checksum = 2
|
||||||
|
} MIHP_HeapValidationMode;
|
||||||
|
|
||||||
typedef struct _MIHP_HeapConfig
|
typedef struct _MIHP_HeapConfig
|
||||||
{
|
{
|
||||||
MIHP_PlatformReqeustMemoryFn* PlatformRequestMemoryFn; // Alignment must at least be alignment of size_t, outActualSize must at least be minRequestedSize
|
MIHP_PlatformReqeustMemoryFn* PlatformRequestMemoryFn; // Alignment must at least be alignment of size_t, outActualSize must at least be minRequestedSize
|
||||||
MIHP_PlatformFreeMemoryFn* PlatformFreeMemoryFn; // Can return false if the memory cannot be freed
|
MIHP_PlatformFreeMemoryFn* PlatformFreeMemoryFn; // Can return false if the memory cannot be freed
|
||||||
MIHP_OnHeapCorruptionDetectedFn* OnHeapCorruptionDetectedFn; // Can be NULL
|
MIHP_OnHeapCorruptionDetectedFn* OnHeapCorruptionDetectedFn; // Can be NULL
|
||||||
|
|
||||||
size_t MinimalMemoryAreaSize; // Must be a multiple of AllocationAlignment
|
size_t MinMemoryAreaSize; // Must be a multiple of AllocationAlignment
|
||||||
size_t MaximalMemoryAreaSize; // Must be a multiple of AllocationAlignment
|
size_t MaxMemoryAreaSize; // Must be a multiple of AllocationAlignment
|
||||||
|
|
||||||
|
size_t MinTotalTraversalsBeforeHeapExpansion; // Minimal amounts of traversals during allocation before considering expanding the heap
|
||||||
|
char MinHeapTraversalPercentToExpand; // Minimal integer percent of the heap traversed before expanding the heap
|
||||||
|
|
||||||
size_t AllocationAlignment; // Must be power of two and at least sizeof(size_t)
|
size_t AllocationAlignment; // Must be power of two and at least sizeof(size_t)
|
||||||
char AllocationInitialValue; // Initial value the returned blocks are to be filled with
|
char AllocationInitialValue; // Initial value the returned blocks are to be filled with
|
||||||
|
|
||||||
|
MIHP_HeapValidationMode HeapValidationMode;
|
||||||
|
|
||||||
void* HeapLock; // Does not need to be reentred safe, can be NULL to disable locking
|
void* HeapLock; // Does not need to be reentred safe, can be NULL to disable locking
|
||||||
MIHIP_LockHeapFn* LockHeapFn; // Can be NULL if HeapLock is NULL
|
MIHIP_LockHeapFn* LockHeapFn; // Can be NULL if HeapLock is NULL
|
||||||
MIHIP_LockHeapFn* UnlockHeapFn; // Can be NULL if HeapLock is NULL
|
MIHIP_LockHeapFn* UnlockHeapFn; // Can be NULL if HeapLock is NULL
|
||||||
@@ -124,6 +123,8 @@ typedef struct _MIHP_Heap
|
|||||||
} MIHP_Heap;
|
} MIHP_Heap;
|
||||||
|
|
||||||
/* API Interface */
|
/* API Interface */
|
||||||
|
MIHP_HeapConfig MIHP_MakeDefaultConfigPreset();
|
||||||
|
|
||||||
bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config);
|
bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config);
|
||||||
bool MIHP_IsHeapInitialized(const MIHP_Heap* heap);
|
bool MIHP_IsHeapInitialized(const MIHP_Heap* heap);
|
||||||
bool MIHP_UninitializeHeap(MIHP_Heap* heap, bool force);
|
bool MIHP_UninitializeHeap(MIHP_Heap* heap, bool force);
|
||||||
@@ -158,8 +159,8 @@ MIHP_HeapSegmentHeader* MIHP_GetSegmentHeaderPtr(MIHP_Heap* heap, void* payloadP
|
|||||||
size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size);
|
size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size);
|
||||||
|
|
||||||
uint32_t MIHP_HashMemoryRegion(const void* data, size_t size);
|
uint32_t MIHP_HashMemoryRegion(const void* data, size_t size);
|
||||||
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area);
|
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area);
|
||||||
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment);
|
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment);
|
||||||
|
|
||||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area);
|
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area);
|
||||||
void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment);
|
void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment);
|
||||||
|
|||||||
@@ -3,6 +3,24 @@
|
|||||||
|
|
||||||
#define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0)
|
#define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0)
|
||||||
|
|
||||||
|
MIHP_HeapConfig MIHP_MakeDefaultConfigPreset()
|
||||||
|
{
|
||||||
|
MIHP_HeapConfig cfg = { 0 };
|
||||||
|
|
||||||
|
cfg.MinMemoryAreaSize = 4096 * 32;
|
||||||
|
cfg.MaxMemoryAreaSize = 4096 * 4096 * 8;
|
||||||
|
|
||||||
|
cfg.MinTotalTraversalsBeforeHeapExpansion = 10'000;
|
||||||
|
cfg.MinHeapTraversalPercentToExpand = 80;
|
||||||
|
|
||||||
|
cfg.AllocationAlignment = 16;
|
||||||
|
cfg.AllocationInitialValue = 0xbe;
|
||||||
|
|
||||||
|
cfg.HeapValidationMode = MIHP_HVM_MagicNumber;
|
||||||
|
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config)
|
bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config)
|
||||||
{
|
{
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
@@ -17,16 +35,22 @@ bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config)
|
|||||||
if (config.PlatformFreeMemoryFn == NULL)
|
if (config.PlatformFreeMemoryFn == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (config.MinTotalTraversalsBeforeHeapExpansion < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (config.MinHeapTraversalPercentToExpand > 100)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (config.AllocationAlignment < sizeof(size_t))
|
if (config.AllocationAlignment < sizeof(size_t))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!MIHP_IS_PO2(config.AllocationAlignment))
|
if (!MIHP_IS_PO2(config.AllocationAlignment))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (config.MinimalMemoryAreaSize % config.AllocationAlignment != 0)
|
if (config.MinMemoryAreaSize % config.AllocationAlignment != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (config.MaximalMemoryAreaSize % config.AllocationAlignment != 0)
|
if (config.MaxMemoryAreaSize % config.AllocationAlignment != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (config.HeapLock != NULL)
|
if (config.HeapLock != NULL)
|
||||||
@@ -41,10 +65,10 @@ bool MIHP_InitializeHeap(MIHP_Heap* heap, MIHP_HeapConfig config)
|
|||||||
MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0);
|
MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0);
|
||||||
|
|
||||||
heap->Config = config;
|
heap->Config = config;
|
||||||
heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinimalMemoryAreaSize);
|
heap->FirstArea = MIHP_CreateHeapMemoryArea(heap, config.MinMemoryAreaSize);
|
||||||
heap->LastSuccessfulAllocationArea = heap->FirstArea;
|
heap->LastSuccessfulAllocationArea = heap->FirstArea;
|
||||||
|
|
||||||
heap->FirstArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap->FirstArea);
|
heap->FirstArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, heap->FirstArea);
|
||||||
return heap;
|
return heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +113,7 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
if (size == 0)
|
if (size == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (size > heap->Config.MaximalMemoryAreaSize)
|
if (size > heap->Config.MaxMemoryAreaSize)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
MIHP_LockHeap(heap);
|
MIHP_LockHeap(heap);
|
||||||
@@ -108,14 +132,14 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
if (currentArea->NumOccupiedSegments == currentArea->NumSegments)
|
if (currentArea->NumOccupiedSegments == currentArea->NumSegments)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
size_t numTraversalsPerArea = MIHP_MAX(100, MIHP_MIN_TRAVERSELS_BEFORE_EXPANSION * currentArea->NumSegments) / heap->Stats.NumTotalSegments;
|
size_t numTraversalsPerArea = MIHP_MAX(100, heap->Config.MinTotalTraversalsBeforeHeapExpansion * currentArea->NumSegments) / heap->Stats.NumTotalSegments;
|
||||||
size_t numTraversedAreaSegments = 0;
|
size_t numTraversedAreaSegments = 0;
|
||||||
|
|
||||||
MIHP_HeapSegmentHeader* nextSegment = currentArea->FirstSegment;
|
MIHP_HeapSegmentHeader* nextSegment = currentArea->FirstSegment;
|
||||||
while (nextSegment)
|
while (nextSegment)
|
||||||
{
|
{
|
||||||
if (numTraversedAreaSegments > numTraversalsPerArea)
|
if (numTraversedAreaSegments > numTraversalsPerArea)
|
||||||
if (numTraversedAreaSegments * 100 > currentArea->NumSegments * MIHP_MIN_EXPANSION_TRAVERSEL_RATIO_INT_PERCENT)
|
if (numTraversedAreaSegments * 100 > currentArea->NumSegments * heap->Config.MinHeapTraversalPercentToExpand)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
numTraversedAreaSegments++;
|
numTraversedAreaSegments++;
|
||||||
@@ -138,10 +162,10 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
targetSegment->OccupiedSize = size;
|
targetSegment->OccupiedSize = size;
|
||||||
targetSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(targetSegment);
|
targetSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, targetSegment);
|
||||||
|
|
||||||
currentArea->NumOccupiedSegments++;
|
currentArea->NumOccupiedSegments++;
|
||||||
currentArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(currentArea);
|
currentArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, currentArea);
|
||||||
|
|
||||||
heap->Stats.NumTotalOccupiedSegments++;
|
heap->Stats.NumTotalOccupiedSegments++;
|
||||||
heap->LastSuccessfulAllocationArea = currentArea;
|
heap->LastSuccessfulAllocationArea = currentArea;
|
||||||
@@ -160,7 +184,7 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
size_t newAreaSize = heap->Stats.TotalSize;
|
size_t newAreaSize = heap->Stats.TotalSize;
|
||||||
|
|
||||||
while (newAreaSize < size)
|
while (newAreaSize < size)
|
||||||
newAreaSize = MIHP_MIN(heap->Config.MaximalMemoryAreaSize, newAreaSize * 2);
|
newAreaSize = MIHP_MIN(heap->Config.MaxMemoryAreaSize, newAreaSize * 2);
|
||||||
|
|
||||||
MIHP_HeapMemoryAreaHeader* newArea = MIHP_CreateHeapMemoryArea(heap, newAreaSize);
|
MIHP_HeapMemoryAreaHeader* newArea = MIHP_CreateHeapMemoryArea(heap, newAreaSize);
|
||||||
if (newArea == NULL)
|
if (newArea == NULL)
|
||||||
@@ -171,11 +195,11 @@ void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
|||||||
|
|
||||||
newArea->NextArea = heap->FirstArea;
|
newArea->NextArea = heap->FirstArea;
|
||||||
heap->FirstArea->PreviousArea = newArea;
|
heap->FirstArea->PreviousArea = newArea;
|
||||||
heap->FirstArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap->FirstArea);
|
heap->FirstArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, heap->FirstArea);
|
||||||
|
|
||||||
heap->FirstArea = newArea;
|
heap->FirstArea = newArea;
|
||||||
heap->LastSuccessfulAllocationArea = newArea;
|
heap->LastSuccessfulAllocationArea = newArea;
|
||||||
newArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(newArea);
|
newArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, newArea);
|
||||||
|
|
||||||
MIHP_UnlockHeap(heap);
|
MIHP_UnlockHeap(heap);
|
||||||
return MIHP_Allocate(heap, size);
|
return MIHP_Allocate(heap, size);
|
||||||
@@ -211,7 +235,7 @@ void* MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize)
|
|||||||
{
|
{
|
||||||
MIHP_MEMSET((char*)ptr + segment->OccupiedSize, newSize - segment->OccupiedSize, heap->Config.AllocationInitialValue);
|
MIHP_MEMSET((char*)ptr + segment->OccupiedSize, newSize - segment->OccupiedSize, heap->Config.AllocationInitialValue);
|
||||||
segment->OccupiedSize = newSize;
|
segment->OccupiedSize = newSize;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
MIHP_UnlockHeap(heap);
|
MIHP_UnlockHeap(heap);
|
||||||
return ptr;
|
return ptr;
|
||||||
@@ -238,7 +262,7 @@ void* MIHP_Reallocate(MIHP_Heap* heap, void* ptr, size_t newSize)
|
|||||||
else if (newSize < segment->OccupiedSize)
|
else if (newSize < segment->OccupiedSize)
|
||||||
{
|
{
|
||||||
segment->OccupiedSize = newSize;
|
segment->OccupiedSize = newSize;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
size_t alignedNewSize = MIHP_GetHeapAlignedSize(heap, newSize);
|
size_t alignedNewSize = MIHP_GetHeapAlignedSize(heap, newSize);
|
||||||
if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + MIHP_GetMinimalPayloadSize(heap))
|
if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + MIHP_GetMinimalPayloadSize(heap))
|
||||||
@@ -281,7 +305,7 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr)
|
|||||||
if (segment->OccupiedSize == 0)
|
if (segment->OccupiedSize == 0)
|
||||||
{
|
{
|
||||||
MIHP_HeapCorruptionInfo corruptionInfo = {0};
|
MIHP_HeapCorruptionInfo corruptionInfo = {0};
|
||||||
corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_DOUBLE_FREE;
|
corruptionInfo.Type = MIHP_HCE_DoubleFree;
|
||||||
corruptionInfo.Ptr = ptr;
|
corruptionInfo.Ptr = ptr;
|
||||||
|
|
||||||
if (heap->Config.OnHeapCorruptionDetectedFn != NULL)
|
if (heap->Config.OnHeapCorruptionDetectedFn != NULL)
|
||||||
@@ -290,10 +314,10 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
segment->OccupiedSize = 0;
|
segment->OccupiedSize = 0;
|
||||||
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
segment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
|
|
||||||
area->NumOccupiedSegments--;
|
area->NumOccupiedSegments--;
|
||||||
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, area);
|
||||||
|
|
||||||
heap->Stats.NumTotalOccupiedSegments--;
|
heap->Stats.NumTotalOccupiedSegments--;
|
||||||
|
|
||||||
@@ -308,14 +332,14 @@ bool MIHP_Free(MIHP_Heap* heap, void* ptr)
|
|||||||
{
|
{
|
||||||
MIHP_ValidateHeapMemoryAreaHeader(heap, prevArea);
|
MIHP_ValidateHeapMemoryAreaHeader(heap, prevArea);
|
||||||
prevArea->NextArea = nextArea;
|
prevArea->NextArea = nextArea;
|
||||||
prevArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(prevArea);
|
prevArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, prevArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextArea)
|
if (nextArea)
|
||||||
{
|
{
|
||||||
MIHP_ValidateHeapMemoryAreaHeader(heap, nextArea);
|
MIHP_ValidateHeapMemoryAreaHeader(heap, nextArea);
|
||||||
nextArea->PreviousArea = prevArea;
|
nextArea->PreviousArea = prevArea;
|
||||||
nextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(nextArea);
|
nextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, nextArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heap->FirstArea == area)
|
if (heap->FirstArea == area)
|
||||||
@@ -367,10 +391,13 @@ bool MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb)
|
|||||||
if (sourceHeap->Config.AllocationAlignment != heapToAbsorb->Config.AllocationAlignment)
|
if (sourceHeap->Config.AllocationAlignment != heapToAbsorb->Config.AllocationAlignment)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sourceHeap->Config.MinimalMemoryAreaSize > heapToAbsorb->Config.MinimalMemoryAreaSize)
|
if (sourceHeap->Config.MinMemoryAreaSize > heapToAbsorb->Config.MinMemoryAreaSize)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (sourceHeap->Config.MaximalMemoryAreaSize < heapToAbsorb->Config.MaximalMemoryAreaSize)
|
if (sourceHeap->Config.MaxMemoryAreaSize < heapToAbsorb->Config.MaxMemoryAreaSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sourceHeap->Config.HeapValidationMode != heapToAbsorb->Config.HeapValidationMode)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MIHP_LockHeap(sourceHeap);
|
MIHP_LockHeap(sourceHeap);
|
||||||
@@ -399,8 +426,8 @@ bool MIHP_MergeHeaps(MIHP_Heap* sourceHeap, MIHP_Heap* heapToAbsorb)
|
|||||||
MIHP_UnlockHeap(heapToAbsorb);
|
MIHP_UnlockHeap(heapToAbsorb);
|
||||||
MIHP_MEMSET(heapToAbsorb, sizeof(MIHP_Heap), 0);
|
MIHP_MEMSET(heapToAbsorb, sizeof(MIHP_Heap), 0);
|
||||||
|
|
||||||
sourceEndArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceEndArea);
|
sourceEndArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea);
|
||||||
sourceEndArea->NextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceEndArea->NextArea);
|
sourceEndArea->NextArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(sourceHeap, sourceEndArea->NextArea);
|
||||||
MIHP_UnlockHeap(sourceHeap);
|
MIHP_UnlockHeap(sourceHeap);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -484,9 +511,9 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t req
|
|||||||
{
|
{
|
||||||
MIHP_ASSERT(heap);
|
MIHP_ASSERT(heap);
|
||||||
|
|
||||||
size_t effectiveSize = ((requestedSize + heap->Config.MinimalMemoryAreaSize - 1) / heap->Config.MinimalMemoryAreaSize) * heap->Config.MinimalMemoryAreaSize;
|
size_t effectiveSize = ((requestedSize + heap->Config.MinMemoryAreaSize - 1) / heap->Config.MinMemoryAreaSize) * heap->Config.MinMemoryAreaSize;
|
||||||
effectiveSize = MIHP_MAX(effectiveSize, heap->Config.MinimalMemoryAreaSize);
|
effectiveSize = MIHP_MAX(effectiveSize, heap->Config.MinMemoryAreaSize);
|
||||||
effectiveSize = MIHP_MIN(effectiveSize, heap->Config.MaximalMemoryAreaSize);
|
effectiveSize = MIHP_MIN(effectiveSize, heap->Config.MaxMemoryAreaSize);
|
||||||
|
|
||||||
size_t actualSize = 0;
|
size_t actualSize = 0;
|
||||||
MIHP_HeapMemoryAreaHeader* area = (MIHP_HeapMemoryAreaHeader*)heap->Config.PlatformRequestMemoryFn(heap, effectiveSize, &actualSize);
|
MIHP_HeapMemoryAreaHeader* area = (MIHP_HeapMemoryAreaHeader*)heap->Config.PlatformRequestMemoryFn(heap, effectiveSize, &actualSize);
|
||||||
@@ -502,7 +529,7 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t req
|
|||||||
|
|
||||||
size_t headerSize = MIHP_GetHeapAlignedSize(heap, sizeof(MIHP_HeapMemoryAreaHeader));
|
size_t headerSize = MIHP_GetHeapAlignedSize(heap, sizeof(MIHP_HeapMemoryAreaHeader));
|
||||||
area->FirstSegment = MIHP_InitializeHeapSegment(heap, area, (char*)area + headerSize, area->AreaSize - headerSize);
|
area->FirstSegment = MIHP_InitializeHeapSegment(heap, area, (char*)area + headerSize, area->AreaSize - headerSize);
|
||||||
area->FirstSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(area->FirstSegment);
|
area->FirstSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, area->FirstSegment);
|
||||||
|
|
||||||
heap->Stats.NumMemoryAreas++;
|
heap->Stats.NumMemoryAreas++;
|
||||||
heap->Stats.TotalSize += area->AreaSize;
|
heap->Stats.TotalSize += area->AreaSize;
|
||||||
@@ -544,7 +571,7 @@ MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_Heap* heap, MIHP_HeapMem
|
|||||||
segment->Checksum = ~0;
|
segment->Checksum = ~0;
|
||||||
|
|
||||||
area->NumSegments++;
|
area->NumSegments++;
|
||||||
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
area->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, area);
|
||||||
|
|
||||||
heap->Stats.NumTotalSegments++;
|
heap->Stats.NumTotalSegments++;
|
||||||
|
|
||||||
@@ -559,7 +586,7 @@ bool MIHP_UninitializeHeapSegment(MIHP_Heap* heap, MIHP_HeapSegmentHeader* segme
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
segment->OwningMemoryArea->NumSegments--;
|
segment->OwningMemoryArea->NumSegments--;
|
||||||
segment->OwningMemoryArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(segment->OwningMemoryArea);
|
segment->OwningMemoryArea->Checksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, segment->OwningMemoryArea);
|
||||||
heap->Stats.NumTotalSegments--;
|
heap->Stats.NumTotalSegments--;
|
||||||
|
|
||||||
MIHP_MEMSET(segment, sizeof(MIHP_HeapSegmentHeader), 0);
|
MIHP_MEMSET(segment, sizeof(MIHP_HeapSegmentHeader), 0);
|
||||||
@@ -592,13 +619,13 @@ bool MIHP_SplitHeapSegment(MIHP_Heap* heap, MIHP_HeapSegmentHeader* sourceSegmen
|
|||||||
{
|
{
|
||||||
MIHP_ValidateHeapSegmentHeader(heap, sourceSegment->NextSegment);
|
MIHP_ValidateHeapSegmentHeader(heap, sourceSegment->NextSegment);
|
||||||
sourceSegment->NextSegment->PreviousSegment = newSegment;
|
sourceSegment->NextSegment->PreviousSegment = newSegment;
|
||||||
sourceSegment->NextSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment->NextSegment);
|
sourceSegment->NextSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, sourceSegment->NextSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSegment->NextSegment = newSegment;
|
sourceSegment->NextSegment = newSegment;
|
||||||
|
|
||||||
newSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(newSegment);
|
newSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, newSegment);
|
||||||
sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment);
|
sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, sourceSegment);
|
||||||
|
|
||||||
*outNewSegment = newSegment;
|
*outNewSegment = newSegment;
|
||||||
return true;
|
return true;
|
||||||
@@ -619,13 +646,13 @@ bool MIHP_MergeHeapSegments(MIHP_Heap* heap, MIHP_HeapSegmentHeader* sourceSegme
|
|||||||
{
|
{
|
||||||
MIHP_ValidateHeapSegmentHeader(heap, sourceSegment->NextSegment);
|
MIHP_ValidateHeapSegmentHeader(heap, sourceSegment->NextSegment);
|
||||||
sourceSegment->NextSegment->PreviousSegment = sourceSegment;
|
sourceSegment->NextSegment->PreviousSegment = sourceSegment;
|
||||||
sourceSegment->NextSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment->NextSegment);
|
sourceSegment->NextSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, sourceSegment->NextSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSegment->SegmentSize += segmentToAbsorb->SegmentSize;
|
sourceSegment->SegmentSize += segmentToAbsorb->SegmentSize;
|
||||||
MIHP_UninitializeHeapSegment(heap, segmentToAbsorb);
|
MIHP_UninitializeHeapSegment(heap, segmentToAbsorb);
|
||||||
|
|
||||||
sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(sourceSegment);
|
sourceSegment->Checksum = MIHP_GenerateHeapSegmentChecksum(heap, sourceSegment);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -664,43 +691,34 @@ uint32_t MIHP_HashMemoryRegion(const void* data, size_t size)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_HeapMemoryAreaHeader* area)
|
uint32_t MIHP_GenerateHeapMemoryAreaChecksum(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area)
|
||||||
{
|
{
|
||||||
|
if (heap->Config.HeapValidationMode == MIHP_HVM_None)
|
||||||
|
return 0;
|
||||||
|
|
||||||
#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE
|
if (heap->Config.HeapValidationMode == MIHP_HVM_MagicNumber)
|
||||||
return 0;
|
return 0xAADEADAA;
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER
|
|
||||||
return 0xAADEADAA;
|
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
|
||||||
|
|
||||||
MIHP_ASSERT(area);
|
MIHP_ASSERT(area);
|
||||||
|
|
||||||
// Do not include the checksum itself into the new checksum
|
// Do not include the checksum itself into the new checksum
|
||||||
size_t size = offsetof(MIHP_HeapMemoryAreaHeader, Checksum);
|
size_t size = offsetof(MIHP_HeapMemoryAreaHeader, Checksum);
|
||||||
return MIHP_HashMemoryRegion(area, size);
|
return MIHP_HashMemoryRegion(area, size);
|
||||||
|
|
||||||
#else
|
|
||||||
#error "Invalid heap structure validation type"
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment)
|
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment)
|
||||||
{
|
{
|
||||||
#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE
|
if (heap->Config.HeapValidationMode == MIHP_HVM_None)
|
||||||
return 0;
|
return 0;
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER
|
|
||||||
return 0x55DEAD55;
|
if (heap->Config.HeapValidationMode == MIHP_HVM_MagicNumber)
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
return 0x55DEAD55;
|
||||||
|
|
||||||
MIHP_ASSERT(segment);
|
MIHP_ASSERT(segment);
|
||||||
|
|
||||||
// Do not include the checksum itself into the new checksum
|
// Do not include the checksum itself into the new checksum
|
||||||
size_t size = offsetof(MIHP_HeapSegmentHeader, Checksum);
|
size_t size = offsetof(MIHP_HeapSegmentHeader, Checksum);
|
||||||
return MIHP_HashMemoryRegion(segment, size);
|
return MIHP_HashMemoryRegion(segment, size);
|
||||||
|
|
||||||
#else
|
|
||||||
#error "Invalid heap structure validation type"
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area)
|
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area)
|
||||||
@@ -710,20 +728,20 @@ void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMem
|
|||||||
|
|
||||||
uint32_t newChecksum;
|
uint32_t newChecksum;
|
||||||
|
|
||||||
#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE
|
if (heap->Config.HeapValidationMode == MIHP_HVM_None)
|
||||||
return;
|
return;
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER
|
|
||||||
newChecksum = 0xAADEADAA;
|
if (heap->Config.HeapValidationMode == MIHP_HVM_MagicNumber)
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
newChecksum = 0xAADEADAA;
|
||||||
newChecksum = MIHP_GenerateHeapMemoryAreaChecksum(area);
|
else if (heap->Config.HeapValidationMode == MIHP_HVM_Checksum)
|
||||||
#else
|
newChecksum = MIHP_GenerateHeapMemoryAreaChecksum(heap, area);
|
||||||
#error "Invalid heap structure validation type"
|
else
|
||||||
#endif
|
MIHP_ASSERT(false);
|
||||||
|
|
||||||
if (area->Checksum != newChecksum)
|
if (area->Checksum != newChecksum)
|
||||||
{
|
{
|
||||||
MIHP_HeapCorruptionInfo corruptionInfo;
|
MIHP_HeapCorruptionInfo corruptionInfo;
|
||||||
corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_MEMORY_AREA_CHECKSUM_MISMATCH;
|
corruptionInfo.Type = MIHP_HCE_MemoryAreaChecksumMismatch;
|
||||||
corruptionInfo.Ptr = area;
|
corruptionInfo.Ptr = area;
|
||||||
corruptionInfo.ExpectedValue = area->Checksum;
|
corruptionInfo.ExpectedValue = area->Checksum;
|
||||||
corruptionInfo.ActualValue = newChecksum;
|
corruptionInfo.ActualValue = newChecksum;
|
||||||
@@ -739,20 +757,20 @@ void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmen
|
|||||||
|
|
||||||
uint32_t newChecksum;
|
uint32_t newChecksum;
|
||||||
|
|
||||||
#if MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_NONE
|
if (heap->Config.HeapValidationMode == MIHP_HVM_None)
|
||||||
return;
|
return;
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER
|
|
||||||
newChecksum = 0x55DEAD55;
|
if (heap->Config.HeapValidationMode == MIHP_HVM_MagicNumber)
|
||||||
#elif MIHP_HEAP_STRUCTURE_VALIDATION_TYPE == MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
newChecksum = 0x55DEAD55;
|
||||||
newChecksum = MIHP_GenerateHeapSegmentChecksum(segment);
|
else if (heap->Config.HeapValidationMode == MIHP_HVM_Checksum)
|
||||||
#else
|
newChecksum = MIHP_GenerateHeapSegmentChecksum(heap, segment);
|
||||||
#error "Invalid heap structure validation type"
|
else
|
||||||
#endif
|
MIHP_ASSERT(false);
|
||||||
|
|
||||||
if (segment->Checksum != newChecksum)
|
if (segment->Checksum != newChecksum)
|
||||||
{
|
{
|
||||||
MIHP_HeapCorruptionInfo corruptionInfo;
|
MIHP_HeapCorruptionInfo corruptionInfo;
|
||||||
corruptionInfo.Type = MIHP_HEAP_CORRUPTION_TYPE_SEGMENT_CHECKSUM_MISMATCH;
|
corruptionInfo.Type = MIHP_HCE_SegmentChecksumMismatch;
|
||||||
corruptionInfo.Ptr = segment;
|
corruptionInfo.Ptr = segment;
|
||||||
corruptionInfo.ExpectedValue = segment->Checksum;
|
corruptionInfo.ExpectedValue = segment->Checksum;
|
||||||
corruptionInfo.ActualValue = newChecksum;
|
corruptionInfo.ActualValue = newChecksum;
|
||||||
|
|||||||
@@ -32,16 +32,13 @@ void* myptrs[NUM_ALLOCATIONS] = { 0 };
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
MIHP_HeapConfig config = {0};
|
MIHP_HeapConfig config = MIHP_MakeDefaultConfigPreset();
|
||||||
|
|
||||||
config.PlatformRequestMemoryFn = RequestMemory;
|
config.PlatformRequestMemoryFn = RequestMemory;
|
||||||
config.PlatformFreeMemoryFn = FreeMemory;
|
config.PlatformFreeMemoryFn = FreeMemory;
|
||||||
config.OnHeapCorruptionDetectedFn = OnHeapCorruptionDetectedCallback;
|
config.OnHeapCorruptionDetectedFn = OnHeapCorruptionDetectedCallback;
|
||||||
|
|
||||||
config.AllocationInitialValue = 0xbe;
|
config.HeapValidationMode = MIHP_HVM_None;
|
||||||
config.AllocationAlignment = 16;
|
|
||||||
config.MinimalMemoryAreaSize = 4096 * 32;
|
|
||||||
config.MaximalMemoryAreaSize = 4096ull * 4096ull * 4096ull;
|
|
||||||
|
|
||||||
MIHP_Heap myHeap = { 0 };
|
MIHP_Heap myHeap = { 0 };
|
||||||
MIHP_InitializeHeap(&myHeap, config);
|
MIHP_InitializeHeap(&myHeap, config);
|
||||||
|
|||||||
Reference in New Issue
Block a user