X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_mem.h;h=3a7a49da06814fe9c2c7d1d1b082ee6cc6a8ed5a;hp=48969d9d13be9588f811b898f9454fd9de96c609;hb=HEAD;hpb=9578dfc2859abc101f78c02c271aae44b351abca diff --git a/vg_mem.h b/vg_mem.h index 48969d9..6fde883 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -1,30 +1,19 @@ -#ifndef VG_MEM_H -#define VG_MEM_H - -#include "vg.h" -#include "vg_stdint.h" -#include "vg_platform.h" -#include "vg_log.h" - -#include -#include - -static void vg_print_backtrace(void); +#pragma once #define VG_MAX_ALLOCATIONS 128 -#define VG_FUZZ_ALLOCATIONS typedef struct vg_linear_allocator vg_linear_allocator; typedef struct vg_allocation_meta vg_allocation_meta; -struct{ +struct vg_global_mem +{ void *rtmemory, *scratch; int use_libc_malloc; u32 quota; } -static vg_mem; +extern vg_mem; struct vg_allocation_meta { @@ -41,8 +30,6 @@ struct vg_allocation_meta #define VG_MEMORY_SYSTEM 0x1 /* systems memory, slow and low counts */ #define VG_MEMORY_REALTIME 0x2 /* per-frame. no max allocs, only size. fast */ -/* systems memory cannot be declared inside realtime memory regions */ - /* * Stored just behind the array. 32 bytes. */ @@ -56,54 +43,48 @@ struct vg_linear_allocator u32 last_alloc_size; void *last_alloc; vg_allocation_meta *alloc_table; - -#ifdef _WIN32 - /* 32 bit pointers! */ - u8 padding[ 8 ]; -#endif }; #pragma pack(pop) -static u32 vg_align8( u32 s ); -static u32 vg_align4( u32 s ); +u32 vg_align8( u32 s ); +u32 vg_align4( u32 s ); /* allocate something from a linear allocator */ __attribute__((warn_unused_result)) -static void *_vg_linear_alloc( void *buffer, u32 size, - const char *constr_name ); +void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name ); /* resize latest block of memory from linear */ __attribute__((warn_unused_result)) -static void *vg_linear_resize( void *buffer, void *data, u32 newsize ); +void *vg_linear_resize( void *buffer, void *data, u32 newsize ); /* its possible to delete just the last item */ -static void vg_linear_del( void *buffer, void *data ); +void vg_linear_del( void *buffer, void *data ); /* extend latest block of memory from linear */ __attribute__((warn_unused_result)) -static void *_vg_linear_extend( void *buffer, void *data, u32 extra, - const char *constr_name ); +void *_vg_linear_extend( void *buffer, void *data, u32 extra, + const char *constr_name ); /* get the current usage of allocator */ -static u32 vg_linear_get_cur( void *buffer ); +u32 vg_linear_get_cur( void *buffer ); /* get the capacity of allocator. */ -static u32 vg_linear_get_capacity( void *buffer ); +u32 vg_linear_get_capacity( void *buffer ); /* get the remaining size of the allocator */ -static u32 vg_linear_remaining( void *buffer ); +u32 vg_linear_remaining( void *buffer ); /* yeet all memory from linear allocator */ -static void vg_linear_clear( void *buffer ); +void vg_linear_clear( void *buffer ); /* request all the memory we need in advance */ -static void vg_set_mem_quota( u32 size ); +void vg_set_mem_quota( u32 size ); /* essentially init() */ -static void vg_alloc_quota(void); +void vg_alloc_quota(void); /* print out tree of current memory used. only works with libc mode */ -static void vg_mem_log( void *lin_alloc, int depth, const char *name ); +void vg_mem_log( void *lin_alloc, int depth, const char *name ); #define VG_MEM_MCSTR(S) VG_MEM_MCSTR2(S) #define VG_MEM_MCSTR2(S) #S @@ -115,343 +96,6 @@ static void vg_mem_log( void *lin_alloc, int depth, const char *name ); #define vg_create_linear_allocator(...) \ _vg_create_linear_allocator( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) ) -/* implementation - * ---------------------------------------- - */ - -static void vg_fatal_error( const char *fmt, ... ); - -#if 0 -static void vg_error(const char *fmt, ...); -static void vg_info(const char *fmt, ...); -#endif - -static u32 vg_align8( u32 s ) -{ - u32 m = (s + 7) >> 3; - return m << 3; -} - -static u32 vg_align4( u32 s ) -{ - u32 m = (s + 3) >> 2; - return m << 2; -} - -/* Returns allocator structure from data pointer */ -static vg_linear_allocator *vg_linear_header( void *data ) -{ - vg_linear_allocator *ptr = data; - ptr --; - - return ptr; -} - -/* allocate something from a linear allocator */ -__attribute__((warn_unused_result)) -static void *_vg_linear_alloc( void *buffer, u32 size, - const char *constr_name ) -{ - if( size % 8 ){ - vg_error( "alloc(%u) is not 8 byte aligned\n", size ); - vg_print_backtrace(); - size = vg_align8( size ); - } - if( ((u64)buffer) % 8 ){ - vg_fatal_error( "unaligned buffer (%p)", buffer ); - } - - vg_linear_allocator *alloc = vg_linear_header( buffer ); - - if( (alloc->cur + size) > alloc->size ){ - vg_fatal_error( "linear allocator overflow (%u + %u > %u)\n", - alloc->cur, size, alloc->size ); - } - - if( alloc->flags & VG_MEMORY_SYSTEM ) - if( (alloc->allocation_count + 1) > VG_MAX_ALLOCATIONS ) - vg_fatal_error( "Max linear allocations reached" ); - - void *data; - - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ - data = malloc( size ); - - vg_allocation_meta *meta = &alloc->alloc_table[ alloc->allocation_count ]; - meta->type = k_allocation_type_block; - meta->data = data; - meta->size = size; - meta->name = constr_name; - } - else{ - data = buffer + alloc->cur; - } - - u8 *bytes = data; - for( u32 i=0; iallocation_count ++; - alloc->last_alloc = data; - alloc->last_alloc_size = size; - alloc->cur += size; - - if( ((u64)data) % 8 ){ - vg_fatal_error( "unaligned" ); - } - - return data; -} - -/* resize latest block of memory from linear */ -__attribute__((warn_unused_result)) -static void *vg_linear_resize( void *buffer, void *data, u32 newsize ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - - if( newsize % 8 ){ - vg_error( "alloc(%u) is not 8 byte aligned\n", newsize ); - vg_print_backtrace(); - newsize = vg_align8( newsize ); - } - - if( alloc->last_alloc != data ) - vg_fatal_error( "This block has been fixed!" ); - - if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size ) - vg_fatal_error( "Cannot resize, overflow" ); - - alloc->cur -= alloc->last_alloc_size; - alloc->cur += newsize; - alloc->last_alloc_size = newsize; - - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ - data = realloc( data, newsize ); - if( !data ) - vg_fatal_error( "realloc failed" ); - - alloc->alloc_table[ alloc->allocation_count-1 ].data = data; - alloc->last_alloc = data; - return data; - } - else{ - return data; - } -} - -/* its possible to delete just the last item */ -static void vg_linear_del( void *buffer, void *data ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - - if( alloc->last_alloc != data ){ - vg_fatal_error( "This block has been fixed! Last alloc: %p, this: %p\n", - alloc->last_alloc, data ); - } - - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ - vg_allocation_meta *meta = &alloc->alloc_table[alloc->allocation_count-1]; - if( meta->type == k_allocation_type_linear ) - vg_fatal_error( "Cannot free a linear allocator in this conext" ); - - free( data ); - } - - alloc->allocation_count --; - alloc->cur -= alloc->last_alloc_size; - alloc->last_alloc = NULL; - alloc->last_alloc_size = 0; -} - -/* extend latest block of memory from linear */ -__attribute__((warn_unused_result)) -static void *_vg_linear_extend( void *buffer, void *data, u32 extra, - const char *constr_name ) -{ - if( !data ) - return _vg_linear_alloc( buffer, vg_align8(extra), constr_name ); - - vg_linear_allocator *alloc = vg_linear_header( buffer ); - - if( alloc->last_alloc != data ) - vg_fatal_error( "This block has been fixed!" ); - - u32 new_size = alloc->last_alloc_size + extra; - return vg_linear_resize( buffer, data, vg_align8(new_size) ); -} - -/* get the current usage of allocator */ -static u32 vg_linear_get_cur( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->cur; -} - -/* get the capacity of allocator. */ -static u32 vg_linear_get_capacity( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->size; -} - -/* get the remaining size of the allocator */ -static u32 vg_linear_remaining( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->size - alloc->cur; -} - -/* yeet all memory from linear allocator */ -static void vg_linear_clear( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - - /* libc mode we recursively free any allocations made */ - if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ - for( u32 i=0; iallocation_count; i++ ){ - vg_allocation_meta *meta = &alloc->alloc_table[i]; - - if( meta->type == k_allocation_type_block ){ - free( meta->data ); - } - else{ - vg_linear_clear( meta->data ); - vg_linear_allocator *sub = vg_linear_header( meta->data ); - - free( sub->alloc_table ); - free( sub ); - } - } - } - - alloc->last_alloc = NULL; - alloc->last_alloc_size = 0; - alloc->allocation_count = 0; - alloc->cur = 0; -} - -/* allocate a FIXED SIZE linear allocator */ -static void *_vg_create_linear_allocator( void *lin_alloc, u32 size, - u16 flags, const char *constr_name) -{ - assert( sizeof( vg_linear_allocator ) == 32 ); - - vg_linear_allocator *header; - u32 block_size = size + sizeof(vg_linear_allocator); - - /* Creating it inside an existing one */ - if( lin_alloc ){ - vg_linear_allocator *alloc = vg_linear_header( lin_alloc ); - - if( alloc->cur + block_size > alloc->size ) - vg_fatal_error( "Out of memory" ); - - if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS ) - vg_fatal_error( "Max allocations in linear allocator" ); - - if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) ) - vg_fatal_error( "Cannot declare realtime allocator inside systems" - " allocator" ); - - if( vg_mem.use_libc_malloc ){ - vg_allocation_meta *meta = - &alloc->alloc_table[ alloc->allocation_count ]; - - if( flags & VG_MEMORY_REALTIME ) - header = malloc( block_size ); - else - header = malloc( sizeof(vg_linear_allocator) ); - - meta->data = header+1; - meta->type = k_allocation_type_linear; - meta->size = size; - meta->name = constr_name; - } - else{ - header = lin_alloc + alloc->cur; - } - - alloc->cur += block_size; - alloc->last_alloc = header; - alloc->last_alloc_size = block_size; - alloc->allocation_count ++; - } - else{ - if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) ) - header = malloc( sizeof(vg_linear_allocator) ); - else - header = malloc( block_size ); - } - - header->allocation_count = 0; - header->cur = 0; - header->last_alloc = NULL; - header->last_alloc_size = 0; - header->size = size; - header->flags = flags; - - if( vg_mem.use_libc_malloc && (flags & VG_MEMORY_SYSTEM) ){ - u32 table_size = sizeof(vg_allocation_meta)*VG_MAX_ALLOCATIONS; - header->alloc_table = malloc( table_size ); - } - else - header->alloc_table = NULL; - - return header+1; -} - -/* request all the memory we need in advance */ -static void vg_set_mem_quota( u32 size ) -{ - vg_mem.quota = size; -} - -static void vg_alloc_quota(void) -{ - u32 size_scratch = 10*1024*1024; - u32 size = VG_MAX( vg_mem.quota, size_scratch ); - - vg_mem.rtmemory = _vg_create_linear_allocator( NULL, size, VG_MEMORY_SYSTEM, - "VG Root" ); - vg_mem.scratch = _vg_create_linear_allocator( vg_mem.rtmemory, - size_scratch, - VG_MEMORY_SYSTEM, - "Scratch buffer" ); -} - -static void vg_mem_log( void *lin_alloc, int depth, const char *name ) -{ - if( vg_mem.use_libc_malloc ){ - vg_linear_allocator *alloc = vg_linear_header( lin_alloc ); - - u32 s = alloc->size; - f32 p = ((float)alloc->cur / (float)alloc->size) * 100.0f; - - for( int i=0; iflags & VG_MEMORY_SYSTEM ){ - for( u32 i=0; iallocation_count; i++ ){ - vg_allocation_meta *meta = &alloc->alloc_table[i]; - - if( meta->type == k_allocation_type_block ){ - for( int i=0; iname, meta->size ); - } - else{ - vg_mem_log( meta->data, depth +1, meta->name ); - } - } - } - else{ - for( int i=0; i (UNTRACKED)\n" ); - } - } - else{ - vg_error( "allocations are not tracked (turn on libc mode)\n" ); - } -} - -#endif /* VG_MEM_H */ +void *_vg_create_linear_allocator( void *lin_alloc, u32 size, + u16 flags, const char *constr_name); +vg_linear_allocator *vg_linear_header( void *data );