base memory allocator and chunked arenas for orca
This commit is contained in:
parent
f36e144bc0
commit
e9e9ab68c2
|
@ -14,7 +14,7 @@
|
||||||
#include"graphics_internal.h"
|
#include"graphics_internal.h"
|
||||||
#include"gl_loader.h"
|
#include"gl_loader.h"
|
||||||
|
|
||||||
#if OS_MACOS
|
#if PLATFORM_MACOS
|
||||||
//NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly
|
//NOTE: EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE on osx defaults to CGL backend, which doesn't handle SwapInterval correctly
|
||||||
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
|
#define MG_EGL_PLATFORM_ANGLE_TYPE EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE
|
||||||
|
|
||||||
|
|
|
@ -85,11 +85,14 @@ typedef struct mg_handle_slot
|
||||||
|
|
||||||
} mg_handle_slot;
|
} mg_handle_slot;
|
||||||
|
|
||||||
|
static const u32 MG_HANDLES_MAX_COUNT = 512;
|
||||||
|
|
||||||
typedef struct mg_data
|
typedef struct mg_data
|
||||||
{
|
{
|
||||||
bool init;
|
bool init;
|
||||||
|
|
||||||
mem_arena handleArena;
|
mg_handle_slot handleArray[MG_HANDLES_MAX_COUNT];
|
||||||
|
int handleNextIndex;
|
||||||
list_info handleFreeList;
|
list_info handleFreeList;
|
||||||
|
|
||||||
mem_arena resourceArena;
|
mem_arena resourceArena;
|
||||||
|
@ -146,7 +149,7 @@ void mg_init()
|
||||||
{
|
{
|
||||||
if(!__mgData.init)
|
if(!__mgData.init)
|
||||||
{
|
{
|
||||||
mem_arena_init(&__mgData.handleArena);
|
__mgData.handleNextIndex = 0;
|
||||||
mem_arena_init(&__mgData.resourceArena);
|
mem_arena_init(&__mgData.resourceArena);
|
||||||
__mgData.init = true;
|
__mgData.init = true;
|
||||||
}
|
}
|
||||||
|
@ -162,21 +165,24 @@ u64 mg_handle_alloc(mg_handle_kind kind, void* data)
|
||||||
{
|
{
|
||||||
mg_init();
|
mg_init();
|
||||||
}
|
}
|
||||||
mem_arena* arena = &__mgData.handleArena;
|
|
||||||
|
|
||||||
mg_handle_slot* slot = list_pop_entry(&__mgData.handleFreeList, mg_handle_slot, freeListElt);
|
mg_handle_slot* slot = list_pop_entry(&__mgData.handleFreeList, mg_handle_slot, freeListElt);
|
||||||
if(!slot)
|
if(!slot && __mgData.handleNextIndex < MG_HANDLES_MAX_COUNT)
|
||||||
{
|
{
|
||||||
slot = mem_arena_alloc_type(arena, mg_handle_slot);
|
slot = &__mgData.handleArray[__mgData.handleNextIndex];
|
||||||
DEBUG_ASSERT(slot);
|
__mgData.handleNextIndex++;
|
||||||
|
|
||||||
slot->generation = 1;
|
slot->generation = 1;
|
||||||
}
|
}
|
||||||
|
u64 h = 0;
|
||||||
|
if(slot)
|
||||||
|
{
|
||||||
slot->kind = kind;
|
slot->kind = kind;
|
||||||
slot->data = data;
|
slot->data = data;
|
||||||
|
|
||||||
u64 h = ((u64)(slot - (mg_handle_slot*)arena->ptr))<<32
|
h = ((u64)(slot - __mgData.handleArray))<<32
|
||||||
|((u64)(slot->generation));
|
|((u64)(slot->generation));
|
||||||
|
}
|
||||||
return(h);
|
return(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,11 +192,10 @@ void mg_handle_recycle(u64 h)
|
||||||
|
|
||||||
u32 index = h>>32;
|
u32 index = h>>32;
|
||||||
u32 generation = h & 0xffffffff;
|
u32 generation = h & 0xffffffff;
|
||||||
mem_arena* arena = &__mgData.handleArena;
|
|
||||||
|
|
||||||
if(index*sizeof(mg_handle_slot) < arena->offset)
|
if(index*sizeof(mg_handle_slot) < __mgData.handleNextIndex)
|
||||||
{
|
{
|
||||||
mg_handle_slot* slot = (mg_handle_slot*)arena->ptr + index;
|
mg_handle_slot* slot = &__mgData.handleArray[index];
|
||||||
if(slot->generation == generation)
|
if(slot->generation == generation)
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(slot->generation != UINT32_MAX, "surface slot generation wrap around\n");
|
DEBUG_ASSERT(slot->generation != UINT32_MAX, "surface slot generation wrap around\n");
|
||||||
|
@ -208,11 +213,10 @@ void* mg_data_from_handle(mg_handle_kind kind, u64 h)
|
||||||
|
|
||||||
u32 index = h>>32;
|
u32 index = h>>32;
|
||||||
u32 generation = h & 0xffffffff;
|
u32 generation = h & 0xffffffff;
|
||||||
mem_arena* arena = &__mgData.handleArena;
|
|
||||||
|
|
||||||
if(index*sizeof(mg_handle_slot) < arena->offset)
|
if(index < __mgData.handleNextIndex)
|
||||||
{
|
{
|
||||||
mg_handle_slot* slot = (mg_handle_slot*)arena->ptr + index;
|
mg_handle_slot* slot = &__mgData.handleArray[index];
|
||||||
if( slot->generation == generation
|
if( slot->generation == generation
|
||||||
&& slot->kind == kind)
|
&& slot->kind == kind)
|
||||||
{
|
{
|
||||||
|
@ -278,10 +282,10 @@ mg_image_data* mg_image_data_from_handle(mg_image handle)
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#if MG_COMPILE_BACKEND_GL
|
#if MG_COMPILE_BACKEND_GL
|
||||||
#if defined(OS_WIN64)
|
#if defined(PLATFORM_WIN64)
|
||||||
#include"wgl_surface.h"
|
#include"wgl_surface.h"
|
||||||
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
#define gl_surface_create_for_window mg_wgl_surface_create_for_window
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(PLATFORM_MACOS)
|
||||||
/*
|
/*
|
||||||
#include"nsgl_surface.h"
|
#include"nsgl_surface.h"
|
||||||
#define gl_surface_create_for_window nsgl_surface_create_for_window
|
#define gl_surface_create_for_window nsgl_surface_create_for_window
|
||||||
|
@ -328,7 +332,7 @@ bool mg_is_canvas_backend_available(mg_backend_id backend)
|
||||||
#if MG_COMPILE_BACKEND_METAL
|
#if MG_COMPILE_BACKEND_METAL
|
||||||
case MG_BACKEND_METAL:
|
case MG_BACKEND_METAL:
|
||||||
#endif
|
#endif
|
||||||
#if MG_COMPILE_BACKEND_GL && defined(OS_WIN64)
|
#if MG_COMPILE_BACKEND_GL && defined(PLATFORM_WIN64)
|
||||||
case MG_BACKEND_GL:
|
case MG_BACKEND_GL:
|
||||||
#endif
|
#endif
|
||||||
result = true;
|
result = true;
|
||||||
|
@ -417,9 +421,9 @@ mg_surface mg_surface_create_host(mp_window window)
|
||||||
}
|
}
|
||||||
mg_surface handle = mg_surface_nil();
|
mg_surface handle = mg_surface_nil();
|
||||||
mg_surface_data* surface = 0;
|
mg_surface_data* surface = 0;
|
||||||
#if OS_MACOS
|
#if PLATFORM_MACOS
|
||||||
surface = mg_osx_surface_create_host(window);
|
surface = mg_osx_surface_create_host(window);
|
||||||
#elif OS_WIN64
|
#elif PLATFORM_WIN64
|
||||||
surface = mg_win32_surface_create_host(window);
|
surface = mg_win32_surface_create_host(window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ typedef enum {
|
||||||
|
|
||||||
//NOTE: these macros are used to select which backend to include when building milepost
|
//NOTE: these macros are used to select which backend to include when building milepost
|
||||||
// they can be overridden by passing them to the compiler command line
|
// they can be overridden by passing them to the compiler command line
|
||||||
#if defined(OS_MACOS)
|
#if defined(PLATFORM_MACOS)
|
||||||
#ifndef MG_COMPILE_BACKEND_METAL
|
#ifndef MG_COMPILE_BACKEND_METAL
|
||||||
#define MG_COMPILE_BACKEND_METAL 1
|
#define MG_COMPILE_BACKEND_METAL 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -45,7 +45,7 @@ typedef enum {
|
||||||
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(OS_WIN64)
|
#elif defined(PLATFORM_WIN64)
|
||||||
#ifndef MG_COMPILE_BACKEND_GL
|
#ifndef MG_COMPILE_BACKEND_GL
|
||||||
#define MG_COMPILE_BACKEND_GL 1
|
#define MG_COMPILE_BACKEND_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,7 +60,7 @@ typedef enum {
|
||||||
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
#define MG_BACKEND_DEFAULT MG_BACKEND_NONE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(PLATFORM_LINUX)
|
||||||
#ifndef MG_COMPILE_BACKEND_GL
|
#ifndef MG_COMPILE_BACKEND_GL
|
||||||
#define MG_COMPILE_BACKEND_GL 1
|
#define MG_COMPILE_BACKEND_GL 1
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,12 +22,12 @@
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
|
|
||||||
#if defined(OS_WIN64)
|
#if defined(PLATFORM_WIN64)
|
||||||
#include"platform/win32_base_allocator.c"
|
#include"platform/win32_memory.c"
|
||||||
#include"platform/win32_clock.c"
|
#include"platform/win32_clock.c"
|
||||||
//TODO
|
//TODO
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(PLATFORM_MACOS)
|
||||||
#include"platform/unix_base_allocator.c"
|
#include"platform/unix_memory.c"
|
||||||
#include"platform/osx_clock.c"
|
#include"platform/osx_clock.c"
|
||||||
/*
|
/*
|
||||||
#include"platform/unix_rng.c"
|
#include"platform/unix_rng.c"
|
||||||
|
@ -35,8 +35,8 @@
|
||||||
#include"platform/posix_socket.c"
|
#include"platform/posix_socket.c"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#elif defined(OS_LINUX)
|
#elif defined(PLATFORM_LINUX)
|
||||||
#include"platform/unix_base_allocator.c"
|
#include"platform/unix_base_memory.c"
|
||||||
#include"platform/linux_clock.c"
|
#include"platform/linux_clock.c"
|
||||||
/*
|
/*
|
||||||
#include"platform/unix_rng.c"
|
#include"platform/unix_rng.c"
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
// app/graphics layer
|
// app/graphics layer
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
|
|
||||||
#if defined(OS_WIN64)
|
#if defined(PLATFORM_WIN64)
|
||||||
#include"win32_app.c"
|
#include"win32_app.c"
|
||||||
#include"graphics.c"
|
#include"graphics.c"
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
#include"egl_surface.c"
|
#include"egl_surface.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(PLATFORM_MACOS)
|
||||||
//NOTE: macos application layer and graphics backends are defined in milepost.m
|
//NOTE: macos application layer and graphics backends are defined in milepost.m
|
||||||
#else
|
#else
|
||||||
#error "Unsupported platform"
|
#error "Unsupported platform"
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
#include"ringbuffer.h"
|
#include"ringbuffer.h"
|
||||||
|
|
||||||
#if defined(OS_WIN64) || defined(OS_WIN32)
|
#if defined(PLATFORM_WIN64) || defined(PLATFORM_WIN32)
|
||||||
#include"win32_app.h"
|
#include"win32_app.h"
|
||||||
#elif defined(OS_MACOS)
|
#elif defined(PLATFORM_MACOS)
|
||||||
#include"osx_app.h"
|
#include"osx_app.h"
|
||||||
#else
|
#else
|
||||||
#error "platform not supported yet"
|
#error "platform not supported yet"
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: orca_memory.c
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 17/04/2023
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
|
||||||
|
#include"platform_memory.h"
|
||||||
|
|
||||||
|
extern void* orca_mem_grow(u64 size);
|
||||||
|
|
||||||
|
void* orca_mem_base_reserve(mem_base_allocator* context, u64 size)
|
||||||
|
{
|
||||||
|
return(orca_mem_grow(size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void orca_mem_base_nop(mem_base_allocator* context, void* ptr, u64 size) {}
|
||||||
|
|
||||||
|
mem_base_allocator* mem_base_allocator_default()
|
||||||
|
{
|
||||||
|
static mem_base_allocator base = {0};
|
||||||
|
if(base.reserve == 0)
|
||||||
|
{
|
||||||
|
base.reserve = orca_mem_base_reserve;
|
||||||
|
base.commit = orca_mem_base_nop;
|
||||||
|
base.decommit = orca_mem_base_nop;
|
||||||
|
base.release = orca_mem_base_nop;
|
||||||
|
}
|
||||||
|
return(&base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: implement malloc/realloc/free/memset/etc here...
|
||||||
|
|
||||||
|
|
||||||
|
void* memset(void* b, int c, size_t n)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i<n; i++)
|
||||||
|
{
|
||||||
|
((char*)b)[i] = (u8)c;
|
||||||
|
}
|
||||||
|
return(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* memcpy(void *restrict dst, const void *restrict src, size_t n)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i<n; i++)
|
||||||
|
{
|
||||||
|
((char*)dst)[i] = ((char*)src)[i];
|
||||||
|
}
|
||||||
|
return(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* memmove(void *dst, const void *src, size_t n)
|
||||||
|
{
|
||||||
|
if(src < dst)
|
||||||
|
{
|
||||||
|
for(size_t i = n-1; i>=0; i--)
|
||||||
|
{
|
||||||
|
((char*)dst)[i] = ((char*)src)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(src > dst)
|
||||||
|
{
|
||||||
|
for(size_t i = 0; i<n; i++)
|
||||||
|
{
|
||||||
|
((char*)dst)[i] = ((char*)src)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
const unsigned char* c1 = (const unsigned char*)s1;
|
||||||
|
const unsigned char* c2 = (const unsigned char*)s2;
|
||||||
|
|
||||||
|
for(size_t i = 0; i<n; i++)
|
||||||
|
{
|
||||||
|
if(c1[i] != c2[i])
|
||||||
|
{
|
||||||
|
return(c1 - c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(0);
|
||||||
|
}
|
|
@ -33,17 +33,17 @@
|
||||||
// OS identification
|
// OS identification
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
#if defined(_WIN64)
|
#if defined(_WIN64)
|
||||||
#define OS_WIN64 1
|
#define PLATFORM_WIN64 1
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#error "Unsupported OS (32bit only version of Windows)"
|
#error "Unsupported OS (32bit only version of Windows)"
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#define OS_MACOS 1
|
#define PLATFORM_MACOS 1
|
||||||
#elif defined(__gnu_linux__)
|
#elif defined(__gnu_linux__)
|
||||||
#define OS_LINUX 1
|
#define PLATFORM_LINUX 1
|
||||||
#elif defined(__ORCA__)
|
#elif defined(__ORCA__)
|
||||||
#define OS_ORCA 1
|
#define PLATFORM_ORCA 1
|
||||||
#else
|
#else
|
||||||
#error "Can't identify OS"
|
#error "Can't identify platform"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
/************************************************************//**
|
|
||||||
*
|
|
||||||
* @file: platform_base_allocator.h
|
|
||||||
* @author: Martin Fouilleul
|
|
||||||
* @date: 10/09/2021
|
|
||||||
* @revision:
|
|
||||||
*
|
|
||||||
*****************************************************************/
|
|
||||||
#ifndef __PLATFORM_BASE_ALLOCATOR_H_
|
|
||||||
#define __PLATFORM_BASE_ALLOCATOR_H_
|
|
||||||
|
|
||||||
#include"typedefs.h"
|
|
||||||
#include"memory.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void* mem_base_reserve_mmap(void* context, u64 size);
|
|
||||||
void mem_base_release_mmap(void* context, void* ptr, u64 size);
|
|
||||||
|
|
||||||
mem_base_allocator* mem_base_allocator_default();
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} // extern "C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //__PLATFORM_BASE_ALLOCATOR_H_
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
/************************************************************//**
|
||||||
|
*
|
||||||
|
* @file: platform_memory.h
|
||||||
|
* @author: Martin Fouilleul
|
||||||
|
* @date: 10/09/2021
|
||||||
|
* @revision:
|
||||||
|
*
|
||||||
|
*****************************************************************/
|
||||||
|
#ifndef __PLATFORM_MEMORY_H_
|
||||||
|
#define __PLATFORM_MEMORY_H_
|
||||||
|
|
||||||
|
#include"typedefs.h"
|
||||||
|
#include"platform.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): base allocator
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
typedef struct mem_base_allocator mem_base_allocator;
|
||||||
|
|
||||||
|
typedef void*(*mem_reserve_function)(mem_base_allocator* context, u64 size);
|
||||||
|
typedef void(*mem_modify_function)(mem_base_allocator* context, void* ptr, u64 size);
|
||||||
|
|
||||||
|
typedef struct mem_base_allocator
|
||||||
|
{
|
||||||
|
mem_reserve_function reserve;
|
||||||
|
mem_modify_function commit;
|
||||||
|
mem_modify_function decommit;
|
||||||
|
mem_modify_function release;
|
||||||
|
|
||||||
|
} mem_base_allocator;
|
||||||
|
|
||||||
|
MP_API mem_base_allocator* mem_base_allocator_default();
|
||||||
|
|
||||||
|
#define mem_base_reserve(base, size) base->reserve(base, size)
|
||||||
|
#define mem_base_commit(base, ptr, size) base->commit(base, ptr, size)
|
||||||
|
#define mem_base_decommit(base, ptr, size) base->decommit(base, ptr, size)
|
||||||
|
#define mem_base_release(base, ptr, size) base->release(base, ptr, size)
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): malloc/free
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
#if PLATFORM_ORCA
|
||||||
|
void* malloc(size_t size);
|
||||||
|
void* realloc(void* ptr, size_t size);
|
||||||
|
void free(void* ptr);
|
||||||
|
#else
|
||||||
|
#include<stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define malloc_type(type) ((type*)malloc(sizeof(type)))
|
||||||
|
#define malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
//NOTE(martin): memset / memcpy
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if PLATFORM_ORCA
|
||||||
|
void* memset(void *b, int c, size_t len);
|
||||||
|
void* memcpy(void *restrict dst, const void *restrict src, size_t n);
|
||||||
|
void* memmove(void *dst, const void *src, size_t len);
|
||||||
|
int memcmp(const void *s1, const void *s2, size_t n);
|
||||||
|
#else
|
||||||
|
#include<string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //__PLATFORM_MEMORY_H_
|
|
@ -1,25 +1,25 @@
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
*
|
*
|
||||||
* @file: unix_base_allocator.c
|
* @file: unix_memory.c
|
||||||
* @author: Martin Fouilleul
|
* @author: Martin Fouilleul
|
||||||
* @date: 10/09/2021
|
* @date: 10/09/2021
|
||||||
* @revision:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#include<sys/mman.h>
|
#include<sys/mman.h>
|
||||||
#include"platform_base_allocator.h"
|
#include"platform_memory.h"
|
||||||
|
|
||||||
/*NOTE(martin):
|
/*NOTE(martin):
|
||||||
Linux and MacOS don't make a distinction between reserved and committed memory, contrary to Windows
|
Linux and MacOS don't make a distinction between reserved and committed memory, contrary to Windows
|
||||||
*/
|
*/
|
||||||
void mem_base_nop(void* context, void* ptr, u64 size) {}
|
void mem_base_nop(mem_base_allocator* context, void* ptr, u64 size) {}
|
||||||
|
|
||||||
void* mem_base_reserve_mmap(void* context, u64 size)
|
void* mem_base_reserve_mmap(mem_base_allocator* context, u64 size)
|
||||||
{
|
{
|
||||||
return(mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0));
|
return(mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_base_release_mmap(void* context, void* ptr, u64 size)
|
void mem_base_release_mmap(mem_base_allocator* context, void* ptr, u64 size)
|
||||||
{
|
{
|
||||||
munmap(ptr, size);
|
munmap(ptr, size);
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/************************************************************//**
|
/************************************************************//**
|
||||||
*
|
*
|
||||||
* @file: win32_base_allocator.c
|
* @file: win32_memory.c
|
||||||
* @author: Martin Fouilleul
|
* @author: Martin Fouilleul
|
||||||
* @date: 17/12/2022
|
* @date: 17/12/2022
|
||||||
* @revision:
|
* @revision:
|
||||||
|
@ -8,27 +8,25 @@
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include<windows.h>
|
#include<windows.h>
|
||||||
#include"platform_base_allocator.h"
|
#include"platform_memory.h"
|
||||||
|
|
||||||
void mem_base_nop(void* context, void* ptr, u64 size) {}
|
void* mem_base_reserve_win32(mem_base_allocator* context, u64 size)
|
||||||
|
|
||||||
void* mem_base_reserve_win32(void* context, u64 size)
|
|
||||||
{
|
{
|
||||||
void* result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
void* result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_base_commit_win32(void* context, void* ptr, u64 size)
|
void mem_base_commit_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||||
{
|
{
|
||||||
VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE);
|
VirtualAlloc(ptr, size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_base_release_win32(void* context, void* ptr, u64 size)
|
void mem_base_release_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||||
{
|
{
|
||||||
VirtualFree(ptr, size, MEM_RELEASE);
|
VirtualFree(ptr, size, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_base_decommit_win32(void* context, void* ptr, u64 size)
|
void mem_base_decommit_win32(mem_base_allocator* context, void* ptr, u64 size)
|
||||||
{
|
{
|
||||||
VirtualFree(ptr, size, MEM_DECOMMIT);
|
VirtualFree(ptr, size, MEM_DECOMMIT);
|
||||||
}
|
}
|
4
src/ui.c
4
src/ui.c
|
@ -2340,9 +2340,9 @@ typedef struct ui_edit_command
|
||||||
|
|
||||||
} ui_edit_command;
|
} ui_edit_command;
|
||||||
|
|
||||||
#if OS_WIN64
|
#if PLATFORM_WIN64
|
||||||
#define OS_COPY_PASTE_MOD MP_KEYMOD_CTRL
|
#define OS_COPY_PASTE_MOD MP_KEYMOD_CTRL
|
||||||
#elif OS_MACOS
|
#elif PLATFORM_MACOS
|
||||||
#define OS_COPY_PASTE_MOD MP_KEYMOD_CMD
|
#define OS_COPY_PASTE_MOD MP_KEYMOD_CMD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,6 @@
|
||||||
//TODO(martin): this is a compiler-specific attribute, recognized by clang and gcc. See if there's a more portable approach
|
//TODO(martin): this is a compiler-specific attribute, recognized by clang and gcc. See if there's a more portable approach
|
||||||
//#define INLINE_GEN __attribute__((used)) static inline
|
//#define INLINE_GEN __attribute__((used)) static inline
|
||||||
|
|
||||||
|
|
||||||
//NOTE(martin): typed and array mallocs
|
|
||||||
#define malloc_type(type) ((type*)malloc(sizeof(type)))
|
|
||||||
#define malloc_array(type, count) ((type*)malloc(sizeof(type)*count))
|
|
||||||
|
|
||||||
//NOTE(martin): 'hygienic' templates, to replace macros and avoid multiple evaluation problems.
|
//NOTE(martin): 'hygienic' templates, to replace macros and avoid multiple evaluation problems.
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
//NOTE(martin): in C++ we use templates and decltype/declval
|
//NOTE(martin): in C++ we use templates and decltype/declval
|
||||||
|
@ -128,9 +123,11 @@ static inline u64 next_pow2_u64(u64 x)
|
||||||
//NOTE: assert macros
|
//NOTE: assert macros
|
||||||
|
|
||||||
#ifndef NO_ASSERT
|
#ifndef NO_ASSERT
|
||||||
#ifdef OS_ORCA
|
#ifdef PLATFORM_ORCA
|
||||||
//TODO add a runtime-provided assert
|
//TODO add a runtime-provided assert
|
||||||
#define _ASSERT_(x, msg)
|
extern void orca_assert(bool x);
|
||||||
|
|
||||||
|
#define _ASSERT_(x, msg) orca_assert(x)
|
||||||
#else
|
#else
|
||||||
#include<assert.h>
|
#include<assert.h>
|
||||||
#define _ASSERT_(x, msg) assert(x && msg)
|
#define _ASSERT_(x, msg) assert(x && msg)
|
||||||
|
|
|
@ -6,19 +6,43 @@
|
||||||
* @revision:
|
* @revision:
|
||||||
*
|
*
|
||||||
*****************************************************************/
|
*****************************************************************/
|
||||||
#include<string.h> // memset
|
|
||||||
|
|
||||||
#include"platform.h"
|
#include"platform.h"
|
||||||
#include"memory.h"
|
#include"memory.h"
|
||||||
#include"platform_base_allocator.h"
|
#include"platform_memory.h"
|
||||||
#include"macro_helpers.h"
|
#include"macro_helpers.h"
|
||||||
|
|
||||||
|
#if PLATFORM_ORCA
|
||||||
|
static const u32 MEM_ARENA_DEFAULT_RESERVE_SIZE = 1<<20;
|
||||||
|
#else
|
||||||
static const u32 MEM_ARENA_DEFAULT_RESERVE_SIZE = 1<<30;
|
static const u32 MEM_ARENA_DEFAULT_RESERVE_SIZE = 1<<30;
|
||||||
static const u32 MEM_ARENA_COMMIT_ALIGNMENT = 1<<20;
|
#endif
|
||||||
|
|
||||||
|
static const u32 MEM_ARENA_COMMIT_ALIGNMENT = 4<<10;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): memory arena
|
//NOTE(martin): memory arena
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
mem_arena_chunk* mem_arena_chunk_alloc(mem_arena* arena, u64 reserveSize)
|
||||||
|
{
|
||||||
|
reserveSize = AlignUpOnPow2(reserveSize, MEM_ARENA_COMMIT_ALIGNMENT);
|
||||||
|
u64 commitSize = AlignUpOnPow2(sizeof(mem_arena_chunk), MEM_ARENA_COMMIT_ALIGNMENT);
|
||||||
|
|
||||||
|
char* mem = mem_base_reserve(arena->base, reserveSize);
|
||||||
|
mem_base_commit(arena->base, mem, commitSize);
|
||||||
|
|
||||||
|
mem_arena_chunk* chunk = (mem_arena_chunk*)mem;
|
||||||
|
|
||||||
|
chunk->ptr = mem;
|
||||||
|
chunk->cap = reserveSize;
|
||||||
|
chunk->offset = sizeof(mem_arena_chunk);
|
||||||
|
chunk->committed = commitSize;
|
||||||
|
|
||||||
|
list_push_back(&arena->chunks, &chunk->listElt);
|
||||||
|
|
||||||
|
return(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
void mem_arena_init(mem_arena* arena)
|
void mem_arena_init(mem_arena* arena)
|
||||||
{
|
{
|
||||||
mem_arena_init_with_options(arena, &(mem_arena_options){0});
|
mem_arena_init_with_options(arena, &(mem_arena_options){0});
|
||||||
|
@ -26,42 +50,69 @@ void mem_arena_init(mem_arena* arena)
|
||||||
|
|
||||||
void mem_arena_init_with_options(mem_arena* arena, mem_arena_options* options)
|
void mem_arena_init_with_options(mem_arena* arena, mem_arena_options* options)
|
||||||
{
|
{
|
||||||
arena->base = options->base ? options->base : mem_base_allocator_default();
|
memset(arena, 0, sizeof(mem_arena));
|
||||||
arena->cap = options->reserve ? options->reserve : MEM_ARENA_DEFAULT_RESERVE_SIZE;
|
|
||||||
|
|
||||||
arena->ptr = mem_base_reserve(arena->base, arena->cap);
|
arena->base = options->base ? options->base : mem_base_allocator_default();
|
||||||
arena->committed = 0;
|
|
||||||
arena->offset = 0;
|
u64 reserveSize = options->reserve ? (options->reserve + sizeof(mem_arena_chunk)) : MEM_ARENA_DEFAULT_RESERVE_SIZE;
|
||||||
|
|
||||||
|
arena->currentChunk = mem_arena_chunk_alloc(arena, reserveSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_arena_release(mem_arena* arena)
|
void mem_arena_release(mem_arena* arena)
|
||||||
{
|
{
|
||||||
mem_base_release(arena->base, arena->ptr, arena->cap);
|
for_list_safe(&arena->chunks, chunk, mem_arena_chunk, listElt)
|
||||||
|
{
|
||||||
|
mem_base_release(arena->base, chunk, chunk->cap);
|
||||||
|
}
|
||||||
memset(arena, 0, sizeof(mem_arena));
|
memset(arena, 0, sizeof(mem_arena));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* mem_arena_alloc(mem_arena* arena, u64 size)
|
void* mem_arena_alloc(mem_arena* arena, u64 size)
|
||||||
{
|
{
|
||||||
u64 nextOffset = arena->offset + size;
|
mem_arena_chunk* chunk = arena->currentChunk;
|
||||||
ASSERT(nextOffset <= arena->cap);
|
ASSERT(chunk);
|
||||||
|
|
||||||
if(nextOffset > arena->committed)
|
u64 nextOffset = chunk->offset + size;
|
||||||
|
u64 lastCap = chunk->cap;
|
||||||
|
while(chunk && nextOffset > chunk->cap)
|
||||||
|
{
|
||||||
|
chunk = list_next_entry(&arena->chunks, chunk, mem_arena_chunk, listElt);
|
||||||
|
nextOffset = chunk->offset + size;
|
||||||
|
lastCap = chunk->cap;
|
||||||
|
}
|
||||||
|
if(!chunk)
|
||||||
|
{
|
||||||
|
u64 reserveSize = maximum(lastCap * 1.5, size);
|
||||||
|
|
||||||
|
chunk = mem_arena_chunk_alloc(arena, reserveSize);
|
||||||
|
nextOffset = chunk->offset + size;
|
||||||
|
}
|
||||||
|
ASSERT(nextOffset <= chunk->cap);
|
||||||
|
|
||||||
|
arena->currentChunk = chunk;
|
||||||
|
|
||||||
|
if(nextOffset > chunk->committed)
|
||||||
{
|
{
|
||||||
u64 nextCommitted = AlignUpOnPow2(nextOffset, MEM_ARENA_COMMIT_ALIGNMENT);
|
u64 nextCommitted = AlignUpOnPow2(nextOffset, MEM_ARENA_COMMIT_ALIGNMENT);
|
||||||
nextCommitted = ClampHighBound(nextCommitted, arena->cap);
|
nextCommitted = ClampHighBound(nextCommitted, chunk->cap);
|
||||||
u64 commitSize = nextCommitted - arena->committed;
|
u64 commitSize = nextCommitted - chunk->committed;
|
||||||
mem_base_commit(arena->base, arena->ptr + arena->committed, commitSize);
|
mem_base_commit(arena->base, chunk->ptr + chunk->committed, commitSize);
|
||||||
arena->committed = nextCommitted;
|
chunk->committed = nextCommitted;
|
||||||
}
|
}
|
||||||
char* p = arena->ptr + arena->offset;
|
char* p = chunk->ptr + chunk->offset;
|
||||||
arena->offset += size;
|
chunk->offset += size;
|
||||||
|
|
||||||
return(p);
|
return(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mem_arena_clear(mem_arena* arena)
|
void mem_arena_clear(mem_arena* arena)
|
||||||
{
|
{
|
||||||
arena->offset = 0;
|
for_list(&arena->chunks, chunk, mem_arena_chunk, listElt)
|
||||||
|
{
|
||||||
|
chunk->offset = sizeof(mem_arena_chunk);
|
||||||
|
}
|
||||||
|
arena->currentChunk = list_first_entry(&arena->chunks, mem_arena_chunk, listElt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
@ -98,7 +149,6 @@ void* mem_pool_alloc(mem_pool* pool)
|
||||||
|
|
||||||
void mem_pool_recycle(mem_pool* pool, void* ptr)
|
void mem_pool_recycle(mem_pool* pool, void* ptr)
|
||||||
{
|
{
|
||||||
ASSERT((((char*)ptr) >= pool->arena.ptr) && (((char*)ptr) < (pool->arena.ptr + pool->arena.offset)));
|
|
||||||
list_push(&pool->freeList, (list_elt*)ptr);
|
list_push(&pool->freeList, (list_elt*)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +167,7 @@ mp_thread_local mem_arena __scratchArena = {0};
|
||||||
|
|
||||||
mem_arena* mem_scratch()
|
mem_arena* mem_scratch()
|
||||||
{
|
{
|
||||||
if(__scratchArena.ptr == 0)
|
if(__scratchArena.base == 0)
|
||||||
{
|
{
|
||||||
mem_arena_init(&__scratchArena);
|
mem_arena_init(&__scratchArena);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,46 +9,33 @@
|
||||||
#ifndef __MEMORY_H_
|
#ifndef __MEMORY_H_
|
||||||
#define __MEMORY_H_
|
#define __MEMORY_H_
|
||||||
|
|
||||||
#include"typedefs.h"
|
#include"util/typedefs.h"
|
||||||
#include"lists.h"
|
#include"util/lists.h"
|
||||||
|
#include"platform/platform_memory.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
//NOTE(martin): base allocator
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
typedef void*(*mem_reserve_function)(void* context, u64 size);
|
|
||||||
typedef void(*mem_modify_function)(void* context, void* ptr, u64 size);
|
|
||||||
|
|
||||||
typedef struct mem_base_allocator
|
|
||||||
{
|
|
||||||
mem_reserve_function reserve;
|
|
||||||
mem_modify_function commit;
|
|
||||||
mem_modify_function decommit;
|
|
||||||
mem_modify_function release;
|
|
||||||
void* context;
|
|
||||||
|
|
||||||
} mem_base_allocator;
|
|
||||||
|
|
||||||
MP_API mem_base_allocator* mem_base_allocator_default();
|
|
||||||
|
|
||||||
#define mem_base_reserve(base, size) base->reserve(base->context, size)
|
|
||||||
#define mem_base_commit(base, ptr, size) base->commit(base->context, ptr, size)
|
|
||||||
#define mem_base_decommit(base, ptr, size) base->decommit(base->context, ptr, size)
|
|
||||||
#define mem_base_release(base, ptr, size) base->release(base->context, ptr, size)
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
//NOTE(martin): memory arena
|
//NOTE(martin): memory arena
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
typedef struct mem_arena
|
|
||||||
|
typedef struct mem_arena_chunk
|
||||||
{
|
{
|
||||||
mem_base_allocator* base;
|
list_elt listElt;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
u64 committed;
|
u64 committed;
|
||||||
u64 cap;
|
u64 cap;
|
||||||
|
} mem_arena_chunk;
|
||||||
|
|
||||||
|
typedef struct mem_arena
|
||||||
|
{
|
||||||
|
mem_base_allocator* base;
|
||||||
|
list_info chunks;
|
||||||
|
mem_arena_chunk* currentChunk;
|
||||||
|
|
||||||
} mem_arena;
|
} mem_arena;
|
||||||
|
|
||||||
typedef struct mem_arena_options
|
typedef struct mem_arena_options
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
#ifndef __TYPEDEFS_H_
|
#ifndef __TYPEDEFS_H_
|
||||||
#define __TYPEDEFS_H_
|
#define __TYPEDEFS_H_
|
||||||
|
|
||||||
#include<inttypes.h>
|
#include<stddef.h>
|
||||||
|
#include<stdint.h>
|
||||||
#include<float.h> //FLT_MAX/MIN etc...
|
#include<float.h> //FLT_MAX/MIN etc...
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
|
|
Loading…
Reference in New Issue