X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=vg_mem.h;h=be11ddd2ef4ce43741b1d23f89eb1718c9a4680f;hb=76d234b7dc5e6500e8a54009b367e7620f11ef97;hp=49d9e37e86b8af8d515a64a164d64873e6d6f59f;hpb=5324992ccec2857770963843fcdb6e44ce2c1a37;p=vg.git diff --git a/vg_mem.h b/vg_mem.h index 49d9e37..be11ddd 100644 --- a/vg_mem.h +++ b/vg_mem.h @@ -4,11 +4,12 @@ #include "vg.h" #include "vg_stdint.h" #include "vg_platform.h" +#include "vg_log.h" #include #include -VG_STATIC void vg_print_backtrace(void); +static void vg_print_backtrace(void); #define VG_MAX_ALLOCATIONS 128 #define VG_FUZZ_ALLOCATIONS @@ -16,8 +17,7 @@ VG_STATIC void vg_print_backtrace(void); typedef struct vg_linear_allocator vg_linear_allocator; typedef struct vg_allocation_meta vg_allocation_meta; -struct -{ +struct{ void *rtmemory, *scratch; @@ -28,10 +28,11 @@ static 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; @@ -49,37 +50,12 @@ 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! */ @@ -88,17 +64,75 @@ struct vg_linear_allocator }; #pragma pack(pop) -VG_STATIC void vg_fatal_exit_loop( const char *error ); -VG_STATIC void vg_error(const char *fmt, ...); -VG_STATIC void vg_info(const char *fmt, ...); +static u32 vg_align8( u32 s ); +static 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 ); + +/* resize latest block of memory from linear */ +__attribute__((warn_unused_result)) +static 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 ); + +/* 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 ); + +/* get the current usage of allocator */ +static u32 vg_linear_get_cur( void *buffer ); + +/* get the capacity of allocator. */ +static u32 vg_linear_get_capacity( void *buffer ); + +/* get the remaining size of the allocator */ +static u32 vg_linear_remaining( void *buffer ); + +/* yeet all memory from linear allocator */ +static void vg_linear_clear( void *buffer ); + +/* request all the memory we need in advance */ +static void vg_set_mem_quota( u32 size ); + +/* essentially init() */ +static void vg_alloc_quota(void); -VG_STATIC u32 vg_align8( u32 s ) +/* 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 ); + +#define VG_MEM_MCSTR(S) VG_MEM_MCSTR2(S) +#define VG_MEM_MCSTR2(S) #S + +#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__) ) + +/* 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; } -VG_STATIC u32 vg_align4( u32 s ) +static u32 vg_align4( u32 s ) { u32 m = (s + 3) >> 2; return m << 2; @@ -115,7 +149,8 @@ static vg_linear_allocator *vg_linear_header( void *data ) /* allocate something from a linear allocator */ __attribute__((warn_unused_result)) -VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) +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 ); @@ -127,20 +162,19 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) #else if( ((u64)buffer) % 8 ){ #endif - vg_error( "buffer: %p\n", buffer ); - vg_fatal_exit_loop( "unaligned buffer" ); + vg_fatal_error( "unaligned buffer (%p)", buffer ); } vg_linear_allocator *alloc = vg_linear_header( buffer ); if( (alloc->cur + size) > alloc->size ){ - vg_error( "%u + %u > %u\n", alloc->cur, size, alloc->size ); - vg_fatal_exit_loop( "linear allocator overflow" ); + 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_exit_loop( "Max linear allocations reached" ); + vg_fatal_error( "Max linear allocations reached" ); void *data; @@ -150,6 +184,8 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 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; @@ -157,7 +193,7 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) u8 *bytes = data; for( u32 i=0; iallocation_count ++; @@ -170,7 +206,7 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) #else if( ((u64)data) % 8 ){ #endif - vg_fatal_exit_loop( "unaligned" ); + vg_fatal_error( "unaligned" ); } return data; @@ -178,7 +214,7 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 size ) /* resize latest block of memory from linear */ __attribute__((warn_unused_result)) -VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize ) +static void *vg_linear_resize( void *buffer, void *data, u32 newsize ) { vg_linear_allocator *alloc = vg_linear_header( buffer ); @@ -189,10 +225,10 @@ VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize ) } if( alloc->last_alloc != data ) - vg_fatal_exit_loop( "This block has been fixed!" ); + vg_fatal_error( "This block has been fixed!" ); if( (alloc->cur - alloc->last_alloc_size + newsize) > alloc->size ) - vg_fatal_exit_loop( "Cannot resize, overflow" ); + vg_fatal_error( "Cannot resize, overflow" ); alloc->cur -= alloc->last_alloc_size; alloc->cur += newsize; @@ -201,7 +237,7 @@ VG_STATIC void *vg_linear_resize( void *buffer, void *data, u32 newsize ) if( vg_mem.use_libc_malloc && (alloc->flags & VG_MEMORY_SYSTEM) ){ data = realloc( data, newsize ); if( !data ) - vg_fatal_exit_loop( "realloc failed" ); + vg_fatal_error( "realloc failed" ); alloc->alloc_table[ alloc->allocation_count-1 ].data = data; alloc->last_alloc = data; @@ -213,17 +249,19 @@ VG_STATIC 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 ) +static void vg_linear_del( void *buffer, void *data ) { vg_linear_allocator *alloc = vg_linear_header( buffer ); - if( alloc->last_alloc != data ) - vg_fatal_exit_loop( "This block has been fixed!" ); + 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_exit_loop( "Cannot free a linear allocator in this conext" ); + vg_fatal_error( "Cannot free a linear allocator in this conext" ); free( data ); } @@ -236,43 +274,44 @@ VG_STATIC 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 ) +static void *_vg_linear_extend( void *buffer, void *data, u32 extra, + const char *constr_name ) { if( !data ) - return vg_linear_alloc( buffer, extra ); + return _vg_linear_alloc( buffer, extra, constr_name ); vg_linear_allocator *alloc = vg_linear_header( buffer ); if( alloc->last_alloc != data ) - vg_fatal_exit_loop( "This block has been fixed!" ); + vg_fatal_error( "This block has been fixed!" ); u32 new_size = alloc->last_alloc_size + extra; return vg_linear_resize( buffer, data, new_size ); } /* get the current usage of allocator */ -VG_STATIC u32 vg_linear_get_cur( void *buffer ) +static u32 vg_linear_get_cur( void *buffer ) { vg_linear_allocator *alloc = vg_linear_header( buffer ); return alloc->cur; } /* get the capacity of allocator. */ -VG_STATIC u32 vg_linear_get_capacity( void *buffer ) +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 */ -VG_STATIC u32 vg_linear_remaining( void *buffer ) +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 */ -VG_STATIC void vg_linear_clear( void *buffer ) +static void vg_linear_clear( void *buffer ) { vg_linear_allocator *alloc = vg_linear_header( buffer ); @@ -301,8 +340,8 @@ VG_STATIC void vg_linear_clear( void *buffer ) } /* allocate a FIXED SIZE linear allocator */ -VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, - u16 flags ) +static void *_vg_create_linear_allocator( void *lin_alloc, u32 size, + u16 flags, const char *constr_name) { assert( sizeof( vg_linear_allocator ) == 32 ); @@ -314,13 +353,13 @@ VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, vg_linear_allocator *alloc = vg_linear_header( lin_alloc ); if( alloc->cur + block_size > alloc->size ) - vg_fatal_exit_loop( "Out of memory" ); + vg_fatal_error( "Out of memory" ); if( alloc->allocation_count + 1 > VG_MAX_ALLOCATIONS ) - vg_fatal_exit_loop( "Max allocations in linear allocator" ); + vg_fatal_error( "Max allocations in linear allocator" ); if( (flags && VG_MEMORY_SYSTEM) && (alloc->flags & VG_MEMORY_REALTIME) ) - vg_fatal_exit_loop( "Cannot declare realtime allocator inside systems" + vg_fatal_error( "Cannot declare realtime allocator inside systems" " allocator" ); if( vg_mem.use_libc_malloc ){ @@ -334,15 +373,16 @@ VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, 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 = NULL; /* cant resize this block! */ + alloc->last_alloc = header; alloc->last_alloc_size = block_size; - alloc->allocation_count ++; } else{ @@ -370,20 +410,56 @@ VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size, } /* request all the memory we need in advance */ -VG_STATIC void vg_set_mem_quota( u32 size ) +static void vg_set_mem_quota( u32 size ) { vg_mem.quota = size; } -VG_STATIC void vg_alloc_quota(void) +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 ); + 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 */