Compare commits
No commits in common. "faa46b4921bab13c6a77d0b5815a147ce819c722" and "d9a19fd7424b046f59c660c320f6b166ead5532a" have entirely different histories.
faa46b4921
...
d9a19fd742
98
dqn.h
98
dqn.h
@ -1495,8 +1495,8 @@ struct Dqn_Arena
|
|||||||
|
|
||||||
Dqn_String8 label; ///< Optional label to describe the arena
|
Dqn_String8 label; ///< Optional label to describe the arena
|
||||||
Dqn_usize min_block_size;
|
Dqn_usize min_block_size;
|
||||||
Dqn_ArenaBlock *curr; ///< Active block the arena is allocating from
|
Dqn_ArenaBlock *curr; ///< The current memory block of the arena
|
||||||
Dqn_ArenaBlock *tail; ///< Last block in the linked list of blocks
|
Dqn_ArenaBlock *tail; ///< The tail memory block of the arena
|
||||||
Dqn_ArenaStat stats; ///< Current arena stats, reset when reset usage is invoked.
|
Dqn_ArenaStat stats; ///< Current arena stats, reset when reset usage is invoked.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -6316,36 +6316,6 @@ DQN_API Dqn_Allocator Dqn_Arena_Allocator(Dqn_Arena *arena)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Dqn_ArenaBlockResetInfo_
|
|
||||||
{
|
|
||||||
bool free_memory;
|
|
||||||
Dqn_usize used_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate the size in bytes required to allocate the memory for the block
|
|
||||||
// (*not* including the memory required for the user in the block!)
|
|
||||||
#define Dqn_Arena_BlockMetadataSize_(arena) ((arena)->use_after_free_guard ? (Dqn_PowerOfTwoAlign(sizeof(Dqn_ArenaBlock), DQN_VMEM_PAGE_GRANULARITY)) : sizeof(Dqn_ArenaBlock))
|
|
||||||
|
|
||||||
DQN_API void Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_FUNCTION Dqn_ArenaBlock *block, Dqn_ZeroMem zero_mem, Dqn_ArenaBlockResetInfo_ reset_info)
|
|
||||||
{
|
|
||||||
if (!block)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (zero_mem == Dqn_ZeroMem_Yes)
|
|
||||||
DQN_MEMSET(block->memory, DQN_MEMSET_BYTE, block->commit);
|
|
||||||
|
|
||||||
if (reset_info.free_memory) {
|
|
||||||
Dqn_usize block_metadata_size = Dqn_Arena_BlockMetadataSize_(block->arena);
|
|
||||||
Dqn_VMem_Release(block, block_metadata_size + block->size);
|
|
||||||
Dqn_Library_LeakTraceMarkFree(DQN_LEAK_TRACE_ARG block);
|
|
||||||
} else {
|
|
||||||
block->used = reset_info.used_value;
|
|
||||||
// NOTE: Guard all the committed pages again
|
|
||||||
if (block->arena->use_after_free_guard)
|
|
||||||
Dqn_VMem_Protect(block->memory, block->commit, Dqn_VMemPage_ReadWrite | Dqn_VMemPage_Guard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DQN_API void Dqn_Arena_Reset(Dqn_Arena *arena, Dqn_ZeroMem zero_mem)
|
DQN_API void Dqn_Arena_Reset(Dqn_Arena *arena, Dqn_ZeroMem zero_mem)
|
||||||
{
|
{
|
||||||
if (!arena)
|
if (!arena)
|
||||||
@ -6355,8 +6325,14 @@ DQN_API void Dqn_Arena_Reset(Dqn_Arena *arena, Dqn_ZeroMem zero_mem)
|
|||||||
for (Dqn_ArenaBlock *block = arena->tail; block; block = block->prev) {
|
for (Dqn_ArenaBlock *block = arena->tail; block; block = block->prev) {
|
||||||
if (!block->prev)
|
if (!block->prev)
|
||||||
arena->curr = block;
|
arena->curr = block;
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
if (zero_mem == Dqn_ZeroMem_Yes)
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE block, zero_mem, reset_info);
|
DQN_MEMSET(block->memory, DQN_MEMSET_BYTE, block->commit);
|
||||||
|
|
||||||
|
block->used = 0;
|
||||||
|
|
||||||
|
// NOTE: Guard all the committed pages again
|
||||||
|
if (arena->use_after_free_guard)
|
||||||
|
Dqn_VMem_Protect(block->memory, block->commit, Dqn_VMemPage_ReadWrite | Dqn_VMemPage_Guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
arena->stats.used = 0;
|
arena->stats.used = 0;
|
||||||
@ -6389,27 +6365,31 @@ DQN_API void Dqn_Arena_EndTempMemory_(DQN_LEAK_TRACE_FUNCTION Dqn_ArenaTempMemor
|
|||||||
// NOTE: Revert the current block to the scope's current block
|
// NOTE: Revert the current block to the scope's current block
|
||||||
arena->curr = scope.curr;
|
arena->curr = scope.curr;
|
||||||
if (arena->curr) {
|
if (arena->curr) {
|
||||||
Dqn_ArenaBlock *curr = arena->curr;
|
Dqn_ArenaBlock *curr = arena->curr;
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
curr->used = scope.curr_used;
|
||||||
reset_info.used_value = scope.curr_used;
|
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG curr, Dqn_ZeroMem_No, reset_info);
|
// NOTE: Reguard the pages
|
||||||
|
if (arena->use_after_free_guard)
|
||||||
|
Dqn_VMem_Protect(curr->memory, curr->commit, Dqn_VMemPage_ReadWrite | Dqn_VMemPage_Guard);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Free the tail blocks until we reach the scope's tail block
|
// NOTE: Free the tail blocks until we reach the scope's tail block
|
||||||
while (arena->tail != scope.tail) {
|
while (arena->tail != scope.tail) {
|
||||||
Dqn_ArenaBlock *tail = arena->tail;
|
Dqn_ArenaBlock *tail = arena->tail;
|
||||||
arena->tail = tail->prev;
|
arena->tail = tail->prev;
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
Dqn_VMem_Release(tail, sizeof(*tail) + tail->size);
|
||||||
reset_info.free_memory = true;
|
Dqn_Library_LeakTraceMarkFree(DQN_LEAK_TRACE_ARG tail);
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG tail, Dqn_ZeroMem_No, reset_info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Reset the usage of all the blocks between the tail and current block's
|
// NOTE: Reset the usage of all the blocks between the tail and current block's
|
||||||
if (arena->tail) {
|
if (arena->tail) {
|
||||||
arena->tail->next = nullptr;
|
arena->tail->next = nullptr;
|
||||||
for (Dqn_ArenaBlock *block = arena->tail; block && block != arena->curr; block = block->prev) {
|
for (Dqn_ArenaBlock *block = arena->tail; block && block != arena->curr; block = block->prev) {
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
block->used = 0;
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG block, Dqn_ZeroMem_No, reset_info);
|
|
||||||
|
// NOTE: Reguard the pages
|
||||||
|
if (arena->use_after_free_guard)
|
||||||
|
Dqn_VMem_Protect(block->memory, block->commit, Dqn_VMemPage_ReadWrite | Dqn_VMemPage_Guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6483,10 +6463,13 @@ DQN_API Dqn_ArenaBlock *Dqn_Arena_Grow_(DQN_LEAK_TRACE_FUNCTION Dqn_Arena *arena
|
|||||||
if (!arena || size == 0)
|
if (!arena || size == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Dqn_usize block_metadata_size = Dqn_Arena_BlockMetadataSize_(arena);
|
Dqn_usize block_metadata_size = sizeof(Dqn_ArenaBlock);
|
||||||
commit = DQN_MIN(commit, size);
|
if (arena->use_after_free_guard)
|
||||||
Dqn_usize reserve_aligned = Dqn_PowerOfTwoAlign(size + block_metadata_size, DQN_VMEM_RESERVE_GRANULARITY);
|
block_metadata_size = Dqn_PowerOfTwoAlign(block_metadata_size, DQN_VMEM_PAGE_GRANULARITY);
|
||||||
Dqn_usize commit_aligned = Dqn_PowerOfTwoAlign(commit + block_metadata_size, DQN_VMEM_COMMIT_GRANULARITY);
|
|
||||||
|
commit = DQN_MIN(commit, size);
|
||||||
|
Dqn_usize reserve_aligned = Dqn_PowerOfTwoAlign(size + block_metadata_size, DQN_VMEM_RESERVE_GRANULARITY);
|
||||||
|
Dqn_usize commit_aligned = Dqn_PowerOfTwoAlign(commit + block_metadata_size, DQN_VMEM_COMMIT_GRANULARITY);
|
||||||
DQN_ASSERT(commit_aligned < reserve_aligned);
|
DQN_ASSERT(commit_aligned < reserve_aligned);
|
||||||
|
|
||||||
// NOTE: If the commit amount is the same as reserve size we can save one
|
// NOTE: If the commit amount is the same as reserve size we can save one
|
||||||
@ -6515,9 +6498,9 @@ DQN_API Dqn_ArenaBlock *Dqn_Arena_Grow_(DQN_LEAK_TRACE_FUNCTION Dqn_Arena *arena
|
|||||||
result->flags = flags;
|
result->flags = flags;
|
||||||
result->arena = arena;
|
result->arena = arena;
|
||||||
|
|
||||||
// NOTE: Reset the block (this will guard the memory pages if required, otherwise no-op).
|
// NOTE: Guard all the committed pages in the memory block
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
if (arena->use_after_free_guard)
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG result, Dqn_ZeroMem_No, reset_info);
|
Dqn_VMem_Protect(result->memory, result->commit, page_flags | Dqn_VMemPage_Guard);
|
||||||
|
|
||||||
// NOTE: Attach the block to the arena
|
// NOTE: Attach the block to the arena
|
||||||
if (arena->tail) {
|
if (arena->tail) {
|
||||||
@ -6596,11 +6579,12 @@ DQN_API void Dqn_Arena_Free_(DQN_LEAK_TRACE_FUNCTION Dqn_Arena *arena, Dqn_ZeroM
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
while (arena->tail) {
|
while (arena->tail) {
|
||||||
Dqn_ArenaBlock *block = arena->tail;
|
Dqn_ArenaBlock *tail = arena->tail;
|
||||||
arena->tail = block->prev;
|
arena->tail = tail->prev;
|
||||||
Dqn_ArenaBlockResetInfo_ reset_info = {};
|
if (zero_mem == Dqn_ZeroMem_Yes)
|
||||||
reset_info.free_memory = true;
|
DQN_MEMSET(tail->memory, DQN_MEMSET_BYTE, tail->commit);
|
||||||
Dqn_Arena_BlockReset_(DQN_LEAK_TRACE_ARG block, zero_mem, reset_info);
|
Dqn_VMem_Release(tail, sizeof(*tail) + tail->size);
|
||||||
|
Dqn_Library_LeakTraceMarkFree(DQN_LEAK_TRACE_ARG tail);
|
||||||
}
|
}
|
||||||
|
|
||||||
arena->curr = arena->tail = nullptr;
|
arena->curr = arena->tail = nullptr;
|
||||||
|
Loading…
Reference in New Issue
Block a user