Removing heap allocations, Porting to Unix

This commit is contained in:
Krzosa Karol
2022-10-09 10:34:23 +02:00
parent aa2b4d90e4
commit b22e1ac0db
13 changed files with 260 additions and 269 deletions

286
base.cpp
View File

@@ -1,7 +1,79 @@
#define NOMINMAX
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#if defined(__clang__)
# define COMPILER_CLANG 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__linux__)
# define OS_LINUX 1
# else
# error Couldnt figure out the platform automatically
# endif
#elif defined(_MSC_VER)
# define COMPILER_MSVC 1
# define OS_WINDOWS 1
#elif defined(__GNUC__)
# define COMPILER_GCC 1
# if defined(__linux__)
# define OS_LINUX 1
# endif
#else
# error Couldnt figure out the compiler
#endif
#if defined(OS_MAC)
#define OS_UNIX 1
#endif
#if defined(OS_LINUX)
#define OS_UNIX 1
#endif
#if !defined(COMPILER_MSVC)
# define COMPILER_MSVC 0
#endif
#if !defined(COMPILER_GCC)
# define COMPILER_GCC 0
#endif
#if !defined(COMPILER_CLANG)
# define COMPILER_CLANG 0
#endif
#if !defined(OS_WINDOWS)
# define OS_WINDOWS 0
#endif
#if !defined(OS_LINUX)
# define OS_LINUX 0
#endif
#if !defined(OS_MAC)
# define OS_MAC 0
#endif
#if !defined(OS_UNIX)
# define OS_UNIX 0
#endif
#if OS_WINDOWS
#define OS_NAME "Win32"_s
#define OS_NAME_LOWER "win32"_s
#elif OS_LINUX
#define OS_NAME "Linux"_s
#define OS_NAME_LOWER "linux"_s
#elif OS_MAC
#define OS_NAME "Mac"_s
#define OS_NAME_LOWER "mac"_s
#else
#error Couldnt figure out the OS with C macros!
#endif
#if OS_WINDOWS
#define NOMINMAX
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#define Breakpoint __debugbreak()
#define force_inline __forceinline
#else
#define Breakpoint (*(volatile int *)0 = 0)
#define force_inline inline
#endif
#include <stdlib.h>
#include <float.h>
#include <stdint.h>
typedef int8_t S8;
@@ -16,12 +88,10 @@ typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef U64 SizeU;
typedef S64 SizeS;
typedef float F32;
typedef double F64;
#define U64MAX UINT64_MAX
#define U32MAX UINT32_MAX
#define U16MAX UINT16_MAX
@@ -46,13 +116,12 @@ typedef double F64;
#define api
#define function static
#define global static
#define force_inline __forceinline
#define assert(x) do{if(!(x))__debugbreak();}while(0)
#define assert_msg(x,...) assert(x)
#define invalid_codepath assert_msg(0, "Invalid codepath")
#define invalid_return do{assert_msg(0, "Invalid codepath"); return {};}while(0)
#define assert(x) do{if(!(x))Breakpoint;}while(0)
#define assert_message(x,...) assert(x)
#define invalid_codepath assert_message(0, "Invalid codepath")
#define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0)
#define invalid_default_case default: invalid_codepath
#define not_implemented assert_msg(0, "Not implemented")
#define not_implemented assert_message(0, "Not implemented")
#define unused(x) ((void)x)
#define buff_cap(x) (sizeof(x)/sizeof((x)[0]))
#define is_flag_set(val,flag) ((val) & (flag))
@@ -66,59 +135,6 @@ typedef double F64;
#define JOIN(X,Y) JOIN1(X,Y)
#define string_expand(x) (int)x.len, x.str
#if defined(__clang__)
# define COMPILER_CLANG 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__linux__)
# define OS_LINUX 1
# else
# error Couldnt figure out the platform automatically
# endif
#elif defined(_MSC_VER)
# define COMPILER_MSVC 1
# define OS_WINDOWS 1
#elif defined(__GNUC__)
# define COMPILER_GCC 1
# if defined(__linux__)
# define OS_LINUX 1
# endif
#else
# error Couldnt figure out the compiler
#endif
#if !defined(COMPILER_MSVC)
# define COMPILER_MSVC 0
#endif
#if !defined(COMPILER_GCC)
# define COMPILER_GCC 0
#endif
#if !defined(COMPILER_CLANG)
# define COMPILER_CLANG 0
#endif
#if !defined(OS_WINDOWS)
# define OS_WINDOWS 0
#endif
#if !defined(OS_LINUX)
# define OS_LINUX 0
#endif
#if !defined(OS_MAC)
# define OS_MAC 0
#endif
#if OS_WINDOWS
#define OS_NAME "Win32"_s
#define OS_NAME_LOWER "win32"_s
#elif OS_LINUX
#define OS_NAME "Linux"_s
#define OS_NAME_LOWER "linux"_s
#elif OS_MAC
#define OS_NAME "Mac"_s
#define OS_NAME_LOWER "mac"_s
#else
#error Couldnt figure out the OS with C macros!
#endif
struct String{
U8 *str;
S64 len;
@@ -210,42 +226,42 @@ union Rect2I {
//-----------------------------------------------------------------------------
// Utilities
//-----------------------------------------------------------------------------
function SizeU
get_align_offset(SizeU size, SizeU align){
SizeU mask = align - 1;
SizeU val = size & mask;
function size_t
get_align_offset(size_t size, size_t align){
size_t mask = align - 1;
size_t val = size & mask;
if(val){
val = align - val;
}
return val;
}
function SizeU
align_up(SizeU size, SizeU align){
SizeU result = size + get_align_offset(size, align);
function size_t
align_up(size_t size, size_t align){
size_t result = size + get_align_offset(size, align);
return result;
}
function SizeU
align_down(SizeU size, SizeU align){
function size_t
align_down(size_t size, size_t align){
size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0
SizeU result = size - (align - get_align_offset(size, align));
size_t result = size - (align - get_align_offset(size, align));
return result;
}
function void
memory_copy(void *dst, void *src, SizeU size){
memory_copy(void *dst, void *src, size_t size){
U8 *d = (U8*)dst;
U8 *s = (U8*)src;
for(SizeU i = 0; i < size; i++){
for(size_t i = 0; i < size; i++){
d[i] = s[i];
}
}
function void
memory_zero(void *p, SizeU size){
memory_zero(void *p, size_t size){
U8 *pp = (U8 *)p;
for(SizeU i = 0; i < size; i++)
for(size_t i = 0; i < size; i++)
pp[i] = 0;
}
@@ -480,47 +496,47 @@ enum Alloc_Flag{
};
struct Allocator;
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, SizeU);
typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, size_t);
struct Allocator{Allocator_Kind kind; Allocator_Proc *proc; String debug_name;};
//-----------------------------------------------------------------------------
// Memory OS
//-----------------------------------------------------------------------------
struct OS_Memory{
SizeU commit, reserve;
size_t commit, reserve;
U8 *data;
};
function OS_Memory os_reserve(SizeU size);
function B32 os_commit(OS_Memory *m, SizeU size);
function OS_Memory os_reserve(size_t size);
function B32 os_commit(OS_Memory *m, size_t size);
function void os_release(OS_Memory *m);
function B32 os_decommit_pos(OS_Memory *m, SizeU pos);
function B32 os_decommit_pos(OS_Memory *m, size_t pos);
//-----------------------------------------------------------------------------
// Memory arenas
//-----------------------------------------------------------------------------
global const SizeU default_reserve_size = gib(4);
global const SizeU default_alignment = 8;
global const SizeU additional_commit_size = mib(1);
global const size_t default_reserve_size = gib(4);
global const size_t default_alignment = 8;
global const size_t additional_commit_size = mib(1);
struct Arena:Allocator{
OS_Memory memory;
SizeU alignment;
SizeU len;
size_t alignment;
size_t len;
// Personal arena memes so we can compute correct size when resizing
// Also a pointer so that we can make sure it didn't change
SizeU old_size;
size_t old_size;
void *debug_prev_pointer;
};
function void arena_init(Arena *arena, String debug_name);
function void
arena_pop_pos(Arena *arena, SizeU pos){
arena_pop_pos(Arena *arena, size_t pos){
pos = clamp_top(pos, arena->len);
arena->len = pos;
}
function void *
arena_pop(Arena *arena, SizeU size){
arena_pop(Arena *arena, size_t size){
size = clamp_top(size, arena->len);
arena->len -= size;
return arena->memory.data + arena->len;
@@ -537,8 +553,8 @@ arena_clear(Arena *arena){
}
function void *
arena_push_size(Arena *a, SizeU size){
SizeU generous_size = size + a->alignment;
arena_push_size(Arena *a, size_t size){
size_t generous_size = size + a->alignment;
if(a->len+generous_size>a->memory.commit){
if(a->memory.reserve == 0){
arena_init(a, "Zero initialized arena"_s);
@@ -555,7 +571,7 @@ arena_push_size(Arena *a, SizeU size){
}
force_inline void *
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
Arena *arena = (Arena *)a;
switch(kind){
case Allocation_Alloc: return arena_push_size(arena, size);
@@ -573,7 +589,7 @@ arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, Size
}
force_inline void *
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){
Arena *arena = (Arena *)a;
arena->alignment = 1;
@@ -614,59 +630,6 @@ arena_make_personal(String debug_name){
return arena;
}
//-----------------------------------------------------------------------------
// OS Heap allocator
//-----------------------------------------------------------------------------
struct OS_Heap:Allocator{
HANDLE handle;
};
function void *
os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){
OS_Heap *heap = (OS_Heap *)a;
switch(kind){
case Allocation_FreeAll:{
invalid_codepath;
return 0;
}
case Allocation_Destroy:{
BOOL result = HeapDestroy(heap->handle);
assert(result != 0);
heap->handle = 0;
heap->proc = 0;
return 0;
}
case Allocation_Free:{
BOOL result = HeapFree(heap->handle, 0, old_pointer);
assert(result != 0);
return 0;
}
case Allocation_Alloc:{
void *result = HeapAlloc(heap->handle, 0, size);
assert(result);
return result;
}
case Allocation_Resize:{
void *result = HeapReAlloc(heap->handle, 0, old_pointer, size);
assert(result);
return result;
}
default: invalid_codepath;
}
return 0;
}
function OS_Heap // max_size == 0 == growing heap
win32_os_heap_create(B32 multithreaded, SizeU initial_size, SizeU max_size, String debug_name){
OS_Heap result = {};
result.debug_name = debug_name;
result.proc = os_heap_allocator_proc;
result.kind = Allocator_OSHeap;
result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size);
assert(result.handle);
return result;
}
enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace};
typedef void Log_Proc(Log_Kind kind, String string, char *file, int line);
//-----------------------------------------------------------------------------
@@ -684,7 +647,6 @@ struct Thread_Ctx{
thread_local Thread_Ctx thread_ctx;
global Arena pernament_arena;
global OS_Heap os_process_heap;
#define REPORT_ALLOCATIONS 0
#define report_file_and_line() report__file_and_line(__FILE__, __LINE__)
@@ -698,7 +660,7 @@ report__file_and_line(const char *file, int line){
// Implicit scratch stack
//-----------------------------------------------------------------------------
struct Scratch{
SizeU saved_pos;
size_t saved_pos;
Arena *arena;
Scratch(Allocator *conflict = 0){
@@ -749,7 +711,7 @@ struct Scoped_Allocator{
#define exp_destroy(a) (report_file_and_line(), exp__destroy(a))
force_inline void *
exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
exp__alloc(Allocator *a, size_t size, Alloc_Flag flag = AF_None){
#if REPORT_ALLOCATIONS
printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
#endif
@@ -759,7 +721,7 @@ exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){
return result;
}
force_inline void *
exp__resize(Allocator *a, void *pointer, SizeU size){
exp__resize(Allocator *a, void *pointer, size_t size){
#if REPORT_ALLOCATIONS
printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size);
#endif
@@ -801,10 +763,6 @@ thread_ctx_init(){
arena_init(thread_ctx.scratch, "Scratch1"_s);
arena_init(thread_ctx.scratch+1, "Scratch2"_s);
arena_init(&pernament_arena, "Pernament Arena"_s);
os_process_heap.proc = os_heap_allocator_proc;
os_process_heap.handle = GetProcessHeap();
os_process_heap.debug_name = "Win32 Process Heap"_s;
os_process_heap.kind = Allocator_OSHeap;
}
@@ -847,7 +805,7 @@ struct Array{
S64 get_index(T *item){
assert((data <= item) && ((data + len) > item));
SizeU offset = item - data;
size_t offset = item - data;
return (S64)offset;
}
@@ -1145,12 +1103,12 @@ function void
map_test(){
Scratch scratch;
Map map = {scratch};
const SizeU size = 1025;
for(SizeU i = 1; i < size; i++){
const size_t size = 1025;
for(size_t i = 1; i < size; i++){
map_insert(&map, i, (void *)i);
}
for(SizeU i = 1; i < size; i++){
SizeU val = (SizeU)map_get(&map, i);
for(size_t i = 1; i < size; i++){
size_t val = (size_t)map_get(&map, i);
assert(val == i);
}
}
@@ -1208,7 +1166,7 @@ test_intern_table(){
}
function Arena
arena_sub(Allocator *base, SizeU size, String debug_name) {
arena_sub(Allocator *base, size_t size, String debug_name) {
Arena result = {};
result.memory.data = (U8 *)exp_alloc(base, size);
result.memory.commit = size;
@@ -1443,7 +1401,7 @@ T pop(List<T> *list){
template<class T>
T *merge(Arena *arena, List<T> *list){
int len = length(list);
T *result = push_array(arena, T, len);
T *result = exp_alloc_array(arena, T, len);
int i = 0;
For_Linked_List(list->first){