254 lines
10 KiB
C
254 lines
10 KiB
C
#if !defined(DN_BASE_MEM_H)
|
|
#define DN_BASE_MEM_H
|
|
|
|
#include "../dn_clangd.h"
|
|
|
|
enum DN_MemCommit
|
|
{
|
|
DN_MemCommit_No,
|
|
DN_MemCommit_Yes,
|
|
};
|
|
|
|
typedef DN_U32 DN_MemPage;
|
|
enum DN_MemPage_
|
|
{
|
|
// Exception on read/write with a page. This flag overrides the read/write
|
|
// access.
|
|
DN_MemPage_NoAccess = 1 << 0,
|
|
|
|
DN_MemPage_Read = 1 << 1, // Only read permitted on the page.
|
|
|
|
// Only write permitted on the page. On Windows this is not supported and
|
|
// will be promoted to read+write permissions.
|
|
DN_MemPage_Write = 1 << 2,
|
|
|
|
DN_MemPage_ReadWrite = DN_MemPage_Read | DN_MemPage_Write,
|
|
|
|
// Modifier used in conjunction with previous flags. Raises exception on
|
|
// first access to the page, then, the underlying protection flags are
|
|
// active. This is supported on Windows, on other OS's using this flag will
|
|
// set the OS equivalent of DN_MemPage_NoAccess.
|
|
// This flag must only be used in DN_Mem_Protect
|
|
DN_MemPage_Guard = 1 << 3,
|
|
|
|
// If leak tracing is enabled, this flag will allow the allocation recorded
|
|
// from the reserve call to be leaked, e.g. not printed when leaks are
|
|
// dumped to the console.
|
|
DN_MemPage_AllocRecordLeakPermitted = 1 << 4,
|
|
|
|
// If leak tracing is enabled this flag will prevent any allocation record
|
|
// from being created in the allocation table at all. If this flag is
|
|
// enabled, 'OSMemPage_AllocRecordLeakPermitted' has no effect since the
|
|
// record will never be created.
|
|
DN_MemPage_NoAllocRecordEntry = 1 << 5,
|
|
|
|
// [INTERNAL] Do not use. All flags together do not constitute a correct
|
|
// configuration of pages.
|
|
DN_MemPage_All = DN_MemPage_NoAccess |
|
|
DN_MemPage_ReadWrite |
|
|
DN_MemPage_Guard |
|
|
DN_MemPage_AllocRecordLeakPermitted |
|
|
DN_MemPage_NoAllocRecordEntry,
|
|
};
|
|
|
|
#if !defined(DN_ARENA_RESERVE_SIZE)
|
|
#define DN_ARENA_RESERVE_SIZE DN_Megabytes(64)
|
|
#endif
|
|
|
|
#if !defined(DN_ARENA_COMMIT_SIZE)
|
|
#define DN_ARENA_COMMIT_SIZE DN_Kilobytes(64)
|
|
#endif
|
|
|
|
struct DN_ArenaBlock
|
|
{
|
|
DN_ArenaBlock *prev;
|
|
DN_U64 used;
|
|
DN_U64 commit;
|
|
DN_U64 reserve;
|
|
DN_U64 reserve_sum;
|
|
};
|
|
|
|
typedef uint32_t DN_ArenaFlags;
|
|
|
|
enum DN_ArenaFlags_
|
|
{
|
|
DN_ArenaFlags_Nil = 0,
|
|
DN_ArenaFlags_NoGrow = 1 << 0,
|
|
DN_ArenaFlags_NoPoison = 1 << 1,
|
|
DN_ArenaFlags_NoAllocTrack = 1 << 2,
|
|
DN_ArenaFlags_AllocCanLeak = 1 << 3,
|
|
|
|
// NOTE: Internal flags. Do not use
|
|
DN_ArenaFlags_UserBuffer = 1 << 4,
|
|
DN_ArenaFlags_MemFuncs = 1 << 5,
|
|
};
|
|
|
|
struct DN_ArenaInfo
|
|
{
|
|
DN_U64 used;
|
|
DN_U64 commit;
|
|
DN_U64 reserve;
|
|
DN_U64 blocks;
|
|
};
|
|
|
|
struct DN_ArenaStats
|
|
{
|
|
DN_ArenaInfo info;
|
|
DN_ArenaInfo hwm;
|
|
};
|
|
|
|
enum DN_ArenaMemFuncType
|
|
{
|
|
DN_ArenaMemFuncType_Nil,
|
|
DN_ArenaMemFuncType_Basic,
|
|
DN_ArenaMemFuncType_VMem,
|
|
};
|
|
|
|
typedef void *(DN_ArenaMemBasicAllocFunc)(DN_USize size);
|
|
typedef void (DN_ArenaMemBasicDeallocFunc)(void *ptr);
|
|
typedef void *(DN_ArenaMemVMemReserveFunc)(DN_USize size, DN_MemCommit commit, DN_MemPage page_flags);
|
|
typedef bool (DN_ArenaMemVMemCommitFunc)(void *ptr, DN_USize size, DN_U32 page_flags);
|
|
typedef void (DN_ArenaMemVMemReleaseFunc)(void *ptr, DN_USize size);
|
|
struct DN_ArenaMemFuncs
|
|
{
|
|
DN_ArenaMemFuncType type;
|
|
DN_ArenaMemBasicAllocFunc *basic_alloc;
|
|
DN_ArenaMemBasicDeallocFunc *basic_dealloc;
|
|
|
|
DN_U32 vmem_page_size;
|
|
DN_ArenaMemVMemReserveFunc *vmem_reserve;
|
|
DN_ArenaMemVMemCommitFunc *vmem_commit;
|
|
DN_ArenaMemVMemReleaseFunc *vmem_release;
|
|
};
|
|
|
|
struct DN_Arena
|
|
{
|
|
DN_ArenaMemFuncs mem_funcs;
|
|
DN_ArenaBlock *curr;
|
|
DN_ArenaStats stats;
|
|
DN_ArenaFlags flags;
|
|
DN_Str8 label;
|
|
DN_Arena *prev, *next;
|
|
};
|
|
|
|
struct DN_ArenaTempMem
|
|
{
|
|
DN_Arena *arena;
|
|
DN_U64 used_sum;
|
|
};
|
|
|
|
struct DN_ArenaTempMemScope
|
|
{
|
|
DN_ArenaTempMemScope(DN_Arena *arena);
|
|
~DN_ArenaTempMemScope();
|
|
DN_ArenaTempMem mem;
|
|
};
|
|
|
|
DN_USize const DN_ARENA_HEADER_SIZE = DN_AlignUpPowerOfTwo(sizeof(DN_Arena), 64);
|
|
|
|
// NOTE: DN_Arena //////////////////////////////////////////////////////////////////////////////////
|
|
DN_API DN_Arena DN_Arena_InitFromBuffer (void *buffer, DN_USize size, DN_ArenaFlags flags);
|
|
DN_API DN_Arena DN_Arena_InitFromMemFuncs (DN_U64 reserve, DN_U64 commit, DN_ArenaFlags flags, DN_ArenaMemFuncs mem_funcs);
|
|
DN_API void DN_Arena_Deinit (DN_Arena *arena);
|
|
DN_API bool DN_Arena_Commit (DN_Arena *arena, DN_U64 size);
|
|
DN_API bool DN_Arena_CommitTo (DN_Arena *arena, DN_U64 pos);
|
|
DN_API bool DN_Arena_Grow (DN_Arena *arena, DN_U64 reserve, DN_U64 commit);
|
|
DN_API void * DN_Arena_Alloc (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
|
DN_API void * DN_Arena_AllocContiguous (DN_Arena *arena, DN_U64 size, uint8_t align, DN_ZeroMem zero_mem);
|
|
DN_API void * DN_Arena_Copy (DN_Arena *arena, void const *data, DN_U64 size, uint8_t align);
|
|
DN_API void DN_Arena_PopTo (DN_Arena *arena, DN_U64 init_used);
|
|
DN_API void DN_Arena_Pop (DN_Arena *arena, DN_U64 amount);
|
|
DN_API DN_U64 DN_Arena_Pos (DN_Arena const *arena);
|
|
DN_API void DN_Arena_Clear (DN_Arena *arena);
|
|
DN_API bool DN_Arena_OwnsPtr (DN_Arena const *arena, void *ptr);
|
|
DN_API DN_ArenaStats DN_Arena_SumStatsArray (DN_ArenaStats const *array, DN_USize size);
|
|
DN_API DN_ArenaStats DN_Arena_SumStats (DN_ArenaStats lhs, DN_ArenaStats rhs);
|
|
DN_API DN_ArenaStats DN_Arena_SumArenaArrayToStats (DN_Arena const *array, DN_USize size);
|
|
DN_API DN_ArenaTempMem DN_Arena_TempMemBegin (DN_Arena *arena);
|
|
DN_API void DN_Arena_TempMemEnd (DN_ArenaTempMem mem);
|
|
#define DN_Arena_New_Frame(T, zero_mem) (T *)DN_Arena_Alloc(DN_OS_TLSGet()->frame_arena, sizeof(T), alignof(T), zero_mem)
|
|
#define DN_Arena_New(arena, T, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
|
|
#define DN_Arena_NewArray(arena, T, count, zero_mem) (T *)DN_Arena_Alloc(arena, sizeof(T) * (count), alignof(T), zero_mem)
|
|
#define DN_Arena_NewCopy(arena, T, src) (T *)DN_Arena_Copy (arena, (src), sizeof(T), alignof(T))
|
|
#define DN_Arena_NewArrayCopy(arena, T, src, count) (T *)DN_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
|
|
|
#if !defined(DN_POOL_DEFAULT_ALIGN)
|
|
#define DN_POOL_DEFAULT_ALIGN 16
|
|
#endif
|
|
|
|
struct DN_PoolSlot
|
|
{
|
|
void *data;
|
|
DN_PoolSlot *next;
|
|
};
|
|
|
|
enum DN_PoolSlotSize
|
|
{
|
|
DN_PoolSlotSize_32B,
|
|
DN_PoolSlotSize_64B,
|
|
DN_PoolSlotSize_128B,
|
|
DN_PoolSlotSize_256B,
|
|
DN_PoolSlotSize_512B,
|
|
DN_PoolSlotSize_1KiB,
|
|
DN_PoolSlotSize_2KiB,
|
|
DN_PoolSlotSize_4KiB,
|
|
DN_PoolSlotSize_8KiB,
|
|
DN_PoolSlotSize_16KiB,
|
|
DN_PoolSlotSize_32KiB,
|
|
DN_PoolSlotSize_64KiB,
|
|
DN_PoolSlotSize_128KiB,
|
|
DN_PoolSlotSize_256KiB,
|
|
DN_PoolSlotSize_512KiB,
|
|
DN_PoolSlotSize_1MiB,
|
|
DN_PoolSlotSize_2MiB,
|
|
DN_PoolSlotSize_4MiB,
|
|
DN_PoolSlotSize_8MiB,
|
|
DN_PoolSlotSize_16MiB,
|
|
DN_PoolSlotSize_32MiB,
|
|
DN_PoolSlotSize_64MiB,
|
|
DN_PoolSlotSize_128MiB,
|
|
DN_PoolSlotSize_256MiB,
|
|
DN_PoolSlotSize_512MiB,
|
|
DN_PoolSlotSize_1GiB,
|
|
DN_PoolSlotSize_2GiB,
|
|
DN_PoolSlotSize_4GiB,
|
|
DN_PoolSlotSize_8GiB,
|
|
DN_PoolSlotSize_16GiB,
|
|
DN_PoolSlotSize_32GiB,
|
|
DN_PoolSlotSize_Count,
|
|
};
|
|
|
|
struct DN_Pool
|
|
{
|
|
DN_Arena *arena;
|
|
DN_PoolSlot *slots[DN_PoolSlotSize_Count];
|
|
uint8_t align;
|
|
};
|
|
|
|
// NOTE: DN_Pool ///////////////////////////////////////////////////////////////////////////////////
|
|
DN_API DN_Pool DN_Pool_Init (DN_Arena *arena, uint8_t align);
|
|
DN_API bool DN_Pool_IsValid (DN_Pool const *pool);
|
|
DN_API void * DN_Pool_Alloc (DN_Pool *pool, DN_USize size);
|
|
DN_API DN_Str8 DN_Pool_AllocStr8FV (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, va_list args);
|
|
DN_API DN_Str8 DN_Pool_AllocStr8F (DN_Pool *pool, DN_FMT_ATTRIB char const *fmt, ...);
|
|
DN_API DN_Str8 DN_Pool_AllocStr8Copy (DN_Pool *pool, DN_Str8 string);
|
|
DN_API void DN_Pool_Dealloc (DN_Pool *pool, void *ptr);
|
|
DN_API void * DN_Pool_Copy (DN_Pool *pool, void const *data, DN_U64 size, uint8_t align);
|
|
|
|
#define DN_Pool_New(pool, T) (T *)DN_Pool_Alloc(pool, sizeof(T))
|
|
#define DN_Pool_NewArray(pool, T, count) (T *)DN_Pool_Alloc(pool, count * sizeof(T))
|
|
#define DN_Pool_NewCopy(arena, T, src) (T *)DN_Pool_Copy (arena, (src), sizeof(T), alignof(T))
|
|
#define DN_Pool_NewArrayCopy(arena, T, src, count) (T *)DN_Pool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
|
|
|
|
// NOTE: DN_Debug //////////////////////////////////////////////////////////////////////////////////
|
|
#if defined(DN_LEAK_TRACKING) && !defined(DN_FREESTANDING)
|
|
DN_API void DN_Debug_TrackAlloc (void *ptr, DN_USize size, bool alloc_can_leak);
|
|
DN_API void DN_Debug_TrackDealloc(void *ptr);
|
|
DN_API void DN_Debug_DumpLeaks ();
|
|
#else
|
|
#define DN_Debug_TrackAlloc(ptr, size, alloc_can_leak) do { (void)ptr; (void)size; (void)alloc_can_leak; } while (0)
|
|
#define DN_Debug_TrackDealloc(ptr) do { (void)ptr; } while (0)
|
|
#define DN_Debug_DumpLeaks() do { } while (0)
|
|
#endif
|
|
#endif // !defined(DN_BASE_MEM_H)
|