X-Git-Url: https://harrygodden.com/git/?p=vg.git;a=blobdiff_plain;f=vg_mem.h;h=3a7a49da06814fe9c2c7d1d1b082ee6cc6a8ed5a;hp=598bc83c352f3c7e382a0835cad459b0cbb2a113;hb=HEAD;hpb=651edda3736812c89f43c11319c6b485ff14ea19 diff --git a/vg_mem.h b/vg_mem.h index 598bc83..6fde883 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -1,22 +1,11 @@ -#ifndef VG_MEM_H -#define VG_MEM_H - -#include "vg.h" -#include "vg_stdint.h" -#include "vg_platform.h" - -#include -#include - -VG_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; @@ -24,14 +13,15 @@ struct int use_libc_malloc; u32 quota; } -static vg_mem; +extern vg_mem; struct vg_allocation_meta { + const char *name; void *data; - enum allocation_type - { - k_allocation_type_block = 0, + u32 size; + enum allocation_type{ + k_allocation_type_block = 0, k_allocation_type_linear = 1 } type; @@ -40,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. */ @@ -49,340 +37,65 @@ struct vg_allocation_meta struct vg_linear_allocator { u32 size; - /* */ - /* */ - /* */ u32 cur; - /* */ - /* */ - /* */ u16 allocation_count; - /* */ u16 flags; - /* */ u32 last_alloc_size; - /* */ - /* */ - /* */ void *last_alloc; - /* */ - /* */ - /* */ - /* */ - /* */ - /* */ - /* */ vg_allocation_meta *alloc_table; - /* */ - /* */ - /* */ - /* */ - /* */ - /* */ - /* */ - -#ifdef _WIN32 - /* 32 bit pointers! */ - u8 padding[ 8 ]; -#endif }; #pragma pack(pop) -VG_STATIC void vg_fatal_error( const char *fmt, ... ); -VG_STATIC void vg_error(const char *fmt, ...); -VG_STATIC void vg_info(const char *fmt, ...); - -VG_STATIC u32 vg_align8( u32 s ) -{ - u32 m = (s + 7) >> 3; - return m << 3; -} - -VG_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; -} +u32 vg_align8( u32 s ); +u32 vg_align4( u32 s ); /* allocate something from a linear allocator */ __attribute__((warn_unused_result)) -VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) -{ - if( size % 8 ){ - vg_error( "alloc(%u) is not 8 byte aligned\n", size ); - vg_print_backtrace(); - size = vg_align8( size ); - } -#ifdef _WIN32 - if( ((u32)buffer) % 8 ){ -#else - if( ((u64)buffer) % 8 ){ -#endif - 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; - } - 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; - -#ifdef _WIN32 - if( ((u32)data) % 8 ){ -#else - if( ((u64)data) % 8 ){ -#endif - vg_fatal_error( "unaligned" ); - } - - return data; -} +void *_vg_linear_alloc( void *buffer, u32 size, const char *constr_name ); /* resize latest block of memory from linear */ __attribute__((warn_unused_result)) -VG_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; - } -} +void *vg_linear_resize( void *buffer, void *data, u32 newsize ); /* its possible to delete just the last item */ -VG_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!" ); - - 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; -} +void vg_linear_del( void *buffer, void *data ); /* extend latest block of memory from linear */ __attribute__((warn_unused_result)) -VG_STATIC void *vg_linear_extend( void *buffer, void *data, u32 extra ) -{ - if( !data ) - return vg_linear_alloc( buffer, extra ); - - 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, new_size ); -} +void *_vg_linear_extend( void *buffer, void *data, u32 extra, + const char *constr_name ); /* get the current usage of allocator */ -VG_STATIC u32 vg_linear_get_cur( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->cur; -} +u32 vg_linear_get_cur( void *buffer ); /* get the capacity of allocator. */ -VG_STATIC u32 vg_linear_get_capacity( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->size; -} +u32 vg_linear_get_capacity( void *buffer ); /* get the remaining size of the allocator */ -VG_STATIC u32 vg_linear_remaining( void *buffer ) -{ - vg_linear_allocator *alloc = vg_linear_header( buffer ); - return alloc->size - alloc->cur; -} +u32 vg_linear_remaining( void *buffer ); /* yeet all memory from linear allocator */ -VG_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 ); - } - } - } +void vg_linear_clear( void *buffer ); - alloc->last_alloc = NULL; - alloc->last_alloc_size = 0; - alloc->allocation_count = 0; - alloc->cur = 0; -} - -/* allocate a FIXED SIZE linear allocator */ -VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, - u16 flags ) -{ - 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; - } - else{ - header = lin_alloc + alloc->cur; - } - - alloc->cur += block_size; - alloc->last_alloc = NULL; /* cant resize this block! */ - 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 ); - } +/* request all the memory we need in advance */ +void vg_set_mem_quota( u32 size ); - header->allocation_count = 0; - header->cur = 0; - header->last_alloc = NULL; - header->last_alloc_size = 0; - header->size = size; - header->flags = flags; +/* essentially init() */ +void vg_alloc_quota(void); - 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; +/* print out tree of current memory used. only works with libc mode */ +void vg_mem_log( void *lin_alloc, int depth, const char *name ); - return header+1; -} +#define VG_MEM_MCSTR(S) VG_MEM_MCSTR2(S) +#define VG_MEM_MCSTR2(S) #S -/* request all the memory we need in advance */ -VG_STATIC void vg_set_mem_quota( u32 size ) -{ - vg_mem.quota = size; -} - -VG_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_mem.scratch = vg_create_linear_allocator( vg_mem.rtmemory, - size_scratch, - VG_MEMORY_SYSTEM ); -} +#define vg_linear_alloc(...) \ + _vg_linear_alloc( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) ) +#define vg_linear_extend(...) \ + _vg_linear_extend( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) ) +#define vg_create_linear_allocator(...) \ + _vg_create_linear_allocator( __VA_ARGS__, __FILE__":"VG_MEM_MCSTR(__LINE__) ) -#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 );