Compare commits
2 Commits
main
...
81300eca52
| Author | SHA1 | Date | |
|---|---|---|---|
| 81300eca52 | |||
| 1477f5b396 |
+36
-22
@@ -3,17 +3,21 @@
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
MemoryBlock *memoryblock_allocate(size_t size)
|
||||
MemoryBlock *memoryblock_allocate(size_t size, size_t commit_size)
|
||||
{
|
||||
void *base = memory_allocate(size);
|
||||
Assert(base != NULL);
|
||||
size_t aligned_size = AlignToPageEnd(size);
|
||||
size_t aligned_commit_size = AlignToPageEnd(commit_size);
|
||||
|
||||
MemoryBlock *block = (MemoryBlock *)base;
|
||||
block->base = (U8 *)base;
|
||||
block->size = size;
|
||||
block->pos = MemoryBlock_Header_Size;
|
||||
block->base_pos = 0;
|
||||
block->prev = NULL;
|
||||
MemoryBlock *block = memory_reserve(aligned_size);
|
||||
Assert(block != NULL);
|
||||
memory_commit(block, aligned_commit_size);
|
||||
|
||||
block->base = (U8 *)block;
|
||||
block->size = aligned_size;
|
||||
block->pos = MemoryBlock_Header_Size;
|
||||
block->base_pos = 0;
|
||||
block->prev = NULL;
|
||||
block->committed_pos = aligned_commit_size;
|
||||
|
||||
return block;
|
||||
}
|
||||
@@ -21,15 +25,17 @@ MemoryBlock *memoryblock_allocate(size_t size)
|
||||
void arena_init(Arena *arena, const ArenaParams *params)
|
||||
{
|
||||
Assert(params->size > MemoryBlock_Header_Size);
|
||||
Assert(params->size < (U32_Max - MemoryBlock_Header_Size - 1));
|
||||
Assert(params->size < (U32_Max - platform_page_size())); // keep last page for overflow detection
|
||||
Assert(IsPow2(params->commit_size));
|
||||
|
||||
MemoryBlock *block = memoryblock_allocate(params->size);
|
||||
MemoryBlock *block = memoryblock_allocate(params->size, params->commit_size);
|
||||
ASAN_UNPOISON_MEMORY_REGION(block, MemoryBlock_Header_Size);
|
||||
|
||||
arena->flags = params->flags;
|
||||
arena->checkpoint_level = 0;
|
||||
arena->current = block;
|
||||
arena->requested_size = params->size;
|
||||
arena->block_size = params->size;
|
||||
arena->commit_size = params->commit_size;
|
||||
|
||||
ASAN_POISON_MEMORY_REGION(&block->base[block->pos], memoryblock_available(block));
|
||||
}
|
||||
@@ -47,20 +53,22 @@ void arena_free(Arena *arena)
|
||||
|
||||
void *arena_push(Arena *arena, U32 size, U32 align)
|
||||
{
|
||||
Assert(size < (U32_Max - align - MemoryBlock_Header_Size - 1));
|
||||
Assert(size < (U32_Max - platform_page_size()));
|
||||
Assert(IsPow2(align));
|
||||
|
||||
MemoryBlock *block = arena->current;
|
||||
U32 start_pos = AlignUpPow2(block->pos, align);
|
||||
U32 available = memoryblock_available(block);
|
||||
U32 available = block->size - start_pos;
|
||||
|
||||
if (available < size) {
|
||||
U32 new_size = arena->requested_size; // original user requeted size
|
||||
if (new_size < size) {
|
||||
new_size = AlignUpPow2(size + MemoryBlock_Header_Size,align);
|
||||
U32 block_size = arena->block_size; // original user requested size
|
||||
U32 new_commit_size = arena->commit_size;
|
||||
if (size > block_size - MemoryBlock_Header_Size) {
|
||||
block_size = AlignUpPow2(size + MemoryBlock_Header_Size,align);
|
||||
new_commit_size = block_size;
|
||||
}
|
||||
|
||||
MemoryBlock *new_block = memoryblock_allocate(new_size);
|
||||
MemoryBlock *new_block = memoryblock_allocate(block_size, new_commit_size);
|
||||
new_block->base_pos = block->base_pos + block->size;
|
||||
new_block->prev = block;
|
||||
arena->current = new_block;
|
||||
@@ -71,7 +79,15 @@ void *arena_push(Arena *arena, U32 size, U32 align)
|
||||
U32 end_pos = start_pos + size;
|
||||
Assert(end_pos <= block->size);
|
||||
|
||||
U8 *mem = &block->base[start_pos];
|
||||
U8 *mem = &block->base[start_pos];
|
||||
if (block->committed_pos < end_pos) {
|
||||
// Commit more memory
|
||||
U32 aligned_end_pos = AlignToPageEnd(start_pos + size);
|
||||
|
||||
U32 aligned_size = RoundUpToMultiple(aligned_end_pos - block->committed_pos, arena->commit_size);
|
||||
memory_commit(&block->base[block->committed_pos], aligned_size);
|
||||
block->committed_pos += aligned_size;
|
||||
}
|
||||
block->pos = end_pos;
|
||||
|
||||
ASAN_UNPOISON_MEMORY_REGION(mem, size);
|
||||
@@ -92,9 +108,7 @@ void arena_pop_to(Arena *arena, U32 abs_pos)
|
||||
} else {
|
||||
U32 new_pos = abs_pos - block->base_pos;
|
||||
new_pos = Max(MemoryBlock_Header_Size, new_pos);
|
||||
// Note, when doing commit/release, new_pos <= current->pos
|
||||
// is the right thing . shouldn't be able to pop to larger than what's already commited
|
||||
Assert(new_pos <= block->size);
|
||||
Assert(new_pos <= block->committed_pos);
|
||||
block->pos = new_pos;
|
||||
ASAN_POISON_MEMORY_REGION(&block->base[block->pos], memoryblock_available(block));
|
||||
break;
|
||||
|
||||
+7
-3
@@ -7,6 +7,7 @@ typedef U32 ArenaFlags; // no flags defined yets
|
||||
typedef struct ArenaParams ArenaParams;
|
||||
struct ArenaParams {
|
||||
U32 size;
|
||||
U32 commit_size;
|
||||
ArenaFlags flags; // No flags defined yet
|
||||
};
|
||||
|
||||
@@ -14,15 +15,17 @@ typedef struct MemoryBlock MemoryBlock;
|
||||
struct MemoryBlock {
|
||||
U8 *base;
|
||||
U32 size;
|
||||
U32 base_pos; // absolute position of base relative to the first linked arena
|
||||
U32 pos; // start of next allocation
|
||||
U32 base_pos; // absolute position of base relative to the first linked arena
|
||||
U32 committed_pos;
|
||||
MemoryBlock *prev;
|
||||
};
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena {
|
||||
MemoryBlock *current;
|
||||
U32 requested_size;
|
||||
U32 block_size;
|
||||
U32 commit_size;
|
||||
ArenaFlags flags;
|
||||
S32 checkpoint_level;
|
||||
};
|
||||
@@ -50,7 +53,8 @@ ArenaCheckPoint arena_temp_begin(Arena *arena);
|
||||
void arena_temp_end(ArenaCheckPoint *checkpoint);
|
||||
void arena_pop_to(Arena *arena, U32 abs_pos);
|
||||
void arena_reset(Arena *arena);
|
||||
MemoryBlock *memoryblock_allocate(size_t size);
|
||||
MemoryBlock *memoryblock_allocate(size_t size, size_t commit_size);
|
||||
|
||||
|
||||
static INLINE U32 memoryblock_available(const MemoryBlock *block)
|
||||
{
|
||||
|
||||
+5
-4
@@ -107,6 +107,7 @@ typedef unsigned __int128 U128;
|
||||
#define AlignDownPow2(val, align) ((val) & ~((align) - 1UL))
|
||||
#define IsPow2(x) ((x) && !((x) & ((x) - 1UL)))
|
||||
#define IsPow2OrZero(x) (!((x) & ((x) - 1UL)))
|
||||
#define IsAlignedTo(x, y) (IsPow2(y) && !((x) & ((y) - 1UL)))
|
||||
|
||||
#define GetBit(val, idx) (((val) >> (idx)) & 1)
|
||||
// Get n_bits starting at idx going left
|
||||
@@ -132,7 +133,7 @@ typedef unsigned __int128 U128;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Round up x / y
|
||||
* Ceiling of X / y , or round up x / y
|
||||
* (e.g 100/9 == 12, 3/2 == 2)
|
||||
* x + y must not overflow.
|
||||
*
|
||||
@@ -140,7 +141,7 @@ typedef unsigned __int128 U128;
|
||||
* @param y denominator
|
||||
* @return x/y rounded up
|
||||
*/
|
||||
#define DivRoundUp(x, y) (((x) + ((y) - 1)) / (y))
|
||||
#define CeilDiv(x, y) (((x) + ((y) - 1)) / (y))
|
||||
|
||||
/**
|
||||
* Round x up to nearest multiple of y
|
||||
@@ -151,7 +152,7 @@ typedef unsigned __int128 U128;
|
||||
* @param y denominator
|
||||
* @return x rounded up to nearest multiple of y
|
||||
*/
|
||||
#define RoundUp(x, y) (DIV_ROUND_UP((x), (y)) * (y))
|
||||
#define RoundUpToMultiple(x, y) (CeilDiv((x), (y)) * (y))
|
||||
|
||||
/**
|
||||
* Round x down to nearest multiple of y
|
||||
@@ -162,7 +163,7 @@ typedef unsigned __int128 U128;
|
||||
* @param y denominator
|
||||
* @return x rounded down nearest multiple of y
|
||||
*/
|
||||
#define RoundDown(x, y) ((x) / (y) * (y))
|
||||
#define RounDownToMultiple(x, y) ((x) / (y) * (y))
|
||||
#define Clamp(val, min, max) (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
+23
-11
@@ -5,6 +5,7 @@
|
||||
|
||||
void arena_dump(const Arena *arena)
|
||||
{
|
||||
return;
|
||||
MemoryBlock *block = arena->current;
|
||||
puts("@@@@@@@@@@");
|
||||
while (block) {
|
||||
@@ -21,7 +22,10 @@ void arena_dump(const Arena *arena)
|
||||
static void arena_test_1(void)
|
||||
{
|
||||
ArenaParams arena_params = {};
|
||||
arena_params.size = 1024+MemoryBlock_Header_Size;
|
||||
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(8);
|
||||
arena_params.size = arena_size;
|
||||
arena_params.commit_size = commit_size;
|
||||
Arena arena;
|
||||
arena_init(&arena, &arena_params);
|
||||
arena_dump(&arena);
|
||||
@@ -43,22 +47,28 @@ static void arena_test_1(void)
|
||||
static void arena_test_2(void)
|
||||
{
|
||||
ArenaParams arena_params = {};
|
||||
arena_params.size = 1024+MemoryBlock_Header_Size;
|
||||
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(16);
|
||||
U32 push_size = KB(32);
|
||||
arena_params.size = arena_size;
|
||||
arena_params.commit_size = commit_size;
|
||||
Arena arena;
|
||||
arena_init(&arena, &arena_params);
|
||||
|
||||
void *ptr;
|
||||
ptr = arena_push(&arena, 1024, 8);
|
||||
MemoryZero(ptr, 1024);
|
||||
ptr = arena_push(&arena, push_size, 8);
|
||||
MemoryZero(ptr, push_size);
|
||||
printf("Allocated ptr %p\n", ptr);
|
||||
|
||||
arena_dump(&arena);
|
||||
ArenaCheckPoint checkpoint = arena_temp_begin(&arena);
|
||||
ptr = arena_push(&arena, 4096, 8);
|
||||
MemoryZero(ptr, 4096);
|
||||
ptr = arena_push(&arena, MB(2), 8);
|
||||
MemoryZero(ptr, MB(2));
|
||||
|
||||
ptr = arena_push(&arena, 4096, 8);
|
||||
MemoryZero(ptr, 4096);
|
||||
ptr = arena_push(&arena, commit_size * 3, 8);
|
||||
MemoryZero(ptr, commit_size * 3 );
|
||||
ptr = arena_push(&arena, commit_size , 8);
|
||||
MemoryZero(ptr, commit_size );
|
||||
|
||||
ArenaCheckPoint checkpoint2 = arena_temp_begin(&arena);
|
||||
ptr = arena_push(&arena, 64, 8);
|
||||
@@ -69,9 +79,11 @@ static void arena_test_2(void)
|
||||
arena_temp_end(&checkpoint);
|
||||
arena_pop_to(&arena, 1088);
|
||||
arena_dump(&arena);
|
||||
ptr = arena_push(&arena, 1, 1);
|
||||
ptr = arena_push(&arena, 1, KB(16));
|
||||
((U8*)ptr)[0] = 0x37;
|
||||
ptr = arena_push(&arena, 1, 1);
|
||||
ptr = arena_push(&arena, 1, KB(16));
|
||||
((U8*)ptr)[0] = 0x73;
|
||||
ptr = arena_push(&arena, 1, KB(4));
|
||||
((U8*)ptr)[0] = 0x73;
|
||||
arena_pop_to(&arena, 1089);
|
||||
arena_dump(&arena);
|
||||
@@ -82,6 +94,6 @@ static void arena_test_2(void)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
arena_test_1();
|
||||
//arena_test_1();
|
||||
arena_test_2();
|
||||
}
|
||||
|
||||
+31
-36
@@ -1,30 +1,18 @@
|
||||
#include "base_core.h"
|
||||
#include "platform.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
#define IsPageAligned(x) (IsAlignedTo(x, platform_page_size()))
|
||||
|
||||
U32 platform_page_size(void)
|
||||
{
|
||||
return getpagesize();
|
||||
}
|
||||
|
||||
static INLINE size_t AlignToPageSize(size_t size)
|
||||
{
|
||||
U32 page_size = platform_page_size();
|
||||
size_t aligned_size = AlignUpPow2(size, page_size);
|
||||
|
||||
return aligned_size;
|
||||
}
|
||||
|
||||
static INLINE size_t AlignToPageStart(size_t size)
|
||||
{
|
||||
U32 page_size = platform_page_size();
|
||||
size_t aligned_size = AlignDownPow2(size, page_size);
|
||||
|
||||
return aligned_size;
|
||||
}
|
||||
|
||||
void *platform_malloc(size_t size)
|
||||
{
|
||||
@@ -39,13 +27,10 @@ void platform_free(void *mem)
|
||||
|
||||
void *memory_allocate(size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
size = 1;
|
||||
}
|
||||
Assert(IsPow2(size));
|
||||
|
||||
size_t aligned_size = AlignToPageSize(size);
|
||||
void *mem = mmap(0, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
TRACEF("memory_allocate size=%zu aligned_size=%zu mem=%p\n", size, aligned_size, mem);
|
||||
void *mem = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
TRACEF("memory_allocate size=%zu mem=%p\n", size, mem);
|
||||
if (mem == MAP_FAILED) {
|
||||
mem = NULL;
|
||||
}
|
||||
@@ -54,36 +39,46 @@ void *memory_allocate(size_t size)
|
||||
|
||||
void memory_free(void *mem, size_t size)
|
||||
{
|
||||
size_t aligned_size = AlignToPageSize(size);
|
||||
TRACEF(" memory_free size=%zu aligned_size=%zu mem=%p\n", size, aligned_size, mem);
|
||||
|
||||
int rc = munmap(mem, aligned_size);
|
||||
TRACEF(" memory_free size=%zu mem=%p\n", size, mem);
|
||||
Assert(IsPageAligned((uintptr_t)mem));
|
||||
Assert(IsPageAligned(size));
|
||||
int rc = munmap(mem, size);
|
||||
|
||||
Assert(rc == 0);
|
||||
|
||||
}
|
||||
void *memory_reserve(size_t size)
|
||||
{
|
||||
Assert(IsPageAligned(size));
|
||||
void *mem = mmap(0, size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
TRACEF("memory_reserve size=%zu mem=%p\n", size, mem);
|
||||
if (mem == MAP_FAILED) {
|
||||
mem = NULL;
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
void memory_commit(void *mem, size_t size)
|
||||
{
|
||||
size_t aligned_size = AlignToPageSize(size);
|
||||
void *aligned_mem = (void *)AlignToPageStart((uintptr_t)mem);
|
||||
TRACEF("memory_commit size=%zu aligned_size=%zu ptr=%p aligned_mem=%p\n", size, aligned_size, mem, aligned_mem);
|
||||
Assert(IsPageAligned((uintptr_t)mem));
|
||||
Assert(IsPageAligned(size));
|
||||
TRACEF("memory_commit size=%zu mem=%p\n", size, mem);
|
||||
|
||||
int rc;
|
||||
rc = mprotect(aligned_mem, aligned_size, PROT_READ | PROT_WRITE);
|
||||
rc = mprotect(mem, size, PROT_READ | PROT_WRITE);
|
||||
Assert(rc == 0);
|
||||
rc = madvise(aligned_mem, aligned_size, MADV_WILLNEED);
|
||||
rc = madvise(mem, size, MADV_WILLNEED);
|
||||
Assert(rc == 0);
|
||||
}
|
||||
|
||||
void memory_decommit(void *mem, size_t size)
|
||||
{
|
||||
size_t aligned_size = AlignToPageSize(size);
|
||||
void *aligned_mem = (void *)AlignToPageStart((uintptr_t)mem);
|
||||
TRACEF("memory_commit size=%zu aligned_size=%zu ptr=%p aligned_mem=%p\n", size, aligned_size, mem, aligned_mem);
|
||||
|
||||
TRACEF("memory_decommit size=%zu mem=%p\n", size, mem);
|
||||
Assert(IsPageAligned((uintptr_t)mem));
|
||||
Assert(IsPageAligned(size));
|
||||
int rc;
|
||||
rc = mprotect(aligned_mem, aligned_size, PROT_NONE);
|
||||
rc = mprotect(mem, size, PROT_NONE);
|
||||
Assert(rc == 0);
|
||||
rc = madvise(aligned_mem, aligned_size, MADV_DONTNEED);
|
||||
rc = madvise(mem, size, MADV_DONTNEED);
|
||||
Assert(rc == 0);
|
||||
}
|
||||
|
||||
+21
-2
@@ -2,9 +2,28 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
void *platform_malloc(size_t size);
|
||||
void platform_free(void *mem);
|
||||
U32 platform_page_size(void);
|
||||
|
||||
void *memory_allocate(size_t size);
|
||||
void *memory_free(void *mem, size_t size);
|
||||
void *memory_reserve(size_t size);
|
||||
void memory_commit(void *mem, size_t size);
|
||||
void memory_decommit(void *mem, size_t size);
|
||||
|
||||
void memory_free(void *mem, size_t size);
|
||||
|
||||
|
||||
static INLINE size_t AlignToPageEnd(size_t size)
|
||||
{
|
||||
U32 page_size = platform_page_size();
|
||||
size_t aligned_size = AlignUpPow2(size, page_size);
|
||||
|
||||
return aligned_size;
|
||||
}
|
||||
|
||||
static INLINE size_t AlignToPageStart(size_t size)
|
||||
{
|
||||
U32 page_size = platform_page_size();
|
||||
size_t aligned_size = AlignDownPow2(size, page_size);
|
||||
|
||||
return aligned_size;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user