mirror of
https://github.com/Ed94/metadesk.git
synced 2026-07-28 18:30:03 +00:00
progress on resolving deps
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#if defined( _WIN64 ) || defined( __x86_64__ ) || defined( _M_X64 ) || defined( __64BIT__ ) || defined( __powerpc64__ ) || defined( __ppc64__ ) || defined( __aarch64__ )
|
||||
# ifndef MD_ARCH_64_BIT
|
||||
# define MD_ARCH_64_BIT 1
|
||||
# endif
|
||||
#else
|
||||
# ifndef MD_ARCH_32_BIT
|
||||
# define MD_ARCH_32_BIT 1
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,128 @@
|
||||
#ifdef MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#include "macros.h"
|
||||
#endif
|
||||
|
||||
#pragma region Basic Types
|
||||
|
||||
#define MD_U8_MIN 0u
|
||||
#define MD_U8_MAX 0xffu
|
||||
#define MD_I8_MIN ( -0x7f - 1 )
|
||||
#define MD_I8_MAX 0x7f
|
||||
|
||||
#define MD_U16_MIN 0u
|
||||
#define MD_U16_MAX 0xffffu
|
||||
#define MD_I16_MIN ( -0x7fff - 1 )
|
||||
#define MD_I16_MAX 0x7fff
|
||||
|
||||
#define MD_U32_MIN 0u
|
||||
#define MD_U32_MAX 0xffffffffu
|
||||
#define MD_I32_MIN ( -0x7fffffff - 1 )
|
||||
#define MD_I32_MAX 0x7fffffff
|
||||
|
||||
#define MD_U64_MIN 0ull
|
||||
#define MD_U64_MAX 0xffffffffffffffffull
|
||||
#define MD_I64_MIN ( -0x7fffffffffffffffll - 1 )
|
||||
#define MD_I64_MAX 0x7fffffffffffffffll
|
||||
|
||||
#if defined( MD_ARCH_32_BIT )
|
||||
# define MD_USIZE_MIN GEN_U32_MIN
|
||||
# define MD_USIZE_MAX GEN_U32_MAX
|
||||
# define MD_ISIZE_MIN GEN_S32_MIN
|
||||
# define MD_ISIZE_MAX GEN_S32_MAX
|
||||
#elif defined( MD_ARCH_64_BIT )
|
||||
# define MD_USIZE_MIN GEN_U64_MIN
|
||||
# define MD_USIZE_MAX GEN_U64_MAX
|
||||
# define MD_ISIZE_MIN GEN_I64_MIN
|
||||
# define MD_ISIZE_MAX GEN_I64_MAX
|
||||
#else
|
||||
# error Unknown architecture size. This library only supports 32 bit and 64 bit architectures.
|
||||
#endif
|
||||
|
||||
#define MD_F32_MIN 1.17549435e-38f
|
||||
#define MD_F32_MAX 3.40282347e+38f
|
||||
#define MD_F64_MIN 2.2250738585072014e-308
|
||||
#define MD_F64_MAX 1.7976931348623157e+308
|
||||
|
||||
#if defined( MD_COMPILER_MSVC )
|
||||
# if _MSC_VER < 1300
|
||||
typedef unsigned char U8;
|
||||
typedef signed char S8;
|
||||
typedef unsigned short U16;
|
||||
typedef signed short S16;
|
||||
typedef unsigned int U32;
|
||||
typedef signed int S32;
|
||||
# else
|
||||
typedef unsigned __int8 U8;
|
||||
typedef signed __int8 S8;
|
||||
typedef unsigned __int16 U16;
|
||||
typedef signed __int16 S16;
|
||||
typedef unsigned __int32 U32;
|
||||
typedef signed __int32 S32;
|
||||
# endif
|
||||
typedef unsigned __int64 U64;
|
||||
typedef signed __int64 S64;
|
||||
#else
|
||||
# include <stdint.h>
|
||||
|
||||
typedef uint8_t U8;
|
||||
typedef int8_t S8;
|
||||
typedef uint16_t U16;
|
||||
typedef int16_t S16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t S32;
|
||||
typedef uint64_t U64;
|
||||
typedef int64_t S64;
|
||||
#endif
|
||||
|
||||
typedef struct U128 U128;
|
||||
struct U128 {
|
||||
U64 data[2];
|
||||
};
|
||||
|
||||
static_assert( sizeof( U8 ) == sizeof( S8 ), "sizeof(U8) != sizeof(S8)" );
|
||||
static_assert( sizeof( U16 ) == sizeof( S16 ), "sizeof(U16) != sizeof(sS6)" );
|
||||
static_assert( sizeof( U32 ) == sizeof( S32 ), "sizeof(U32) != sizeof(sS2)" );
|
||||
static_assert( sizeof( U64 ) == sizeof( S64 ), "sizeof(U64) != sizeof(sS4)" );
|
||||
|
||||
static_assert( sizeof( U8 ) == 1, "sizeof(U8) != 1" );
|
||||
static_assert( sizeof( U16 ) == 2, "sizeof(U16) != 2" );
|
||||
static_assert( sizeof( U32 ) == 4, "sizeof(U32) != 4" );
|
||||
static_assert( sizeof( U64 ) == 8, "sizeof(U64) != 8" );
|
||||
|
||||
typedef size_t USIZE;
|
||||
typedef ptrdiff_t SSIZE;
|
||||
|
||||
static_assert( sizeof( USIZE ) == sizeof( SSIZE ), "sizeof(USIZE) != sizeof(SSIZE)" );
|
||||
|
||||
// NOTE: (u)zpl_intptr is only here for semantic reasons really as this library will only support 32/64 bit OSes.
|
||||
#if defined( _WIN64 )
|
||||
typedef signed __int64 SPTR;
|
||||
typedef unsigned __int64 UPTR;
|
||||
#elif defined( _WIN32 )
|
||||
// NOTE; To mark types changing their size, e.g. zpl_intptr
|
||||
# ifndef _W64
|
||||
# if ! defined( __midl ) && ( defined( _X86_ ) || defined( _M_IX86 ) ) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
# endifk
|
||||
typedef _W64 signed int SPTR;
|
||||
typedef _W64 unsigned int UPTR;
|
||||
#else
|
||||
typedef uintptr_t UPTR;
|
||||
typedef intptr_t SPTR;
|
||||
#endif
|
||||
|
||||
static_assert( sizeof( UPTR ) == sizeof( SPTR ), "sizeof(UPTR) != sizeof(SPTR)" );
|
||||
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
|
||||
static_assert( sizeof( F32 ) == 4, "sizeof(F32) != 4" );
|
||||
static_assert( sizeof( F64 ) == 8, "sizeof(F64) != 8" );
|
||||
|
||||
typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
@@ -0,0 +1,65 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#pragma region Platform Compiler
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
# pragma message("Detected MSVC")
|
||||
// # define MD_COMPILER_CLANG 0
|
||||
# define MD_COMPILER_MSVC 1
|
||||
// # define MD_COMPILER_GCC 0
|
||||
#elif defined( __GNUC__ )
|
||||
# pragma message("Detected GCC")
|
||||
// # define MD_COMPILER_CLANG 0
|
||||
// # define MD_COMPILER_MSVC 0
|
||||
# define MD_COMPILER_GCC 1
|
||||
#elif defined( __clang__ )
|
||||
# pragma message("Detected CLANG")
|
||||
# define MD_COMPILER_CLANG 1
|
||||
// # define MD_COMPILER_MSVC 0
|
||||
// # define MD_COMPILER_GCC 0
|
||||
#else
|
||||
# error Unknown compiler
|
||||
#endif
|
||||
|
||||
#if defined( __has_attribute )
|
||||
# define MD_HAS_ATTRIBUTE( attribute ) __has_attribute( attribute )
|
||||
#else
|
||||
# define MD_HAS_ATTRIBUTE( attribute ) ( 0 )
|
||||
#endif
|
||||
|
||||
#if defined(MD_GCC_VERSION_CHECK)
|
||||
# undef MD_GCC_VERSION_CHECK
|
||||
#endif
|
||||
#if defined(GEN_GCC_VERSION)
|
||||
# define MD_GCC_VERSION_CHECK(major,minor,patch) (GEN_GCC_VERSION >= GEN_VERSION_ENCODE(major, minor, patch))
|
||||
#else
|
||||
# define MD_GCC_VERSION_CHECK(major,minor,patch) (0)
|
||||
#endif
|
||||
|
||||
#if ! defined(MD_COMPILER_C)
|
||||
# ifdef __cplusplus
|
||||
# define MD_COMPILER_C 0
|
||||
# define MD_COMPILER_CPP 1
|
||||
# else
|
||||
# if defined(__STDC__)
|
||||
# define MD_COMPILER_C 1
|
||||
# define MD_COMPILER_CPP 0
|
||||
# else
|
||||
// Fallback for very old C compilers
|
||||
# define MD_COMPILER_C 1
|
||||
# define MD_COMPILER_CPP 0
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MD_COMPILER_C
|
||||
#pragma message("MD: Detected C")
|
||||
#endif
|
||||
|
||||
#if MD_COMPILER_CPP
|
||||
#pragma message("MD: Detected CPP")
|
||||
#endif
|
||||
|
||||
#pragma endregion Platform Compiler
|
||||
@@ -0,0 +1,22 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#include "arch.h"
|
||||
#include "os.h"
|
||||
#include "compiler.h"
|
||||
#endif
|
||||
|
||||
#pragma region Mandatory Includes
|
||||
|
||||
# include <stdarg.h>
|
||||
# include <stddef.h>
|
||||
|
||||
# if defined( MD_SYSTEM_WINDOWS )
|
||||
# include <intrin.h>
|
||||
# endif
|
||||
|
||||
#if MD_COMPILER_C
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#pragma endregion Mandatory Includes
|
||||
@@ -0,0 +1,125 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#include "cstd.h"
|
||||
#endif
|
||||
|
||||
#ifndef MD_API
|
||||
#if MD_COMPILER_MSVC
|
||||
# ifdef MD_DYN_LINK
|
||||
# ifdef MD_DYN_EXPORT
|
||||
# define MD_API __declspec(dllexport)
|
||||
# else
|
||||
# define MD_API __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define MD_API // Empty for static builds
|
||||
# endif
|
||||
#else
|
||||
# ifdef MD_DYN_LINK
|
||||
# define MD_API __attribute__((visibility("default")))
|
||||
# else
|
||||
# define MD_API // Empty for static builds
|
||||
# endif
|
||||
#endif
|
||||
#endif // GEN_API
|
||||
|
||||
#ifndef internal
|
||||
#define internal static
|
||||
#endif
|
||||
|
||||
#ifndef local_persist
|
||||
#define local_persist static
|
||||
#endif
|
||||
|
||||
#if MD_COMPILER_CPP
|
||||
# ifndef ccast
|
||||
# define ccast( type, value ) ( const_cast< type >( (value) ) )
|
||||
# endif
|
||||
# ifndef pcast
|
||||
# define pcast( type, value ) ( * reinterpret_cast< type* >( & ( value ) ) )
|
||||
# endif
|
||||
# ifndef rcast
|
||||
# define rcast( type, value ) reinterpret_cast< type >( value )
|
||||
# endif
|
||||
# ifndef scast
|
||||
# define scast( type, value ) static_cast< type >( value )
|
||||
# endif
|
||||
#else
|
||||
# ifndef ccast
|
||||
# define ccast( type, value ) ( (type)(value) )
|
||||
# endif
|
||||
# ifndef pcast
|
||||
# define pcast( type, value ) ( * (type*)(& value) )
|
||||
# endif
|
||||
# ifndef rcast
|
||||
# define rcast( type, value ) ( (type)(value) )
|
||||
# endif
|
||||
# ifndef scast
|
||||
# define scast( type, value ) ( (type)(value) )
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined(typeof) && (!MD_COMPILER_C || __STDC_VERSION__ < 202311L)
|
||||
# if ! MD_COMPILER_C
|
||||
# define typeof decltype
|
||||
# elif defined(_MSC_VER)
|
||||
# define typeof __typeof__
|
||||
# elif defined(__GNUC__) || defined(__clang__)
|
||||
# define typeof __typeof__
|
||||
# else
|
||||
# error "Compiler not supported"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef MD_API_C_BEGIN
|
||||
# if MD_COMPILER_C
|
||||
# define MD_API_C_BEGIN
|
||||
# define MD_API_C_END
|
||||
# else
|
||||
# define MD_API_C_BEGIN extern "C" {
|
||||
# define MD_API_C_END }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MD_COMPILER_C
|
||||
# if __STDC_VERSION__ >= 202311L
|
||||
# define enum_underlying(type) : type
|
||||
# else
|
||||
# define enum_underlying(type)
|
||||
# endif
|
||||
#else
|
||||
# define enum_underlying(type) : type
|
||||
#endif
|
||||
|
||||
#if MD_COMPILER_C
|
||||
# ifndef nullptr
|
||||
# define nullptr NULL
|
||||
# endif
|
||||
|
||||
# ifndef MD_REMOVE_PTR
|
||||
# define MD_REMOVE_PTR(type) typeof(* ( (type) NULL) )
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined(MD_PARAM_DEFAULT) && MD_COMPILER_CPP
|
||||
# define MD_PARAM_DEFAULT = {}
|
||||
#else
|
||||
# define MD_PARAM_DEFAULT
|
||||
#endif
|
||||
|
||||
#if MD_DONT_USE_NAMESPACE || MD_COMPILER_C
|
||||
# if MD_COMPILER_C
|
||||
# define MD_NS
|
||||
# define MD_NS_BEGIN
|
||||
# define MD_NS_END
|
||||
# else
|
||||
# define MD_NS ::
|
||||
# define MD_NS_BEGIN
|
||||
# define MD_NS_END
|
||||
# endif
|
||||
#else
|
||||
namespace MD {}
|
||||
namespace md = MD;
|
||||
# define MD_NS MD::
|
||||
# define MD_NS_BEGIN namespace MD {
|
||||
# define MD_NS_END }
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#include "base/base_types.h"
|
||||
#endif
|
||||
|
||||
typedef union Rng1U64 Rng1U64;
|
||||
union Rng1U64
|
||||
{
|
||||
struct
|
||||
{
|
||||
U64 min;
|
||||
U64 max;
|
||||
};
|
||||
U64 v[2];
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
#if MD_INTELLISENE_DIRECTIVES
|
||||
#pragma once
|
||||
#include "base_types.h"
|
||||
#endif
|
||||
|
||||
#define MD_KILOBYTES( x ) ( ( x ) * ( S64 )( 1024 ) )
|
||||
#define MD_MEGABYTES( x ) ( MD_KILOBYTES( x ) * ( S64 )( 1024 ) )
|
||||
#define MD_GIGABYTES( x ) ( MD_MEGABYTES( x ) * ( S64 )( 1024 ) )
|
||||
#define MD_TERABYTES( x ) ( MD_GIGABYTES( x ) * ( S64 )( 1024 ) )
|
||||
|
||||
#define MD__ONES ( scast( GEN_NS usize, - 1) / MD_U8_MAX )
|
||||
#define MD__HIGHS ( MD__ONES * ( MD_U8_MAX / 2 + 1 ) )
|
||||
#define MD__HAS_ZERO( x ) ( ( ( x ) - MD__ONES ) & ~( x ) & MD__HIGHS )
|
||||
|
||||
#define swap(a, b) \
|
||||
do \
|
||||
{ \
|
||||
typeof(a) tmp = a; \
|
||||
a = b; \
|
||||
b = tmp; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#if MD_COMPILER_MSVC || (MD_COMPILER_CLANG && MD_OS_WINDOWS)
|
||||
# pragma section(".rdata$", read)
|
||||
# define read_only __declspec(allocate(".rdata$"))
|
||||
#elif (MD_COMPILER_CLANG && MD_OS_LINUX)
|
||||
# define read_only __attribute__((section(".rodata")))
|
||||
#else
|
||||
// NOTE(rjf): I don't know of a useful way to do this in GCC land.
|
||||
// __attribute__((section(".rodata"))) looked promising, but it introduces a
|
||||
// strange warning about malformed section attributes, and it doesn't look
|
||||
// like writing to that section reliably produces access violations, strangely
|
||||
// enough. (It does on Clang)
|
||||
# define read_only
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#pragma region Platform OS
|
||||
|
||||
#if defined( _WIN32 ) || defined( _WIN64 )
|
||||
# ifndef MD_OS_WINDOWS
|
||||
# define MD_OS_WINDOWS 1
|
||||
# endif
|
||||
#elif defined( __APPLE__ ) && defined( __MACH__ )
|
||||
# ifndef MD_OS_OSX
|
||||
# define MD_OS_OSX 1
|
||||
# endif
|
||||
# ifndef MD_OS_MACOS
|
||||
# define MD_OS_MACOS 1
|
||||
# endif
|
||||
#elif defined( __unix__ )
|
||||
# ifndef MD_OS_UNIX
|
||||
# define MD_OS_UNIX 1
|
||||
# endif
|
||||
# if defined( ANDROID ) || defined( __ANDROID__ )
|
||||
# ifndef MD_OS_ANDROID
|
||||
# define MD_OS_ANDROID 1
|
||||
# endif
|
||||
# ifndef MD_OS_LINUX
|
||||
# define MD_OS_LINUX 1
|
||||
# endif
|
||||
# elif defined( __linux__ )
|
||||
# ifndef MD_OS_LINUX
|
||||
# define MD_OS_LINUX 1
|
||||
# endif
|
||||
# elif defined( __FreeBSD__ ) || defined( __FreeBSD_kernel__ )
|
||||
# ifndef MD_OS_FREEBSD
|
||||
# define MD_OS_FREEBSD 1
|
||||
# endif
|
||||
# elif defined( __OpenBSD__ )
|
||||
# ifndef MD_OS_OPENBSD
|
||||
# define MD_OS_OPENBSD 1
|
||||
# endif
|
||||
# elif defined( __EMSCRIPTEN__ )
|
||||
# ifndef MD_OS_EMSCRIPTEN
|
||||
# define MD_OS_EMSCRIPTEN 1
|
||||
# endif
|
||||
# elif defined( __CYGWIN__ )
|
||||
# ifndef MD_OS_CYGWIN
|
||||
# define MD_OS_CYGWIN 1
|
||||
# endif
|
||||
# else
|
||||
# error This UNIX operating system is not supported
|
||||
# endif
|
||||
#else
|
||||
# error This operating system is not supported
|
||||
#endif
|
||||
|
||||
#pragma endregion Platform OS
|
||||
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
|
||||
internal Arena *
|
||||
arena_alloc_(ArenaParams *params)
|
||||
{
|
||||
// rjf: round up reserve/commit sizes
|
||||
U64 reserve_size = params->reserve_size;
|
||||
U64 commit_size = params->commit_size;
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->large_page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->large_page_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
reserve_size = AlignPow2(reserve_size, os_get_system_info()->page_size);
|
||||
commit_size = AlignPow2(commit_size, os_get_system_info()->page_size);
|
||||
}
|
||||
|
||||
// rjf: reserve/commit initial block
|
||||
void *base = params->optional_backing_buffer;
|
||||
if(base == 0)
|
||||
{
|
||||
if(params->flags & ArenaFlag_LargePages)
|
||||
{
|
||||
base = os_reserve_large(reserve_size);
|
||||
os_commit_large(base, commit_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
base = os_reserve(reserve_size);
|
||||
os_commit(base, commit_size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: panic on arena creation failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(base == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: extract arena header & fill
|
||||
Arena *arena = (Arena *)base;
|
||||
arena->current = arena;
|
||||
arena->flags = params->flags;
|
||||
arena->cmt_size = (U32)params->commit_size;
|
||||
arena->res_size = params->reserve_size;
|
||||
arena->base_pos = 0;
|
||||
arena->pos = ARENA_HEADER_SIZE;
|
||||
arena->cmt = commit_size;
|
||||
arena->res = reserve_size;
|
||||
AsanPoisonMemoryRegion(base, commit_size);
|
||||
AsanUnpoisonMemoryRegion(base, ARENA_HEADER_SIZE);
|
||||
return arena;
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_release(Arena *arena)
|
||||
{
|
||||
for(Arena *n = arena->current, *prev = 0; n != 0; n = prev)
|
||||
{
|
||||
prev = n->prev;
|
||||
os_release(n, n->res);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop core functions
|
||||
|
||||
internal void *
|
||||
arena_push(Arena *arena, U64 size, U64 align)
|
||||
{
|
||||
Arena *current = arena->current;
|
||||
U64 pos_pre = AlignPow2(current->pos, align);
|
||||
U64 pos_pst = pos_pre + size;
|
||||
|
||||
// rjf: chain, if needed
|
||||
if(current->res < pos_pst && !(arena->flags & ArenaFlag_NoChain))
|
||||
{
|
||||
U64 res_size = current->res_size;
|
||||
U64 cmt_size = current->cmt_size;
|
||||
if(size + ARENA_HEADER_SIZE > res_size)
|
||||
{
|
||||
res_size = size + ARENA_HEADER_SIZE;
|
||||
cmt_size = size + ARENA_HEADER_SIZE;
|
||||
}
|
||||
Arena *new_block = arena_alloc(.reserve_size = res_size,
|
||||
.commit_size = cmt_size,
|
||||
.flags = current->flags);
|
||||
new_block->base_pos = current->base_pos + current->res;
|
||||
SLLStackPush_N(arena->current, new_block, prev);
|
||||
current = new_block;
|
||||
pos_pre = AlignPow2(current->pos, align);
|
||||
pos_pst = pos_pre + size;
|
||||
}
|
||||
|
||||
// rjf: commit new pages, if needed
|
||||
if(current->cmt < pos_pst && !(current->flags & ArenaFlag_LargePages))
|
||||
{
|
||||
U64 cmt_pst_aligned = AlignPow2(pos_pst, current->cmt_size);
|
||||
U64 cmt_pst_clamped = ClampTop(cmt_pst_aligned, current->res);
|
||||
U64 cmt_size = cmt_pst_clamped - current->cmt;
|
||||
os_commit((U8 *)current + current->cmt, cmt_size);
|
||||
current->cmt = cmt_pst_clamped;
|
||||
}
|
||||
|
||||
// rjf: push onto current block
|
||||
void *result = 0;
|
||||
if(current->cmt >= pos_pst)
|
||||
{
|
||||
result = (U8 *)current+pos_pre;
|
||||
current->pos = pos_pst;
|
||||
AsanUnpoisonMemoryRegion(result, size);
|
||||
}
|
||||
|
||||
// rjf: panic on failure
|
||||
#if OS_FEATURE_GRAPHICAL
|
||||
if(Unlikely(result == 0))
|
||||
{
|
||||
os_graphical_message(1, str8_lit("Fatal Allocation Failure"), str8_lit("Unexpected memory allocation failure."));
|
||||
os_abort(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
arena_pos(Arena *arena)
|
||||
{
|
||||
Arena *current = arena->current;
|
||||
U64 pos = current->base_pos + current->pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_pop_to(Arena *arena, U64 pos)
|
||||
{
|
||||
U64 big_pos = ClampBot(ARENA_HEADER_SIZE, pos);
|
||||
Arena *current = arena->current;
|
||||
for(Arena *prev = 0; current->base_pos >= big_pos; current = prev)
|
||||
{
|
||||
prev = current->prev;
|
||||
os_release(current, current->res);
|
||||
}
|
||||
arena->current = current;
|
||||
U64 new_pos = big_pos - current->base_pos;
|
||||
AssertAlways(new_pos <= current->pos);
|
||||
AsanPoisonMemoryRegion((U8*)current + new_pos, (current->pos - new_pos));
|
||||
current->pos = new_pos;
|
||||
}
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
|
||||
internal void
|
||||
arena_clear(Arena *arena)
|
||||
{
|
||||
arena_pop_to(arena, 0);
|
||||
}
|
||||
|
||||
internal void
|
||||
arena_pop(Arena *arena, U64 amt)
|
||||
{
|
||||
U64 pos_old = arena_pos(arena);
|
||||
U64 pos_new = pos_old;
|
||||
if(amt < pos_old)
|
||||
{
|
||||
pos_new = pos_old - amt;
|
||||
}
|
||||
arena_pop_to(arena, pos_new);
|
||||
}
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
|
||||
internal Temp
|
||||
temp_begin(Arena *arena)
|
||||
{
|
||||
U64 pos = arena_pos(arena);
|
||||
Temp temp = {arena, pos};
|
||||
return temp;
|
||||
}
|
||||
|
||||
internal void
|
||||
temp_end(Temp temp)
|
||||
{
|
||||
arena_pop_to(temp.arena, temp.pos);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef BASE_ARENA_H
|
||||
#define BASE_ARENA_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Constants
|
||||
|
||||
#define ARENA_HEADER_SIZE 64
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Types
|
||||
|
||||
typedef U32 ArenaFlags;
|
||||
enum
|
||||
{
|
||||
ArenaFlag_NoChain = (1<<0),
|
||||
ArenaFlag_LargePages = (1<<1),
|
||||
};
|
||||
|
||||
typedef struct ArenaParams ArenaParams;
|
||||
struct ArenaParams
|
||||
{
|
||||
ArenaFlags flags;
|
||||
U64 reserve_size;
|
||||
U64 commit_size;
|
||||
void *optional_backing_buffer;
|
||||
};
|
||||
|
||||
typedef struct Arena Arena;
|
||||
struct Arena
|
||||
{
|
||||
Arena *prev; // previous arena in chain
|
||||
Arena *current; // current arena in chain
|
||||
ArenaFlags flags;
|
||||
U32 cmt_size;
|
||||
U64 res_size;
|
||||
U64 base_pos;
|
||||
U64 pos;
|
||||
U64 cmt;
|
||||
U64 res;
|
||||
};
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
|
||||
typedef struct Temp Temp;
|
||||
struct Temp
|
||||
{
|
||||
Arena *arena;
|
||||
U64 pos;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Arena Functions
|
||||
|
||||
//- rjf: arena creation/destruction
|
||||
internal Arena *arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = MB(64), .commit_size = KB(64), __VA_ARGS__})
|
||||
internal void arena_release(Arena *arena);
|
||||
|
||||
//- rjf: arena push/pop/pos core functions
|
||||
internal void *arena_push(Arena *arena, U64 size, U64 align);
|
||||
internal U64 arena_pos(Arena *arena);
|
||||
internal void arena_pop_to(Arena *arena, U64 pos);
|
||||
|
||||
//- rjf: arena push/pop helpers
|
||||
internal void arena_clear(Arena *arena);
|
||||
internal void arena_pop(Arena *arena, U64 amt);
|
||||
|
||||
//- rjf: temporary arena scopes
|
||||
internal Temp temp_begin(Arena *arena);
|
||||
internal void temp_end(Temp temp);
|
||||
|
||||
//- rjf: push helper macros
|
||||
#define push_array_no_zero_aligned(a, T, c, align) (T *)arena_push((a), sizeof(T)*(c), (align))
|
||||
#define push_array_aligned(a, T, c, align) (T *)MemoryZero(push_array_no_zero_aligned(a, T, c, align), sizeof(T)*(c))
|
||||
#define push_array_no_zero(a, T, c) push_array_no_zero_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
#define push_array(a, T, c) push_array_aligned(a, T, c, Max(8, AlignOf(T)))
|
||||
|
||||
#endif // BASE_ARENA_H
|
||||
@@ -0,0 +1,11 @@
|
||||
#if MD_INTELLISENSE_DIRECTIVES
|
||||
#include "base_types.h"
|
||||
#endif
|
||||
|
||||
typedef struct String8 String8;
|
||||
struct String8
|
||||
{
|
||||
U8 *str;
|
||||
U64 size;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user