mirror of
https://github.com/ToyB-Chan/minimal-heap.git
synced 2026-07-13 21:51:16 +02:00
fixed when compacting segment on realloc, the new segment not getting merged with the following empty segment
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
|
/* Version 1.2 */
|
||||||
|
|
||||||
/* Version 1.1 */
|
#ifndef __MINIMAL_HEAP_H__
|
||||||
|
#define __MINIMAL_HEAP_H__
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -13,9 +15,6 @@
|
|||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER 1
|
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_MAGIC_NUMBER 1
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM 2
|
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM 2
|
||||||
|
|
||||||
#ifndef __MINIMAL_HEAP_H__
|
|
||||||
#define __MINIMAL_HEAP_H__
|
|
||||||
|
|
||||||
/* Defines to be configured by the library user */
|
/* Defines to be configured by the library user */
|
||||||
#ifndef MIHP_HEAP_STRUCTURE_VALIDATION_TYPE
|
#ifndef MIHP_HEAP_STRUCTURE_VALIDATION_TYPE
|
||||||
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
#define MIHP_HEAP_STRUCTURE_VALIDATION_TYPE MIHP_HEAP_STRUCTURE_VALIDATION_TYPE_CHECKSUM
|
||||||
@@ -72,7 +71,7 @@ typedef struct _MIHP_HeapMemoryAreaHeader
|
|||||||
struct _MIHP_HeapMemoryAreaHeader* NextArea;
|
struct _MIHP_HeapMemoryAreaHeader* NextArea;
|
||||||
struct _MIHP_HeapMemoryAreaHeader* PreviousArea;
|
struct _MIHP_HeapMemoryAreaHeader* PreviousArea;
|
||||||
|
|
||||||
struct _MIHP_HeapInfo* OwningHeap;
|
struct _MIHP_Heap* OwningHeap;
|
||||||
struct _MIHP_HeapSegmentHeader* FirstSegment;
|
struct _MIHP_HeapSegmentHeader* FirstSegment;
|
||||||
|
|
||||||
|
|
||||||
@@ -97,14 +96,14 @@ typedef struct _MIHP_HeapSegmentHeader
|
|||||||
|
|
||||||
typedef struct _MIHP_HeapCorruptionInfo
|
typedef struct _MIHP_HeapCorruptionInfo
|
||||||
{
|
{
|
||||||
const struct _MIHP_HeapInfo* Heap;
|
const struct _MIHP_Heap* Heap;
|
||||||
uint8_t Type;
|
uint8_t Type;
|
||||||
const void* Ptr;
|
const void* Ptr;
|
||||||
uint32_t ExpectedValue;
|
uint32_t ExpectedValue;
|
||||||
uint32_t ActualValue;
|
uint32_t ActualValue;
|
||||||
} MIHP_HeapCorruptionInfo;
|
} MIHP_HeapCorruptionInfo;
|
||||||
|
|
||||||
typedef struct _MIHP_HeapInfo
|
typedef struct _MIHP_Heap
|
||||||
{
|
{
|
||||||
MIHP_HeapConfig Config;
|
MIHP_HeapConfig Config;
|
||||||
MIHP_HeapStats Stats;
|
MIHP_HeapStats Stats;
|
||||||
@@ -112,23 +111,23 @@ typedef struct _MIHP_HeapInfo
|
|||||||
MIHP_HeapMemoryAreaHeader* LastSuccessfulAllocationArea;
|
MIHP_HeapMemoryAreaHeader* LastSuccessfulAllocationArea;
|
||||||
|
|
||||||
MIHP_HEAP_LOCK_TYPE HeapLock;
|
MIHP_HEAP_LOCK_TYPE HeapLock;
|
||||||
} MIHP_HeapInfo;
|
} MIHP_Heap;
|
||||||
|
|
||||||
/* API Interface */
|
/* API Interface */
|
||||||
MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config);
|
MIHP_Heap* MIHP_CreateHeap(MIHP_HeapConfig config);
|
||||||
bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force);
|
bool MIHP_DestroyHeap(MIHP_Heap* heap, bool force);
|
||||||
void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size);
|
void* MIHP_Allocate(MIHP_Heap* heap, size_t size);
|
||||||
void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize);
|
void* MIHP_Realloc(MIHP_Heap* heap, void* ptr, size_t newSize);
|
||||||
bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr);
|
bool MIHP_Free(MIHP_Heap* heap, void* ptr);
|
||||||
|
|
||||||
bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr);
|
bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr);
|
||||||
size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr);
|
size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr);
|
||||||
void MIHP_ValidateHeap(MIHP_HeapInfo* heap);
|
void MIHP_ValidateHeap(MIHP_Heap* heap);
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
/* Internals */
|
/* Internals */
|
||||||
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize);
|
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t requestedSize);
|
||||||
bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* area);
|
bool MIHP_DestroyHeapMemoryArea(MIHP_Heap* heap, MIHP_HeapMemoryAreaHeader* area);
|
||||||
|
|
||||||
MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t size);
|
MIHP_HeapSegmentHeader* MIHP_InitializeHeapSegment(MIHP_HeapMemoryAreaHeader* area, void* segmentStart, size_t size);
|
||||||
bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment);
|
bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment);
|
||||||
@@ -136,14 +135,14 @@ bool MIHP_UninitializeHeapSegment(MIHP_HeapSegmentHeader* segment);
|
|||||||
bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** outNewSegment);
|
bool MIHP_SplitHeapSegment(MIHP_HeapSegmentHeader* sourceSegment, size_t newSegmentSize, MIHP_HeapSegmentHeader** outNewSegment);
|
||||||
bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb);
|
bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegmentHeader* segmentToAbsorb);
|
||||||
|
|
||||||
size_t MIHP_GetHeapAlignedSize(const MIHP_HeapInfo* 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_HeapMemoryAreaHeader* area);
|
||||||
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment);
|
uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment);
|
||||||
|
|
||||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area);
|
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area);
|
||||||
void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment);
|
void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment);
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0)
|
#define MIHP_IS_PO2(Val) (Val != 0 && (Val & (Val - 1)) == 0)
|
||||||
|
|
||||||
MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config)
|
MIHP_Heap* MIHP_CreateHeap(MIHP_HeapConfig config)
|
||||||
{
|
{
|
||||||
if (config.AllocationAlignment < sizeof(size_t))
|
if (config.AllocationAlignment < sizeof(size_t))
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -13,11 +13,11 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config)
|
|||||||
if (!MIHP_IS_PO2(config.AllocationAlignment))
|
if (!MIHP_IS_PO2(config.AllocationAlignment))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
MIHP_HeapInfo* heap = (MIHP_HeapInfo*)MIHP_PlatformRequestMemory(sizeof(MIHP_HeapInfo));
|
MIHP_Heap* heap = (MIHP_Heap*)MIHP_PlatformRequestMemory(sizeof(MIHP_Heap));
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
MIHP_MEMSET(heap, sizeof(MIHP_HeapInfo), 0);
|
MIHP_MEMSET(heap, sizeof(MIHP_Heap), 0);
|
||||||
|
|
||||||
heap->Config = config;
|
heap->Config = config;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config)
|
|||||||
heap->LastSuccessfulAllocationArea = heap->FirstArea;
|
heap->LastSuccessfulAllocationArea = heap->FirstArea;
|
||||||
if (heap->FirstArea == NULL)
|
if (heap->FirstArea == NULL)
|
||||||
{
|
{
|
||||||
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo));
|
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ MIHP_HeapInfo* MIHP_CreateHeap(MIHP_HeapConfig config)
|
|||||||
return heap;
|
return heap;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force)
|
bool MIHP_DestroyHeap(MIHP_Heap* heap, bool force)
|
||||||
{
|
{
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -52,11 +52,11 @@ bool MIHP_DestroyHeap(MIHP_HeapInfo* heap, bool force)
|
|||||||
MIHP_DestroyHeapMemoryArea(heap, currentArea);
|
MIHP_DestroyHeapMemoryArea(heap, currentArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_HeapInfo));
|
MIHP_PlatformFreeMemory(heap, sizeof(MIHP_Heap));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size)
|
void* MIHP_Allocate(MIHP_Heap* heap, size_t size)
|
||||||
{
|
{
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -152,7 +152,7 @@ void* MIHP_Allocate(MIHP_HeapInfo* heap, size_t size)
|
|||||||
return MIHP_Allocate(heap, size);
|
return MIHP_Allocate(heap, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize)
|
void* MIHP_Realloc(MIHP_Heap* heap, void* ptr, size_t newSize)
|
||||||
{
|
{
|
||||||
if (newSize == 0)
|
if (newSize == 0)
|
||||||
{
|
{
|
||||||
@@ -216,7 +216,11 @@ void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize)
|
|||||||
if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + minimumPayloadSize)
|
if (segment->SegmentSize > 2 * segmentHeaderSize + alignedNewSize + minimumPayloadSize)
|
||||||
{
|
{
|
||||||
size_t newSplitSegmentSize = segment->SegmentSize - segmentHeaderSize - alignedNewSize;
|
size_t newSplitSegmentSize = segment->SegmentSize - segmentHeaderSize - alignedNewSize;
|
||||||
MIHP_SplitHeapSegment(segment, newSplitSegmentSize, NULL);
|
|
||||||
|
MIHP_HeapSegmentHeader* newSpittedSegment = NULL;
|
||||||
|
MIHP_SplitHeapSegment(segment, newSplitSegmentSize, &newSpittedSegment);
|
||||||
|
if (newSpittedSegment && newSpittedSegment->NextSegment)
|
||||||
|
MIHP_MergeHeapSegments(newSpittedSegment, newSpittedSegment->NextSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
MIHP_UNLOCK_HEAP(&heap->HeapLock);
|
MIHP_UNLOCK_HEAP(&heap->HeapLock);
|
||||||
@@ -227,7 +231,7 @@ void* MIHP_Realloc(MIHP_HeapInfo* heap, void* ptr, size_t newSize)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr)
|
bool MIHP_Free(MIHP_Heap* heap, void* ptr)
|
||||||
{
|
{
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -304,7 +308,7 @@ bool MIHP_Free(MIHP_HeapInfo* heap, void* ptr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr)
|
bool MIHP_IsPointerInHeap(MIHP_Heap* heap, void* ptr)
|
||||||
{
|
{
|
||||||
if (heap == NULL)
|
if (heap == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -333,7 +337,7 @@ bool MIHP_IsPointerInHeap(MIHP_HeapInfo* heap, void* ptr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr)
|
size_t MIHP_GetPtrAllocationSize(MIHP_Heap* heap, void* ptr)
|
||||||
{
|
{
|
||||||
if (!MIHP_IsPointerInHeap(heap, ptr))
|
if (!MIHP_IsPointerInHeap(heap, ptr))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -347,7 +351,7 @@ size_t MIHP_GetPtrAllocationSize(MIHP_HeapInfo* heap, void* ptr)
|
|||||||
return segment->OccupiedSize;
|
return segment->OccupiedSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIHP_ValidateHeap(MIHP_HeapInfo* heap)
|
void MIHP_ValidateHeap(MIHP_Heap* heap)
|
||||||
{
|
{
|
||||||
MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea;
|
MIHP_HeapMemoryAreaHeader* nextArea = heap->FirstArea;
|
||||||
while (nextArea)
|
while (nextArea)
|
||||||
@@ -366,7 +370,7 @@ void MIHP_ValidateHeap(MIHP_HeapInfo* heap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t requestedSize)
|
MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_Heap* heap, size_t requestedSize)
|
||||||
{
|
{
|
||||||
MIHP_ASSERT(heap);
|
MIHP_ASSERT(heap);
|
||||||
|
|
||||||
@@ -394,7 +398,7 @@ MIHP_HeapMemoryAreaHeader* MIHP_CreateHeapMemoryArea(MIHP_HeapInfo* heap, size_t
|
|||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MIHP_DestroyHeapMemoryArea(MIHP_HeapInfo* heap, MIHP_HeapMemoryAreaHeader* memoryArea)
|
bool MIHP_DestroyHeapMemoryArea(MIHP_Heap* heap, MIHP_HeapMemoryAreaHeader* memoryArea)
|
||||||
{
|
{
|
||||||
MIHP_ASSERT(heap);
|
MIHP_ASSERT(heap);
|
||||||
MIHP_ASSERT(memoryArea);
|
MIHP_ASSERT(memoryArea);
|
||||||
@@ -516,7 +520,7 @@ bool MIHP_MergeHeapSegments(MIHP_HeapSegmentHeader* sourceSegment, MIHP_HeapSegm
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MIHP_GetHeapAlignedSize(const MIHP_HeapInfo* heap, size_t size)
|
size_t MIHP_GetHeapAlignedSize(const MIHP_Heap* heap, size_t size)
|
||||||
{
|
{
|
||||||
return (size + (heap->Config.AllocationAlignment - 1)) & ~(heap->Config.AllocationAlignment - 1);
|
return (size + (heap->Config.AllocationAlignment - 1)) & ~(heap->Config.AllocationAlignment - 1);
|
||||||
}
|
}
|
||||||
@@ -573,7 +577,7 @@ uint32_t MIHP_GenerateHeapSegmentChecksum(const MIHP_HeapSegmentHeader* segment)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_HeapMemoryAreaHeader* area)
|
void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_Heap* heap, const MIHP_HeapMemoryAreaHeader* area)
|
||||||
{
|
{
|
||||||
uint32_t newChecksum;
|
uint32_t newChecksum;
|
||||||
|
|
||||||
@@ -600,7 +604,7 @@ void MIHP_ValidateHeapMemoryAreaHeader(const MIHP_HeapInfo* heap, const MIHP_Hea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MIHP_ValidateHeapSegmentHeader(const MIHP_HeapInfo* heap, const MIHP_HeapSegmentHeader* segment)
|
void MIHP_ValidateHeapSegmentHeader(const MIHP_Heap* heap, const MIHP_HeapSegmentHeader* segment)
|
||||||
{
|
{
|
||||||
uint32_t newChecksum;
|
uint32_t newChecksum;
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ int main()
|
|||||||
config.AllocationAlignment = 16;
|
config.AllocationAlignment = 16;
|
||||||
config.MinimalMemoryAreaSize = 4096 * 32;
|
config.MinimalMemoryAreaSize = 4096 * 32;
|
||||||
config.MaximalMemoryAreaSize = 4096ull * 4096ull * 4096ull;
|
config.MaximalMemoryAreaSize = 4096ull * 4096ull * 4096ull;
|
||||||
MIHP_HeapInfo* myHeap = MIHP_CreateHeap(config);
|
MIHP_Heap* myHeap = MIHP_CreateHeap(config);
|
||||||
|
|
||||||
for (int i = 0; i < NUM_ALLOCATIONS; i++)
|
for (int i = 0; i < NUM_ALLOCATIONS; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user