Commit 8eeda17
memory/arenas.h
@@ -25,6 +25,8 @@ MemArena MemArena_from( MemArena *arena ); /* Get a sub arena, with a new arena
status MemArena_take_amount( MemArena *arena, u64 size, void** out );
#define MemArena_take( arena, type, count, out ) MemArena_take_amount( arena, (sizeof(type))*(count), out )
+status MemArena_give_amount( MemArena *arena, u64 size );
+#define MemArena_give( arena, type, count ) MemArena_give_amount( arena, (sizeof(type))*(count) )
void MemArena_clear( MemArena *arena );
status MemArena_uncommit_unused( MemArena *arena );
@@ -96,9 +98,10 @@ status MemArena_uncommit_unused( MemArena *arena );
}
arena->last_commited = (void*)new_committed;
+ arena->top += (allocation - (u64)arena->top + size);
#if defined(KC_ZERO_MEMORY_STRICT)
- mem_set( arena->top, arena->end - arena->top, 0 );
+ mem_set_range( arena->top, arena->end, 0 );
#endif
*outptr = (void*)allocation;
@@ -106,11 +109,29 @@ status MemArena_uncommit_unused( MemArena *arena );
return STATUS_SUCCESS;
}
+ status MemArena_give_amount( MemArena *arena, u64 size ) {
+ ASSERT_MEM_ARENA_IS_SANE(arena);
+ assert(size);
+
+ if( size > (u64)(arena->top - arena->start) ) {
+ return ERROR_WOULD_UNDERRUN;
+ }
+
+ u8* new_top = arena->top - size;
+ arena->top = new_top;
+
+ #if defined(KC_ZERO_MEMORY_STRICT)
+ mem_set_range( new_top, arena->top, 0 );
+ #endif
+
+ return STATUS_SUCCESS;
+ }
+
void MemArena_clear( MemArena *arena ) {
ASSERT_MEM_ARENA_IS_SANE(arena);
#if defined(KC_ZERO_MEMORY_STRICT)
- mem_set( arena->start, arena->end - arena->start, 0 );
+ mem_set_range( arena->start, arena->end, 0 );
#endif
arena->top = arena->start;
@@ -119,14 +140,15 @@ status MemArena_uncommit_unused( MemArena *arena );
status MemArena_uncommit_unused( MemArena *arena ) {
ASSERT_MEM_ARENA_IS_SANE(arena);
+
+ u8* new_commited = (u8*)ROUND_UP_TO_A_POW2( (u64)arena->top, KC_PLATFORM_MEM_PAGESIZE );
+
#if defined(KC_ZERO_MEMORY_STRICT)
- mem_set( arena->top, arena->end - arena->start, 0 );
+ mem_set_range( new_commited, arena->last_commited, 0 );
#endif
+ PROPAGATE_ERROR( kc_platform_mem_va_uncommit( new_commited, arena->last_commited - new_commited ) );
- u64 new_last_commit = ROUND_UP_TO_A_POW2( arena->top, KC_PLATFORM_MEM_PAGESIZE );
-
- PROPAGATE_ERROR( kc_platform_mem_va_uncommit( (void*)new_last_commit, (u64)arena->last_commited - new_last_commit) );
- arena->last_commited = (u8*)new_last_commit;
+ arena->last_commited = new_commited;
return STATUS_SUCCESS;
}
memory/ops.h
@@ -6,6 +6,6 @@
status mem_copy( void *src, void *dst, u64 size );
status mem_move( void *src, void *dst, u64 size );
status mem_set( void *buf, u64 size, u8 value );
-
+status mem_set_range( void *start, void *end, u8 value );
#endif
tests/a.out
Binary file
tests/main.c
@@ -10,7 +10,7 @@
int main(void) {
-MemArena a;
+ MemArena a;
assert(OK( MemArena_create( &a, GiB(120) )) );
@@ -21,8 +21,11 @@ MemArena a;
data[i] = 'K';
}
- MemArena_uncommit_unused( &a );
+ assert( OK(MemArena_give_amount( &a, MiB(512) ) ));
+ assert( OK(MemArena_uncommit_unused( &a )));
+ assert( OK(MemArena_give_amount( &a, MiB(512) ) ));
+ assert( OK(MemArena_uncommit_unused( &a )));
assert(OK(MemArena_destroy(&a)));
}
tests/main.o
Binary file
types/types.h
@@ -18,6 +18,7 @@ enum _Status {
STATUS_SUCCESS = 0,
ERROR_GENERIC = 1,
ERROR_WOULD_OVERRUN = 2,
+ ERROR_WOULD_UNDERRUN = 3,
ERROR_PLATFORM_GENERIC = 10000,
ERROR_PLATFORM_MAPPING_FAILED = 10001,