#include "vg.h"
#include "vg_stdint.h"
#include "vg_platform.h"
+#include "vg_log.h"
#include <stdlib.h>
#include <malloc.h>
typedef struct vg_linear_allocator vg_linear_allocator;
typedef struct vg_allocation_meta vg_allocation_meta;
-struct
-{
+struct{
void *rtmemory,
*scratch;
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;
};
#pragma pack(pop)
+VG_STATIC u32 vg_align8( u32 s );
+VG_STATIC 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,
+ 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 );
+
+/* its possible to delete just the last item */
+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,
+ const char *constr_name );
+
+/* get the current usage of allocator */
+VG_STATIC u32 vg_linear_get_cur( void *buffer );
+
+/* get the capacity of allocator. */
+VG_STATIC u32 vg_linear_get_capacity( void *buffer );
+
+/* get the remaining size of the allocator */
+VG_STATIC u32 vg_linear_remaining( void *buffer );
+
+/* yeet all memory from linear allocator */
+VG_STATIC void vg_linear_clear( void *buffer );
+
+/* request all the memory we need in advance */
+VG_STATIC void vg_set_mem_quota( u32 size );
+
+/* essentially init() */
+VG_STATIC void vg_alloc_quota(void);
+
+/* print out tree of current memory used. only works with libc mode */
+VG_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
+ * ----------------------------------------
+ */
+
VG_STATIC void vg_fatal_error( const char *fmt, ... );
+
+#if 0
VG_STATIC void vg_error(const char *fmt, ...);
VG_STATIC void vg_info(const char *fmt, ...);
+#endif
VG_STATIC u32 vg_align8( u32 s )
{
/* allocate something from a linear allocator */
__attribute__((warn_unused_result))
-VG_STATIC void *vg_linear_alloc( void *buffer, u32 size )
+VG_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_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;
/* extend latest block of memory from linear */
__attribute__((warn_unused_result))
-VG_STATIC void *vg_linear_extend( void *buffer, void *data, u32 extra )
+VG_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 );
}
/* allocate a FIXED SIZE linear allocator */
-VG_STATIC void *vg_create_linear_allocator( void *lin_alloc, u32 size,
- u16 flags )
+VG_STATIC void *_vg_create_linear_allocator( void *lin_alloc, u32 size,
+ u16 flags, const char *constr_name)
{
assert( sizeof( vg_linear_allocator ) == 32 );
meta->data = header+1;
meta->type = k_allocation_type_linear;
+ meta->size = size;
+ meta->name = constr_name;
}
else{
header = lin_alloc + alloc->cur;
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_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 */