2023-07-19 15:09:41 +00:00
|
|
|
////////////////////////////////
|
|
|
|
//- sixten: Common Memory Functions
|
2023-06-17 17:00:55 +00:00
|
|
|
|
2023-06-21 16:59:36 +00:00
|
|
|
static void Copy(void *Dest, void *Source, umm Count)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
if(Count <= S32_Max)
|
|
|
|
{
|
|
|
|
u8 *Dest8 = (u8 *)Dest;
|
|
|
|
u8 *Source8 = (u8 *)Source;
|
|
|
|
|
|
|
|
while(Count--)
|
|
|
|
{
|
|
|
|
*Dest8++ = *Source8++;
|
|
|
|
}
|
|
|
|
}
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 15:09:41 +00:00
|
|
|
static void CopyReverse(void *Dest, void *Source, umm Count)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
if(Count <= S32_Max)
|
|
|
|
{
|
|
|
|
u8 *Dest8 = (u8 *)Dest + Count;
|
|
|
|
u8 *Source8 = (u8 *)Source + Count;
|
|
|
|
|
|
|
|
while(Count--)
|
|
|
|
{
|
|
|
|
*--Dest8 = *--Source8;
|
|
|
|
}
|
|
|
|
}
|
2023-06-21 16:59:36 +00:00
|
|
|
}
|
|
|
|
|
2023-07-19 15:09:41 +00:00
|
|
|
static void Fill(void *Dest, u8 Value, umm Count)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
if(Count <= S32_Max)
|
|
|
|
{
|
|
|
|
u8 *Dest8 = (u8 *)Dest;
|
|
|
|
|
|
|
|
while(Count--)
|
|
|
|
{
|
|
|
|
*Dest8++ = Value;
|
|
|
|
}
|
|
|
|
}
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
|
|
|
#include <sanitizer/asan_interface.h>
|
|
|
|
#endif
|
|
|
|
|
2023-07-19 15:09:41 +00:00
|
|
|
////////////////////////////////
|
|
|
|
//- sixten: Memory Arena Functions
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static arena *ArenaAlloc(u64 Size, b32 Chaining)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
arena *Arena = 0;
|
|
|
|
if(Chaining)
|
|
|
|
{
|
|
|
|
void *Memory = Platform.Allocate(Size);
|
|
|
|
Arena = (arena *)Memory;
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
2023-12-23 07:27:22 +00:00
|
|
|
ASAN_POISON_MEMORY_REGION(Arena, Size);
|
|
|
|
ASAN_UNPOISON_MEMORY_REGION(Arena, sizeof(arena));
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
|
|
|
|
Arena->Chaining = true;
|
|
|
|
SenDLLInit(Arena);
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u64 RoundedSize = Size+Megabytes(64)-1;
|
|
|
|
RoundedSize -= RoundedSize&Megabytes(64);
|
|
|
|
void *Memory = Platform.Reserve(RoundedSize);
|
|
|
|
u64 InitialCommitSize = MEMORY_ARENA_COMMIT_SIZE;
|
|
|
|
Platform.Commit(Memory, InitialCommitSize);
|
|
|
|
Arena = (arena *)Memory;
|
|
|
|
}
|
|
|
|
Arena->Position = sizeof(arena);
|
|
|
|
Arena->Size = Size;
|
|
|
|
Arena->Align = 8;
|
|
|
|
return(Arena);
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void ArenaRelease(arena *Arena)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
if(Arena->Chaining)
|
|
|
|
{
|
|
|
|
arena *Node = Arena->Prev;
|
|
|
|
for(;Node != Arena;)
|
|
|
|
{
|
|
|
|
arena *Next = Node->Prev;
|
|
|
|
Platform.Deallocate(Node);
|
|
|
|
Node = Next;
|
|
|
|
}
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
2023-12-23 07:27:22 +00:00
|
|
|
ASAN_POISON_MEMORY_REGION(Arena, Arena->Size);
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
Platform.Deallocate(Arena);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Platform.Release(Arena);
|
|
|
|
}
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void *ArenaPushNoClear(arena *Arena, u64 Size)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
void *Result = 0;
|
|
|
|
if(Arena->Chaining)
|
|
|
|
{
|
|
|
|
if(Size <= Arena->Size)
|
|
|
|
{
|
|
|
|
arena *Target = Arena->Prev; // sixten: We always append to the end of the list.
|
|
|
|
if(Target->Position + Size + Arena->Align > Target->Size)
|
|
|
|
{
|
|
|
|
arena *New = ArenaAlloc(Arena->Size, true);
|
|
|
|
New->NotFirst = true;
|
|
|
|
SenDLLInsertLast(Arena, New);
|
|
|
|
Target = New;
|
|
|
|
}
|
|
|
|
u8 *Base = (u8 *)Target;
|
|
|
|
u64 PostAlignPos = (Target->Position+Target->Align-1);
|
|
|
|
PostAlignPos -= PostAlignPos%Target->Align;
|
|
|
|
Result = Base + PostAlignPos;
|
|
|
|
Target->Position = PostAlignPos+Size;
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
2023-12-23 07:27:22 +00:00
|
|
|
ASAN_UNPOISON_MEMORY_REGION(Result, Size);
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// sixten(NOTE): We can't really do anything in this situation.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(Arena->Position + Size <= Arena->Size)
|
|
|
|
{
|
|
|
|
u8 *Base = (u8 *)Arena;
|
|
|
|
u64 PostAlignPos = (Arena->Position+Arena->Align-1);
|
|
|
|
PostAlignPos -= PostAlignPos%Arena->Align;
|
|
|
|
u64 Align = PostAlignPos - Arena->Position;
|
|
|
|
Result = Base + Arena->Position + Align;
|
|
|
|
Arena->Position += Size + Align;
|
|
|
|
if(Arena->CommitPosition < Arena->Position)
|
|
|
|
{
|
|
|
|
u64 ToCommit = Arena->Position - Arena->CommitPosition;
|
|
|
|
ToCommit += MEMORY_ARENA_COMMIT_SIZE - 1;
|
|
|
|
ToCommit -= ToCommit%MEMORY_ARENA_COMMIT_SIZE;
|
|
|
|
Platform.Commit(Base + Arena->CommitPosition, ToCommit);
|
|
|
|
Arena->CommitPosition += ToCommit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
InvalidCodepath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(Result);
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void *ArenaPush(arena *Arena, u64 Size)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
void *Result = ArenaPushNoClear(Arena, Size);
|
|
|
|
Fill(Result, 0, Size);
|
|
|
|
return(Result);
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void ArenaPopTo(arena *Arena, u64 Position)
|
2023-07-19 15:09:41 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
if(Arena->Chaining)
|
|
|
|
{
|
|
|
|
// sixten: find the relevant arena
|
|
|
|
arena *Target = Arena;
|
|
|
|
for(int ArenaIndex = 0; ArenaIndex < Position/Arena->Size; ++ArenaIndex)
|
|
|
|
{
|
|
|
|
Target = Arena->Next;
|
|
|
|
}
|
|
|
|
|
|
|
|
// sixten: deallocate all arenas that are no longer needed
|
|
|
|
{
|
|
|
|
arena *Node = Arena->Prev;
|
|
|
|
while(Node != Target)
|
|
|
|
{
|
|
|
|
arena *Prev = Node->Prev;
|
|
|
|
SenDLLRemove(Node);
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
2023-12-23 07:27:22 +00:00
|
|
|
ASAN_POISON_MEMORY_REGION(Node, Node->Size);
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
Platform.Deallocate(Node);
|
|
|
|
Node = Prev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Target->Position = Position%Arena->Size;
|
2023-10-29 10:00:34 +00:00
|
|
|
#if VN_ASAN_ENABLED
|
2023-12-23 07:27:22 +00:00
|
|
|
u64 UnpoisonPosition = Target->Position;
|
|
|
|
ASAN_POISON_MEMORY_REGION(Target, Target->Size);
|
|
|
|
ASAN_UNPOISON_MEMORY_REGION(Target, UnpoisonPosition);
|
2023-10-29 10:00:34 +00:00
|
|
|
#endif
|
2023-12-23 07:27:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
u64 MinPosition = sizeof(*Arena);
|
|
|
|
u64 NewPosition = Maximum(MinPosition, Position);
|
|
|
|
Arena->Position = NewPosition;
|
|
|
|
u64 CommitAlignedPosition = Arena->Position+MEMORY_ARENA_COMMIT_SIZE-1;
|
|
|
|
CommitAlignedPosition -= CommitAlignedPosition%MEMORY_ARENA_COMMIT_SIZE;
|
|
|
|
if(CommitAlignedPosition + MEMORY_ARENA_DECOMMIT_THRESHOLD <= Arena->CommitPosition)
|
|
|
|
{
|
|
|
|
u8 *Base = (u8 *)Arena;
|
|
|
|
u64 ToDecommit = Arena->CommitPosition-CommitAlignedPosition;
|
|
|
|
Platform.Decommit(Base+CommitAlignedPosition, ToDecommit);
|
|
|
|
Arena->CommitPosition -= ToDecommit;
|
|
|
|
}
|
|
|
|
}
|
2023-07-19 15:09:41 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void ArenaPop(arena *Arena, u64 Amount)
|
2023-08-06 10:35:09 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
ArenaPopTo(Arena, Max(Arena->Position-Amount, (s64)sizeof(arena)));
|
2023-08-06 10:35:09 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void ArenaClear(arena *Arena)
|
2023-07-19 15:09:41 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
ArenaPopTo(Arena, sizeof(*Arena));
|
2023-07-19 15:09:41 +00:00
|
|
|
}
|
|
|
|
|
2023-10-29 10:00:34 +00:00
|
|
|
static void ArenaSetAlign(arena *Arena, u64 Align)
|
2023-07-19 15:09:41 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
Arena->Align = Align;
|
2023-07-19 15:09:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////
|
|
|
|
//- sixten: Temporary Memory Functions
|
2023-06-17 17:00:55 +00:00
|
|
|
|
2023-12-23 07:27:22 +00:00
|
|
|
static temp BeginTemp(arena *Arena)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
temp Temp;
|
|
|
|
Temp.Arena = Arena;
|
|
|
|
Temp.Position = Arena->Position;
|
|
|
|
return(Temp);
|
2023-06-17 17:00:55 +00:00
|
|
|
}
|
|
|
|
|
2023-12-23 07:27:22 +00:00
|
|
|
static void EndTemp(temp Temp)
|
2023-06-17 17:00:55 +00:00
|
|
|
{
|
2023-12-23 07:27:22 +00:00
|
|
|
ArenaPopTo(Temp.Arena, Temp.Position);
|
2023-06-21 16:59:36 +00:00
|
|
|
}
|