Skip to content

Commit

Permalink
More work with the memory arena implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
tanis2000 committed Mar 25, 2024
1 parent 728aeb9 commit 271c2cc
Show file tree
Hide file tree
Showing 8 changed files with 475 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .idea/fileTemplates/includes/C File Header.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ if(BINOCLE_SHOW_CONSOLE)
add_definitions(-DBINOCLE_SHOW_CONSOLE)
endif()

if(BINOCLE_LOG_MEMORY_ALLOCATIONS)
add_definitions(-DBINOCLE_LOG_MEMORY_ALLOCATIONS)
endif()

include(BinocleUtils)

SET(VERSION_MAJOR "0")
Expand Down
1 change: 1 addition & 0 deletions CMakeOptions.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
option(BINOCLE_LUAJIT "Enable LuaJIT on supported platforms (Windows, macOS)" OFF)
option(BINOCLE_SHOW_CONSOLE "Enable console output on Windows" OFF)
option(BINOCLE_HTTP "Enable HTTP support on supported platforms (Windows, macOS, web)" ON)
option(BINOCLE_LOG_MEMORY_ALLOCATIONS "Enable logging of memory allocations through the memory arena" OFF)
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# -- Project information -----------------------------------------------------

project = 'Binocle'
copyright = '2019-2021, Valerio Santinelli'
copyright = '2019-2023, Valerio Santinelli'
author = 'Valerio Santinelli'


Expand Down
10 changes: 10 additions & 0 deletions example/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "binocle_audio.h"
#include "sokol_gfx.h"
#include "binocle_http.h"
#include "binocle_memory.h"

//#define GAMELOOP 1
//#define DEMOLOOP
Expand Down Expand Up @@ -72,6 +73,10 @@ typedef struct screen_shader_vs_params_t {
float transform[16];
} screen_shader_vs_params_t;

typedef struct game_state_t {
binocle_memory_arena *main_arena;
} game_state_t;

binocle_window *window;
binocle_input input;
binocle_viewport_adapter *adapter;
Expand All @@ -97,6 +102,7 @@ sg_image render_target;
sg_shader default_shader;
sg_shader screen_shader;
sg_image wabbit_image;
game_state_t *game_state;

#if (defined(__APPLE__) && !defined(__IPHONEOS__)) || defined(__EMSCRIPTEN__)
#define WITH_PHYSICS
Expand Down Expand Up @@ -444,6 +450,10 @@ void main_loop() {

int main(int argc, char *argv[])
{
// binocle_memory_init();
// game_state = binocle_memory_bootstrap_push_struct(game_state_t, main_arena, binocle_memory_default_bootstrap_params(), binocle_memory_default_arena_params());
// binocle_string s1 = binocle_memory_push_cstring(game_state->main_arena, "Something");
// binocle_string s2 = binocle_memory_push_cstring(game_state->main_arena, "Different");
binocle_app_desc_t app_desc = {0};
app = binocle_app_new();
binocle_app_init(&app, &app_desc);
Expand Down
10 changes: 10 additions & 0 deletions src/binocle/core/binocle_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef BINOCLE_MATH_H
#define BINOCLE_MATH_H

#include <stdbool.h>
#include <stdint.h>
#include <kazmath/kazmath.h>

#ifndef MIN
Expand Down Expand Up @@ -65,4 +67,12 @@ static kmMat4 binocle_math_create_orthographic_matrix_off_center(
}
//#endif //BINOCLE_MATH_IMPL

static bool binocle_math_is_pow_2(uint32_t value)
{
bool result = ((value & ~(value - 1)) == value);
return result;
}

#define binocle_math_align_pow_2(value, alignment) (((value) + ((alignment) - 1)) & ~(((value) - (value)) + (alignment) - 1))

#endif //BINOCLE_MATH_H
297 changes: 297 additions & 0 deletions src/binocle/core/binocle_memory.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,297 @@
//
// Binocle
// Copyright (c) 2015-2019 Valerio Santinelli
// All rights reserved.
//

#include "binocle_memory.h"
#include "SDL_stdinc.h"
#include "binocle_math.h"
#include <assert.h>
#include <sys/mman.h>

static binocle_memory_state g_memory_state;

void binocle_memory_init() {
g_memory_state.memory_sentinel.prev = &g_memory_state.memory_sentinel;
g_memory_state.memory_sentinel.next = &g_memory_state.memory_sentinel;
}

binocle_memory_arena_push_params binocle_memory_default_arena_params(void) {
binocle_memory_arena_push_params params;
params.flags = BINOCLE_MEMORY_ARENA_PUSH_FLAG_CLEAR_TO_ZERO;
params.alignment = 4;
return params;
}

binocle_memory_arena_bootstrap_params
binocle_memory_default_bootstrap_params(void) {
binocle_memory_arena_bootstrap_params params = {};
return params;
}

binocle_memory_index
binocle_memory_get_alignment_offset(binocle_memory_arena *Arena,
binocle_memory_index alignment) {
binocle_memory_index alignment_offset = 0;

binocle_memory_index result_pointer =
(binocle_memory_index)Arena->current_block->base +
Arena->current_block->used;
binocle_memory_index alignment_mask = alignment - 1;
if (result_pointer & alignment_mask) {
alignment_offset = alignment - (result_pointer & alignment_mask);
}

return (alignment_offset);
}

binocle_memory_index
binocle_memory_get_effective_size_for(binocle_memory_arena *arena,
binocle_memory_index size_init,
binocle_memory_arena_push_params params) {
binocle_memory_index size = size_init;

binocle_memory_index alignment_offset =
binocle_memory_get_alignment_offset(arena, params.alignment);
size += alignment_offset;

return (size);
}

void binocle_memory_zero_size(binocle_memory_index size, void *ptr) {
uint8_t *byte = (uint8_t *)ptr;
while (size--) {
*byte++ = 0;
}
}

binocle_memory_block *binocle_memory_allocate(binocle_memory_index size,
uint64_t flags) {
// We require memory block headers not to change the cache
// line alignment of an allocation
assert(sizeof(binocle_memory_platform_block) == 56);

uintptr_t PageSize = 4096;
uintptr_t TotalSize = size + sizeof(binocle_memory_platform_block);
uintptr_t BaseOffset = sizeof(binocle_memory_platform_block);
uintptr_t ProtectOffset = 0;
if(flags & BINOCLE_MEMORY_FLAG_CHECK_UNDERFLOW)
{
TotalSize = size + 2*PageSize;
BaseOffset = 2*PageSize;
ProtectOffset = PageSize;
}
else if(flags & BINOCLE_MEMORY_FLAG_CHECK_OVERFLOW)
{
uintptr_t SizeRoundedUp = binocle_math_align_pow_2(size, PageSize);
TotalSize = SizeRoundedUp + 2*PageSize;
BaseOffset = PageSize + SizeRoundedUp - size;
ProtectOffset = PageSize + SizeRoundedUp;
}

binocle_memory_platform_block *Block = (binocle_memory_platform_block *)
mmap(0, TotalSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(Block != MAP_FAILED);
Block->block.base = (uint8_t *)Block + BaseOffset;
assert(Block->block.used == 0);
assert(Block->block.prev_arena == 0);

if(flags & (BINOCLE_MEMORY_FLAG_CHECK_UNDERFLOW|BINOCLE_MEMORY_FLAG_CHECK_OVERFLOW))
{
int Protected = mprotect((uint8_t *)Block + ProtectOffset, PageSize, PROT_NONE);
assert(Protected != -1);
}

binocle_memory_platform_block *Sentinel = &g_memory_state.memory_sentinel;
Block->next = Sentinel;
Block->block.size = size;
Block->block.flags = flags;
Block->prev = Sentinel->prev;
Block->prev->next = Block;
Block->next->prev = Block;

binocle_memory_block *PlatBlock = &Block->block;
return PlatBlock;
}




// binocle_memory_block *block = SDL_calloc(1, size);
// block->flags = flags;
// block->size = size;
// block->base = (uint8_t *)block;
// return block;
//}

void *
binocle_memory_push_size_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
binocle_memory_index size_init,
binocle_memory_arena_push_params params) {
void *result;

assert(params.alignment <= 128);
assert(binocle_math_is_pow_2(params.alignment));

binocle_memory_index size = 0;
if (arena->current_block) {
size = binocle_memory_get_effective_size_for(arena, size_init, params);
}

if (!arena->current_block ||
((arena->current_block->used + size) > arena->current_block->size)) {
size = size_init;
if (arena->allocation_flags & (BINOCLE_MEMORY_FLAG_CHECK_OVERFLOW |
BINOCLE_MEMORY_FLAG_CHECK_UNDERFLOW)) {
arena->minimum_block_size = 0;
size = binocle_math_align_pow_2(size, params.alignment);
} else if (!arena->minimum_block_size) {
arena->minimum_block_size = 1024 * 1024;
}

binocle_memory_index block_size = MAX(size, arena->minimum_block_size);

binocle_memory_block *new_block =
binocle_memory_allocate(block_size, arena->allocation_flags);
new_block->prev_arena = arena->current_block;
arena->current_block = new_block;
}

assert((arena->current_block->used + size) <= arena->current_block->size);

binocle_memory_index alignment_offset =
binocle_memory_get_alignment_offset(arena, params.alignment);
uintptr_t OffsetInBlock = arena->current_block->used + alignment_offset;
result = arena->current_block->base + OffsetInBlock;
arena->current_block->used += size;

assert(size >= size_init);
assert(arena->current_block->used <= arena->current_block->size);

if (params.flags & BINOCLE_MEMORY_ARENA_PUSH_FLAG_CLEAR_TO_ZERO) {
binocle_memory_zero_size(size_init, result);
}

return result;
}

void *binocle_memory_bootstrap_push_size(
BINOCLE_MEMORY_PARAM uintptr_t struct_size, uintptr_t offset_to_arena,
binocle_memory_arena_bootstrap_params bootstrap_params,
binocle_memory_arena_push_params push_params) {
binocle_memory_arena bootstrap = {};
bootstrap.allocation_flags = bootstrap_params.allocation_flags;
bootstrap.minimum_block_size = bootstrap_params.minimum_block_size;
void *res_struct = binocle_memory_push_size_(BINOCLE_MEMORY_PASS & bootstrap,
struct_size, push_params);
*(binocle_memory_arena *)((uint8_t *)res_struct + offset_to_arena) =
bootstrap;

return (res_struct);
}

uint32_t binocle_string_length(char *string) {
uint32_t count = 0;
if (string) {
while (*string++) {
++count;
}
}

return (count);
}

void *binocle_memory_copy(binocle_memory_index size, void *source_init,
void *dest_init) {
uint8_t *Source = (uint8_t *)source_init;
uint8_t *Dest = (uint8_t *)dest_init;
while (size--) {
*Dest++ = *Source++;
}

return dest_init;
}

binocle_memory_arena_push_params binocle_memory_no_clear(void) {
binocle_memory_arena_push_params params =
binocle_memory_default_arena_params();
params.flags &= ~BINOCLE_MEMORY_ARENA_PUSH_FLAG_CLEAR_TO_ZERO;
return params;
}

void *
binocle_memory_push_copy_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
uintptr_t size, void *source,
binocle_memory_arena_push_params params) {
void *result =
binocle_memory_push_size_(BINOCLE_MEMORY_PASS arena, size, params);
binocle_memory_copy(size, source, result);
return (result);
}

char *
binocle_memory_push_string_z_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
char *source) {
uint32_t size = 1;
for (char *At = source; *At; ++At) {
++size;
}

char *dest = (char *)binocle_memory_push_size_(
BINOCLE_MEMORY_PASS arena, size, binocle_memory_no_clear());
for (uint32_t char_index = 0; char_index < size; ++char_index) {
dest[char_index] = source[char_index];
}

return (dest);
}

binocle_buffer
binocle_memory_push_buffer_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
uintptr_t size,
binocle_memory_arena_push_params params) {
binocle_buffer result;
result.count = size;
result.data = (uint8_t *)binocle_memory_push_size_(BINOCLE_MEMORY_PASS arena,
result.count, params);

return (result);
}

binocle_string
binocle_memory_push_cstring_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
char *source) {
binocle_string result;
result.count = binocle_string_length(source);
result.data = (uint8_t *)binocle_memory_push_copy_(
BINOCLE_MEMORY_PASS arena, result.count, source,
binocle_memory_default_arena_params());

return (result);
}

binocle_string
binocle_memory_push_string_(BINOCLE_MEMORY_PARAM binocle_memory_arena *arena,
binocle_string source) {
binocle_string result;
result.count = source.count;
result.data = (uint8_t *)binocle_memory_push_copy_(
BINOCLE_MEMORY_PASS arena, result.count, source.data,
binocle_memory_default_arena_params());

return (result);
}

char *binocle_memory_push_and_null_terminate_(
BINOCLE_MEMORY_PARAM binocle_memory_arena *arena, uint32_t length,
const char *source) {
char *dest = (char *)binocle_memory_push_size_(
BINOCLE_MEMORY_PASS arena, length + 1, binocle_memory_no_clear());
for (uint32_t char_index = 0; char_index < length; ++char_index) {
dest[char_index] = source[char_index];
}
dest[length] = 0;

return (dest);
}
Loading

0 comments on commit 271c2cc

Please sign in to comment.