//////////////////////////////// //- sixten: Common Memory Functions static void Copy(void *Dest, void *Source, umm Count) { if(Count <= S64_Max) { u8 *Dest8 = (u8 *)Dest; u8 *Source8 = (u8 *)Source; while(Count--) { *Dest8++ = *Source8++; } } } static void CopyReverse(void *Dest, void *Source, umm Count) { if(Count <= S64_Max) { u8 *Dest8 = (u8 *)Dest + Count; u8 *Source8 = (u8 *)Source + Count; while(Count--) { *--Dest8 = *--Source8; } } } static void Fill(void *Dest, u8 Value, umm Count) { if(Count <= S64_Max) { u8 *Dest8 = (u8 *)Dest; while(Count--) { *Dest8++ = Value; } } } //////////////////////////////// //- sixten: Memory Arena Functions static memory_arena *ArenaAllocate(u64 Size) { 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); memory_arena *Arena = (memory_arena *)Memory; Arena->Position = sizeof(memory_arena); Arena->CommitPosition = InitialCommitSize; Arena->Size = Size; Arena->Align = 8; return(Arena); } static void ArenaRelease(memory_arena *Arena) { Platform.Release(Arena); } static void *ArenaPushNoClear(memory_arena *Arena, u64 Size) { void *Result = 0; 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); } static void *ArenaPush(memory_arena *Arena, u64 Size) { void *Result = ArenaPushNoClear(Arena, Size); Fill(Result, 0, Size); return(Result); } static void ArenaPopTo(memory_arena *Arena, u64 Position) { 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; } } static void ArenaPop(memory_arena *Arena, u64 Amount) { ArenaPopTo(Arena, Max(Arena->Position-Amount, (s64)sizeof(memory_arena))); } static void ArenaClear(memory_arena *Arena) { ArenaPopTo(Arena, sizeof(*Arena)); } static void ArenaSetAlign(memory_arena *Arena, u64 Align) { Arena->Align = Align; } //////////////////////////////// //- sixten: Temporary Memory Functions static temporary_memory BeginTemporaryMemory(memory_arena *Arena) { temporary_memory Temp; Temp.Arena = Arena; Temp.Position = Arena->Position; return(Temp); } static void EndTemporaryMemory(temporary_memory Temp) { ArenaPopTo(Temp.Arena, Temp.Position); }