Centralize memory ops via MemoryUtility, add VM support
Refactor all memory allocation/deallocation to use MemoryUtility, replacing direct calls with unified methods. Introduce cross-platform virtual memory management (Mmap, Munmap, Decommit, Recommit). Switch to NativeMemory for standard allocations. Enhance FreeList with global free buckets and thread safety. Standardize alignment/size calculations. Remove global usings for memory utils. Bump version to 1.6.24. Includes minor cleanups and improved docs.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#if MHP_ENABLE_SAFETY_CHECKS
|
||||
using Misaki.HighPerformance.Collections;
|
||||
#endif
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -101,7 +102,7 @@ public static unsafe class AllocationManager
|
||||
|
||||
private static void* Allocate(void* _, nuint size, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var ptr = AlignedAlloc(size, alignment);
|
||||
var ptr = MemoryUtility.AlignedAlloc(size, alignment);
|
||||
if (ptr == null)
|
||||
{
|
||||
return null;
|
||||
@@ -109,7 +110,7 @@ public static unsafe class AllocationManager
|
||||
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(ptr, size);
|
||||
MemoryUtility.MemClear(ptr, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -117,7 +118,7 @@ public static unsafe class AllocationManager
|
||||
|
||||
private static void* Reallocate(void* _, void* ptr, nuint oldSize, nuint newSize, nuint alignment, AllocationOption allocationOption)
|
||||
{
|
||||
var newPtr = AlignedRealloc(ptr, newSize, alignment);
|
||||
var newPtr = MemoryUtility.AlignedRealloc(ptr, newSize, alignment);
|
||||
if (newPtr == null)
|
||||
{
|
||||
return null;
|
||||
@@ -127,7 +128,7 @@ public static unsafe class AllocationManager
|
||||
{
|
||||
var offset = (byte*)newPtr + oldSize;
|
||||
var clearSize = newSize - oldSize;
|
||||
MemClear(offset, clearSize);
|
||||
MemoryUtility.MemClear(offset, clearSize);
|
||||
}
|
||||
|
||||
return newPtr;
|
||||
@@ -135,7 +136,7 @@ public static unsafe class AllocationManager
|
||||
|
||||
private static void Free(void* _, void* ptr)
|
||||
{
|
||||
AlignedFree(ptr);
|
||||
MemoryUtility.AlignedFree(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +265,7 @@ public static unsafe class AllocationManager
|
||||
|
||||
var spanDesc = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref desc, 1));
|
||||
var spanDefault = MemoryMarshal.AsBytes(MemoryMarshal.CreateSpan(ref defaultDesc, 1));
|
||||
ReplaceIfZeros(spanDesc, spanDefault);
|
||||
MemoryUtility.ReplaceIfZeros(spanDesc, spanDefault);
|
||||
|
||||
s_arenaAllocator = new MemoryPool<VirtualArena, VirtualArena.CreationOptions>(new VirtualArena.CreationOptions
|
||||
{
|
||||
@@ -277,10 +278,10 @@ public static unsafe class AllocationManager
|
||||
chunkSize = desc.FreeListChunkSize
|
||||
});
|
||||
|
||||
s_pHeapAllocator = (HeapAllocator*)Malloc((nuint)sizeof(HeapAllocator));
|
||||
s_pHeapAllocator = (HeapAllocator*)NativeMemory.Alloc((nuint)sizeof(HeapAllocator));
|
||||
s_pHeapAllocator->Init();
|
||||
|
||||
s_pTLSFAllocator = (TLSFAllocator*)Malloc((nuint)sizeof(TLSFAllocator));
|
||||
s_pTLSFAllocator = (TLSFAllocator*)NativeMemory.Alloc((nuint)sizeof(TLSFAllocator));
|
||||
s_pTLSFAllocator->Init(desc.TLSFAlignment, desc.TLSFInitialChunkSize);
|
||||
|
||||
s_threadLocalStackSize = desc.StackCapacity;
|
||||
@@ -487,14 +488,14 @@ public static unsafe class AllocationManager
|
||||
|
||||
if (s_pHeapAllocator != null)
|
||||
{
|
||||
Free(s_pHeapAllocator);
|
||||
NativeMemory.Free(s_pHeapAllocator);
|
||||
s_pHeapAllocator = null;
|
||||
}
|
||||
|
||||
if (s_pTLSFAllocator != null)
|
||||
{
|
||||
s_pTLSFAllocator->Dispose();
|
||||
Free(s_pTLSFAllocator);
|
||||
NativeMemory.Free(s_pTLSFAllocator);
|
||||
s_pTLSFAllocator = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
return;
|
||||
}
|
||||
|
||||
_buffer = (byte*)Malloc(size);
|
||||
_buffer = (byte*)NativeMemory.Alloc(size);
|
||||
_size = size;
|
||||
_offset = 0;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
var ptr = _buffer + alignedOffset;
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(ptr, size);
|
||||
MemoryUtility.MemClear(ptr, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -120,7 +120,7 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
{
|
||||
if (allocationOption.HasOption(AllocationOption.Clear) && additionalSize > 0)
|
||||
{
|
||||
MemClear((byte*)ptr + oldSize, additionalSize);
|
||||
MemoryUtility.MemClear((byte*)ptr + oldSize, additionalSize);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -134,7 +134,7 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
return null;
|
||||
}
|
||||
|
||||
MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
MemoryUtility.MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,6 @@ public unsafe struct Arena : IMemoryAllocator<Arena, Arena.CreationOptions>
|
||||
_size = 0;
|
||||
_offset = 0;
|
||||
|
||||
MemoryUtility.Free(ptr);
|
||||
NativeMemory.Free(ptr);
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
public DynamicArena(nuint initialSize)
|
||||
{
|
||||
_initialSize = initialSize;
|
||||
_root = (ArenaNode*)Malloc(SizeOf<ArenaNode>());
|
||||
_root = (ArenaNode*)NativeMemory.Alloc((nuint)sizeof(ArenaNode));
|
||||
_root->arena = new Arena(initialSize);
|
||||
_root->next = null;
|
||||
_current = _root;
|
||||
@@ -70,7 +70,7 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
return true;
|
||||
}
|
||||
|
||||
var newNode = (ArenaNode*)Malloc(SizeOf<ArenaNode>());
|
||||
var newNode = (ArenaNode*)NativeMemory.Alloc((nuint)sizeof(ArenaNode));
|
||||
try
|
||||
{
|
||||
newNode->arena = new Arena(size);
|
||||
@@ -85,7 +85,7 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
}
|
||||
catch
|
||||
{
|
||||
Free(newNode);
|
||||
NativeMemory.Free(newNode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
|
||||
if (newPtr != ptr)
|
||||
{
|
||||
MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
MemoryUtility.MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
}
|
||||
|
||||
return newPtr;
|
||||
@@ -194,7 +194,7 @@ public unsafe struct DynamicArena : IMemoryAllocator<DynamicArena, DynamicArena.
|
||||
{
|
||||
var next = current->next;
|
||||
current->arena.Dispose();
|
||||
MemoryUtility.Free(current);
|
||||
NativeMemory.Free(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,10 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
public int isDisposed;
|
||||
public ThreadCache* headCache;
|
||||
public ThreadCache* inactiveCacheHead;
|
||||
|
||||
// nint is not allowed in fixed buffer, use long instead for 64-bit/32-bit pointers
|
||||
public fixed long globalFreeBuckets[_MAX_BUCKETS];
|
||||
public fixed int globalFreeLocks[_MAX_BUCKETS];
|
||||
}
|
||||
|
||||
private class CacheReclaimer
|
||||
@@ -123,6 +127,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
}
|
||||
|
||||
private const byte _MAX_BUCKETS = 16;
|
||||
private const int _MAX_CACHED_BLOCKS_PER_BUCKET = 256;
|
||||
private const int _DEFAULT_MAX_CONCURRENCY_LEVEL = 1;
|
||||
private const int _OVERFLOW_CACHE_INDEX = 0;
|
||||
private const nuint _MIN_BLOCK_SIZE = 32;
|
||||
@@ -179,11 +184,17 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
|
||||
try
|
||||
{
|
||||
var state = (SharedState*)Malloc((nuint)sizeof(SharedState));
|
||||
var state = (SharedState*)NativeMemory.Alloc((nuint)sizeof(SharedState));
|
||||
state->isDisposed = 0;
|
||||
state->headCache = null;
|
||||
state->inactiveCacheHead = null;
|
||||
|
||||
for (var i = 0; i < _MAX_BUCKETS; i++)
|
||||
{
|
||||
state->globalFreeBuckets[i] = 0;
|
||||
state->globalFreeLocks[i] = 0;
|
||||
}
|
||||
|
||||
_instanceId = state;
|
||||
|
||||
_chunks = null;
|
||||
@@ -196,7 +207,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
{
|
||||
if (_instanceId != null)
|
||||
{
|
||||
MemoryUtility.Free(_instanceId);
|
||||
NativeMemory.Free(_instanceId);
|
||||
_instanceId = null;
|
||||
}
|
||||
|
||||
@@ -250,7 +261,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private ThreadCache* CreateCacheForThread(int threadId)
|
||||
{
|
||||
var cache = (ThreadCache*)_chunkArena.Allocate(SizeOf<ThreadCache>(), AlignOf<ThreadCache>(), AllocationOption.Clear);
|
||||
var cache = (ThreadCache*)_chunkArena.Allocate(MemoryUtility.SizeOf<ThreadCache>(), MemoryUtility.AlignOf<ThreadCache>(), AllocationOption.Clear);
|
||||
if (cache == null)
|
||||
{
|
||||
return null;
|
||||
@@ -279,6 +290,92 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private readonly void* TryPopFromGlobalQueue(byte bucketIndex, ThreadCache* cache, nuint alignment)
|
||||
{
|
||||
var state = (SharedState*)_instanceId;
|
||||
FreeNode* node = null;
|
||||
|
||||
var spinWait = new SpinWait();
|
||||
while (Interlocked.CompareExchange(ref state->globalFreeLocks[bucketIndex], 1, 0) != 0)
|
||||
{
|
||||
spinWait.SpinOnce();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var globalHead = state->globalFreeBuckets[bucketIndex];
|
||||
if (globalHead != 0)
|
||||
{
|
||||
node = (FreeNode*)(nint)globalHead;
|
||||
state->globalFreeBuckets[bucketIndex] = (long)(nint)node->next;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Volatile.Write(ref state->globalFreeLocks[bucketIndex], 0);
|
||||
}
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var userPtr = (byte*)(((nuint)node + (nuint)sizeof(BlockHeader) + alignment - 1) & ~(alignment - 1));
|
||||
var header = (BlockHeader*)userPtr - 1;
|
||||
|
||||
AssignBlockHeader(header, node, node->ownerChunk, bucketIndex, cache);
|
||||
return userPtr;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private readonly void* TryScavengeFromSleepingThreads(byte bucketIndex, ThreadCache* currentCache, nuint alignment)
|
||||
{
|
||||
var state = (SharedState*)_instanceId;
|
||||
var cacheToScavenge = state->headCache;
|
||||
|
||||
while (cacheToScavenge != null)
|
||||
{
|
||||
if (cacheToScavenge != currentCache && Volatile.Read(ref cacheToScavenge->remoteFreeHead) != 0)
|
||||
{
|
||||
var stolenHead = (FreeNode*)Interlocked.Exchange(ref cacheToScavenge->remoteFreeHead, 0);
|
||||
if (stolenHead != null)
|
||||
{
|
||||
// Push all stolen blocks except one to the current cache
|
||||
var node = stolenHead;
|
||||
void* result = null;
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
var next = node->next;
|
||||
|
||||
if (node->bucketIndex == bucketIndex && result == null)
|
||||
{
|
||||
var userPtr = (byte*)(((nuint)node + (nuint)sizeof(BlockHeader) + alignment - 1) & ~(alignment - 1));
|
||||
var header = (BlockHeader*)userPtr - 1;
|
||||
AssignBlockHeader(header, node, node->ownerChunk, bucketIndex, currentCache);
|
||||
result = userPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
PushToBucket(currentCache, node->bucketIndex, node, node->ownerChunk);
|
||||
}
|
||||
|
||||
node = next;
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheToScavenge = cacheToScavenge->next;
|
||||
}
|
||||
|
||||
return null; // Return null specifically if scavenging didn't produce the desired block size.
|
||||
}
|
||||
|
||||
private ThreadCache* RegisterThreadCache()
|
||||
{
|
||||
if (_instanceId == null || _disposed != 0)
|
||||
@@ -387,6 +484,29 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
var node = (FreeNode*)ptr;
|
||||
node->ownerChunk = ownerChunk;
|
||||
node->bucketIndex = bucketIndex;
|
||||
|
||||
if (bucket->freeCount >= _MAX_CACHED_BLOCKS_PER_BUCKET)
|
||||
{
|
||||
var state = (SharedState*)_instanceId;
|
||||
var spinWait = new SpinWait();
|
||||
while (Interlocked.CompareExchange(ref state->globalFreeLocks[bucketIndex], 1, 0) != 0)
|
||||
{
|
||||
spinWait.SpinOnce();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var globalHead = state->globalFreeBuckets[bucketIndex];
|
||||
node->next = (FreeNode*)(nint)globalHead;
|
||||
state->globalFreeBuckets[bucketIndex] = (long)(nint)node;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Volatile.Write(ref state->globalFreeLocks[bucketIndex], 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
node->next = (FreeNode*)bucket->freeHead;
|
||||
bucket->freeHead = (nint)node;
|
||||
bucket->freeCount++;
|
||||
@@ -479,14 +599,14 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
}
|
||||
|
||||
var newChunkSize = Math.Max(_chunkSize, size); // 默认保底 64KB
|
||||
var newMemory = (byte*)AlignedAlloc(newChunkSize, alignment);
|
||||
var newMemory = (byte*)NativeMemory.AlignedAlloc(newChunkSize, alignment);
|
||||
if (newMemory == null)
|
||||
{
|
||||
ownerChunk = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
var newChunk = (MemoryChunk*)_chunkArena.Allocate(SizeOf<MemoryChunk>(), AlignOf<MemoryChunk>(), AllocationOption.None);
|
||||
var newChunk = (MemoryChunk*)_chunkArena.Allocate(MemoryUtility.SizeOf<MemoryChunk>(), MemoryUtility.AlignOf<MemoryChunk>(), AllocationOption.None);
|
||||
newChunk->memory = newMemory;
|
||||
newChunk->size = newChunkSize;
|
||||
newChunk->used = size;
|
||||
@@ -544,18 +664,28 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
if (userPtr == null)
|
||||
{
|
||||
DrainRemoteFrees(cache);
|
||||
|
||||
userPtr = TryPopFromBucket(cache, bucketIndex, alignment);
|
||||
if (userPtr == null && TryCreateBlocksForBucket(cache, bucketIndex))
|
||||
|
||||
if (userPtr == null)
|
||||
{
|
||||
userPtr = TryPopFromBucket(cache, bucketIndex, alignment);
|
||||
userPtr = TryPopFromGlobalQueue(bucketIndex, cache, alignment);
|
||||
|
||||
if (userPtr == null)
|
||||
{
|
||||
userPtr = TryScavengeFromSleepingThreads(bucketIndex, cache, alignment);
|
||||
|
||||
if (userPtr == null && TryCreateBlocksForBucket(cache, bucketIndex))
|
||||
{
|
||||
userPtr = TryPopFromBucket(cache, bucketIndex, alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oversized block: Bypass chunk linking entirely and go straight to the OS
|
||||
void* ptr = AlignedAlloc(totalSize, alignment);
|
||||
var ptr = NativeMemory.AlignedAlloc(totalSize, alignment);
|
||||
if (ptr != null)
|
||||
{
|
||||
userPtr = (byte*)(((nuint)ptr + (nuint)sizeof(BlockHeader) + alignment - 1) & ~(alignment - 1));
|
||||
@@ -572,7 +702,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(userPtr, alignedSize);
|
||||
MemoryUtility.MemClear(userPtr, alignedSize);
|
||||
}
|
||||
|
||||
return userPtr;
|
||||
@@ -594,7 +724,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
if (newPtr != null && ptr != null)
|
||||
{
|
||||
var copySize = Math.Min(oldSize, newSize);
|
||||
MemCpy(newPtr, ptr, copySize);
|
||||
MemoryUtility.MemCpy(newPtr, ptr, copySize);
|
||||
Free(ptr);
|
||||
}
|
||||
|
||||
@@ -630,7 +760,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
// This is an oversized allocation. It doesn't belong to a bucket or a chunk.
|
||||
// Erase the magic number for safety and instantly yield it back to the OS.
|
||||
header->magicNumber = 0;
|
||||
AlignedFree(blockStartPtr);
|
||||
NativeMemory.AlignedFree(blockStartPtr);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -679,7 +809,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
MemoryUtility.Free(_instanceId);
|
||||
NativeMemory.Free(_instanceId);
|
||||
_instanceId = null;
|
||||
}
|
||||
|
||||
@@ -690,7 +820,7 @@ public unsafe struct FreeList : IMemoryAllocator<FreeList, FreeList.CreationOpti
|
||||
while (chunk != null)
|
||||
{
|
||||
var next = chunk->next;
|
||||
AlignedFree(chunk->memory);
|
||||
NativeMemory.AlignedFree(chunk->memory);
|
||||
chunk = next;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly void Clear()
|
||||
{
|
||||
MemClear(_buffer, _size);
|
||||
MemoryUtility.MemClear(_buffer, _size);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -141,7 +141,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
|
||||
fixed (T* pDest = destination)
|
||||
{
|
||||
MemCpy(pDest, _buffer, _size);
|
||||
MemoryUtility.MemCpy(pDest, _buffer, _size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +165,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
|
||||
fixed (T* pDest = destination)
|
||||
{
|
||||
MemCpy(pDest + destinationIndex, (byte*)_buffer + sourceOffset, length * sizeOfElement);
|
||||
MemoryUtility.MemCpy(pDest + destinationIndex, (byte*)_buffer + sourceOffset, length * sizeOfElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
|
||||
fixed (T* pSrc = source)
|
||||
{
|
||||
MemCpy(_buffer, pSrc, sourceSize);
|
||||
MemoryUtility.MemCpy(_buffer, pSrc, sourceSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +211,7 @@ public unsafe struct MemoryBlock : IDisposable
|
||||
|
||||
fixed (T* pSrc = source)
|
||||
{
|
||||
MemCpy((byte*)_buffer + destinationOffset, pSrc + sourceIndex, length * sizeOfElement);
|
||||
MemoryUtility.MemCpy((byte*)_buffer + destinationOffset, pSrc + sourceIndex, length * sizeOfElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Buffer;
|
||||
|
||||
@@ -16,7 +17,7 @@ public unsafe struct MemoryPool<TAllocator, TOpts> : IDisposable
|
||||
{
|
||||
var allocator = TAllocator.Create(opts);
|
||||
|
||||
_pAllocator = (TAllocator*)Malloc((nuint)sizeof(TAllocator));
|
||||
_pAllocator = (TAllocator*)NativeMemory.Alloc((nuint)sizeof(TAllocator));
|
||||
*_pAllocator = allocator;
|
||||
|
||||
_allocationHandle = new AllocationHandle(_pAllocator, &Allocate, &Reallocate, &Free);
|
||||
@@ -46,7 +47,7 @@ public unsafe struct MemoryPool<TAllocator, TOpts> : IDisposable
|
||||
|
||||
_pAllocator->Dispose();
|
||||
|
||||
MemoryUtility.Free(_pAllocator);
|
||||
NativeMemory.Free(_pAllocator);
|
||||
|
||||
_pAllocator = null;
|
||||
_allocationHandle = default;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Misaki.HighPerformance.LowLevel.Utilities;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Misaki.HighPerformance.LowLevel.Buffer;
|
||||
|
||||
@@ -60,7 +61,7 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(size);
|
||||
|
||||
_buffer = (byte*)Malloc(size);
|
||||
_buffer = (byte*)NativeMemory.Alloc(size);
|
||||
_size = size;
|
||||
_offset = 0;
|
||||
}
|
||||
@@ -113,7 +114,7 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(ptr, size);
|
||||
MemoryUtility.MemClear(ptr, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -140,7 +141,7 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
_offset += diff;
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(_buffer + _offset - diff, diff);
|
||||
MemoryUtility.MemClear(_buffer + _offset - diff, diff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +154,7 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
return null;
|
||||
}
|
||||
|
||||
MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
MemoryUtility.MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
@@ -184,6 +185,6 @@ public unsafe partial struct Stack : IMemoryAllocator<Stack, Stack.CreationOptio
|
||||
_offset = 0;
|
||||
_size = 0;
|
||||
|
||||
MemoryUtility.Free(ptr);
|
||||
NativeMemory.Free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
|
||||
var slSize = 64 * (nuint)sizeof(uint);
|
||||
var blocksSize = 64 * 32 * (nuint)sizeof(BlockHeader*);
|
||||
_slBitmaps = (uint*)Calloc(slSize);
|
||||
_blocks = (BlockHeader**)Calloc(blocksSize);
|
||||
_slBitmaps = (uint*)NativeMemory.AllocZeroed(slSize);
|
||||
_blocks = (BlockHeader**)NativeMemory.AllocZeroed(blocksSize);
|
||||
|
||||
AddChunk(_chunkSize);
|
||||
}
|
||||
@@ -140,7 +140,7 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
private void AddChunk(nuint size)
|
||||
{
|
||||
var totalSize = size + (nuint)sizeof(MemoryChunk);
|
||||
var mem = (byte*)AlignedAlloc(totalSize, _alignment);
|
||||
var mem = (byte*)NativeMemory.AlignedAlloc(totalSize, _alignment);
|
||||
|
||||
MemoryChunk* chunk = (MemoryChunk*)mem;
|
||||
chunk->next = _chunks;
|
||||
@@ -313,7 +313,7 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
void* userPtr = (byte*)block + 16;
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(userPtr, block->Size - 16);
|
||||
MemoryUtility.MemClear(userPtr, block->Size - 16);
|
||||
}
|
||||
|
||||
return userPtr;
|
||||
@@ -458,7 +458,7 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
if (newPtr != null)
|
||||
{
|
||||
var copySize = oldSize < newSize ? oldSize : newSize;
|
||||
MemCpy(newPtr, ptr, copySize);
|
||||
MemoryUtility.MemCpy(newPtr, ptr, copySize);
|
||||
Free(ptr);
|
||||
}
|
||||
return newPtr;
|
||||
@@ -468,13 +468,13 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
{
|
||||
if (_blocks != null)
|
||||
{
|
||||
MemoryUtility.Free(_blocks);
|
||||
NativeMemory.Free(_blocks);
|
||||
_blocks = null;
|
||||
}
|
||||
|
||||
if (_slBitmaps != null)
|
||||
{
|
||||
MemoryUtility.Free(_slBitmaps);
|
||||
NativeMemory.Free(_slBitmaps);
|
||||
_slBitmaps = null;
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ public unsafe struct TLSF : IMemoryAllocator<TLSF, TLSF.CreationOptions>
|
||||
while (chunk != null)
|
||||
{
|
||||
MemoryChunk* next = chunk->next;
|
||||
AlignedFree(chunk->memory);
|
||||
NativeMemory.AlignedFree(chunk->memory);
|
||||
chunk = next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
_committedSize = 0;
|
||||
_allocatedOffset = 0;
|
||||
|
||||
_baseAddress = (byte*)Mmap(null, _reserveCapacity, VirtualAllocationFlags.Reserve);
|
||||
_baseAddress = (byte*)MemoryUtility.Mmap(null, _reserveCapacity, VirtualAllocationFlags.Reserve);
|
||||
|
||||
if (_baseAddress == null)
|
||||
{
|
||||
@@ -87,7 +87,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(ptr, size);
|
||||
MemoryUtility.MemClear(ptr, size);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -113,7 +113,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
sizeToCommit = (sizeToCommit + _PAGE_SIZE - 1) & ~(_PAGE_SIZE - 1);
|
||||
|
||||
var commitAddress = _baseAddress + currentCommitted;
|
||||
var result = Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
var result = MemoryUtility.Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
@@ -177,7 +177,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
sizeToCommit = (sizeToCommit + _PAGE_SIZE - 1) & ~(_PAGE_SIZE - 1);
|
||||
|
||||
var commitAddress = _baseAddress + currentCommitted;
|
||||
var result = Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
var result = MemoryUtility.Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
@@ -199,7 +199,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
// Safe to clear: we own the space between oldSize and newOffset
|
||||
if (allocationOption.HasOption(AllocationOption.Clear) && additionalSize > 0)
|
||||
{
|
||||
MemClear((byte*)ptr + oldSize, additionalSize);
|
||||
MemoryUtility.MemClear((byte*)ptr + oldSize, additionalSize);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -212,7 +212,7 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
return null;
|
||||
}
|
||||
|
||||
MemCpy(newPtr, ptr, oldSize);
|
||||
MemoryUtility.MemCpy(newPtr, ptr, oldSize);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
@@ -244,6 +244,6 @@ public unsafe struct VirtualArena : IMemoryAllocator<VirtualArena, VirtualArena.
|
||||
_committedSize = 0;
|
||||
_reserveCapacity = 0;
|
||||
|
||||
Munmap(ptr, _reserveCapacity);
|
||||
MemoryUtility.Munmap(ptr, _reserveCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
_committedSize = 0;
|
||||
_allocatedOffset = 0;
|
||||
|
||||
_baseAddress = (byte*)Mmap(null, _reserveCapacity, VirtualAllocationFlags.Reserve);
|
||||
_baseAddress = (byte*)MemoryUtility.Mmap(null, _reserveCapacity, VirtualAllocationFlags.Reserve);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +115,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
sizeToCommit = (sizeToCommit + _PAGE_SIZE - 1) & ~(_PAGE_SIZE - 1);
|
||||
|
||||
var commitAddress = _baseAddress + _committedSize;
|
||||
var result = Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
var result = MemoryUtility.Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
@@ -130,7 +130,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
|
||||
if (option.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(userPtr, size);
|
||||
MemoryUtility.MemClear(userPtr, size);
|
||||
}
|
||||
|
||||
return userPtr;
|
||||
@@ -166,7 +166,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
sizeToCommit = (sizeToCommit + _PAGE_SIZE - 1) & ~(_PAGE_SIZE - 1);
|
||||
|
||||
var commitAddress = _baseAddress + _committedSize;
|
||||
var result = Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
var result = MemoryUtility.Mmap(commitAddress, sizeToCommit, VirtualAllocationFlags.Commit);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
@@ -178,7 +178,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
|
||||
if (allocationOption.HasOption(AllocationOption.Clear))
|
||||
{
|
||||
MemClear(_baseAddress + _allocatedOffset - diff, diff);
|
||||
MemoryUtility.MemClear(_baseAddress + _allocatedOffset - diff, diff);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -190,7 +190,7 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
return null;
|
||||
}
|
||||
|
||||
MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
MemoryUtility.MemCpy(newPtr, ptr, Math.Min(oldSize, newSize));
|
||||
|
||||
return newPtr;
|
||||
}
|
||||
@@ -224,6 +224,6 @@ public unsafe struct VirtualStack : IMemoryAllocator<VirtualStack, VirtualStack.
|
||||
_committedSize = 0;
|
||||
_reserveCapacity = 0;
|
||||
|
||||
Munmap(ptr, size);
|
||||
MemoryUtility.Munmap(ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user