replace VG_STATIC -> static
[vg.git] / vg_mem.h
index 8f3da6361396d97577c1334e401bf1b251462206..be11ddd2ef4ce43741b1d23f89eb1718c9a4680f 100644 (file)
--- 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 <stdlib.h>
 #include <malloc.h>
 
-VG_STATIC void vg_print_backtrace(void);
+static void vg_print_backtrace(void);
 
 #define VG_MAX_ALLOCATIONS 128
 #define VG_FUZZ_ALLOCATIONS
@@ -16,11 +17,9 @@ 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,
-        *async;
+        *scratch;
 
    int   use_libc_malloc;
    u32   quota;
@@ -29,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;
@@ -50,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! */
@@ -89,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;
@@ -116,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 );
@@ -128,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;
 
@@ -151,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;
@@ -158,7 +193,7 @@ VG_STATIC void *vg_linear_alloc( void *buffer, u32 size )
 
    u8 *bytes = data;
    for( u32 i=0; i<size; i++ ){
-      bytes[i] = 0xae;
+      bytes[i] = 0xfe;
    }
 
    alloc->allocation_count ++;
@@ -171,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;
@@ -179,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 );
 
@@ -190,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;
@@ -202,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;
@@ -214,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 );
    }
@@ -237,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 );
 
@@ -302,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 );
 
@@ -315,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 ){
@@ -335,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{
@@ -371,23 +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" );
+}
 
-   vg_mem.async = vg_create_linear_allocator( NULL, 50*1024*1024, 
-                                              VG_MEMORY_REALTIME );
+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; i<depth; i++ ) printf( "  " );
+      printf( "LA(%s): %u bytes, %f%% used\n", name, s, p );
+
+      if( alloc->flags & VG_MEMORY_SYSTEM ){
+         for( u32 i=0; i<alloc->allocation_count; i++ ){
+            vg_allocation_meta *meta = &alloc->alloc_table[i];
+            
+            if( meta->type == k_allocation_type_block ){
+               for( int i=0; i<depth+1; i++ ) printf( "  " );
+               printf( "B(%s): %u bytes\n", meta->name, meta->size );
+            }
+            else{
+               vg_mem_log( meta->data, depth +1, meta->name );
+            }
+         }
+      }
+      else{
+         for( int i=0; i<depth+1; i++ ) printf( "  " );
+         printf( "<opaque memory> (UNTRACKED)\n" );
+      }
+   }
+   else{
+      vg_error( "allocations are not tracked (turn on libc mode)\n" );
+   }
 }
 
 #endif /* VG_MEM_H */