bad char
[vg.git] / vg_mem.h
index 6aa22f273abfec1878cd22914a295540149d8d83..6fde883b7643e7c91ad5b58a35ee63e35679082f 100644 (file)
--- 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 <stdlib.h>
-#include <malloc.h>
-
-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,353 +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; i<size; i++ ){
-      bytes[i] = 0xfe;
-   }
-
-   alloc->allocation_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; i<alloc->allocation_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
- *
- * FIXME: there was a bug in vg's code that caused a race condition between
- *        two system allocations. make this IMPOSSIBLE by requiring a lock
- *        on the allocater to be passed between threads.
- *
- *        luckily that bug only exists when using development tools, but still!
- *
- *        this should then only be checked and turned on in debugging.
- *
- */
-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; 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 */
+void *_vg_create_linear_allocator( void *lin_alloc, u32 size, 
+                                   u16 flags, const char *constr_name);
+vg_linear_allocator *vg_linear_header( void *data );