diff --git a/sp.h b/sp.h index 6c62666..efb3b43 100644 --- a/sp.h +++ b/sp.h @@ -1452,7 +1452,7 @@ typedef enum { SP_TYPEDEF_FN( void*, sp_allocator_fn_t, - void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr + void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size ); typedef struct sp_allocator_t { @@ -1461,11 +1461,11 @@ typedef struct sp_allocator_t { } sp_mem_t; SP_API void* sp_mem_allocator_alloc(sp_mem_t arena, u64 size); -SP_API void* sp_mem_allocator_realloc(sp_mem_t arena, void* ptr, u64 size); -SP_API void sp_mem_allocator_free(sp_mem_t arena, void* buffer); +SP_API void* sp_mem_allocator_realloc(sp_mem_t arena, void* ptr, u64 old_size, u64 size); +SP_API void sp_mem_allocator_free(sp_mem_t arena, void* buffer, u64 size); SP_API void* sp_alloc(sp_mem_t mem, u64 size); -SP_API void* sp_realloc(sp_mem_t mem, void* memory, u64 size); -SP_API void sp_free(sp_mem_t mem, void* memory); +SP_API void* sp_realloc(sp_mem_t mem, void* memory, u64 old_size, u64 size); +SP_API void sp_free(sp_mem_t mem, void* memory, u64 size); SP_API sp_mem_t sp_mem_get_scratch(); ////////// @@ -1501,33 +1501,24 @@ SP_API sp_mem_fixed_t sp_mem_fixed_ex(void* buffer, u64 capacity, u8 alignment); SP_API sp_mem_t sp_mem_fixed_as_allocator(sp_mem_fixed_t* fixed); SP_API void sp_mem_fixed_clear(sp_mem_fixed_t* fixed); SP_API u64 sp_mem_fixed_bytes_used(sp_mem_fixed_t* fixed); -SP_API void* sp_mem_fixed_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old); +SP_API void* sp_mem_fixed_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old, u64 old_size); //////////////////// // PAGE ALLOCATOR // //////////////////// -typedef struct SP_ALIGNED { - u64 size; -} sp_mem_os_header_t; - SP_API void* sp_mem_os_alloc(u64 size); -SP_API void* sp_mem_os_realloc(void* ptr, u64 size); -SP_API void sp_mem_os_free(void* ptr); -SP_API void* sp_mem_os_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr); -SP_API sp_mem_os_header_t* sp_mem_os_get_header(void* ptr); +SP_API void* sp_mem_os_realloc(void* ptr, u64 old_size, u64 size); +SP_API void sp_mem_os_free(void* ptr, u64 size); +SP_API void* sp_mem_os_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size); SP_API sp_mem_t sp_mem_os_new(); ///////////////////// // ARENA ALLOCATOR // ///////////////////// -typedef enum { - SP_MEM_ARENA_MODE_DEFAULT, - SP_MEM_ARENA_MODE_NO_REALLOC, -} sp_mem_arena_mode_t; +#define SP_MEM_ARENA_MAX_BLOCK_SIZE (1 << 20) -typedef struct sp_mem_arena_block_t { +typedef struct SP_ALIGNED sp_mem_arena_block_t { struct sp_mem_arena_block_t* next; - u8* buffer; u64 capacity; u64 bytes_used; } sp_mem_arena_block_t; @@ -1537,7 +1528,6 @@ typedef struct { sp_mem_arena_block_t* head; sp_mem_arena_block_t* current; u64 block_size; - sp_mem_arena_mode_t mode; u8 alignment; } sp_mem_arena_t; @@ -1549,18 +1539,18 @@ typedef struct { } sp_mem_arena_marker_t; SP_API sp_mem_arena_t* sp_mem_arena_new(sp_mem_t mem); -SP_API sp_mem_arena_t* sp_mem_arena_new_ex(sp_mem_t mem, u64 block_size, sp_mem_arena_mode_t mode, u8 alignment); +SP_API sp_mem_arena_t* sp_mem_arena_new_ex(sp_mem_t mem, u64 block_size, u8 alignment); SP_API sp_mem_t sp_mem_arena_as_allocator(sp_mem_arena_t* arena); SP_API void sp_mem_arena_clear(sp_mem_arena_t* arena); SP_API void sp_mem_arena_destroy(sp_mem_arena_t* arena); -SP_API void* sp_mem_arena_on_alloc(void* ptr, sp_mem_alloc_mode_t mode, u64 n, void* old); +SP_API void* sp_mem_arena_on_alloc(void* ptr, sp_mem_alloc_mode_t mode, u64 n, void* old, u64 old_size); SP_API sp_mem_arena_marker_t sp_mem_arena_mark(sp_mem_arena_t* a); SP_API void sp_mem_arena_pop(sp_mem_arena_marker_t marker); SP_API u64 sp_mem_arena_capacity(sp_mem_arena_t* arena); SP_API u64 sp_mem_arena_bytes_used(sp_mem_arena_t* arena); SP_API void* sp_mem_arena_alloc(sp_mem_arena_t* arena, u64 size); -SP_API void* sp_mem_arena_realloc(sp_mem_arena_t* arena, void* ptr, u64 size); -SP_API void sp_mem_arena_free(sp_mem_arena_t* arena, void* ptr); +SP_API void* sp_mem_arena_realloc(sp_mem_arena_t* arena, void* ptr, u64 old_size, u64 size); +SP_API void sp_mem_arena_free(sp_mem_arena_t* arena, void* ptr, u64 size); SP_API sp_mem_arena_t* sp_mem_get_scratch_arena(); SP_API sp_mem_arena_t* sp_mem_get_scratch_arena_for(sp_mem_t mem); SP_API sp_mem_arena_marker_t sp_mem_begin_scratch(); @@ -1675,7 +1665,7 @@ typedef struct sp_mem_heap_t { SP_API sp_mem_heap_t* sp_mem_heap_new(); SP_API void sp_mem_heap_destroy(sp_mem_heap_t* heap); SP_API sp_mem_t sp_mem_heap_as_allocator(sp_mem_heap_t* heap); -SP_API void* sp_mem_heap_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr); +SP_API void* sp_mem_heap_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size); SP_API void* sp_mem_heap_alloc(sp_mem_heap_t* heap, u64 size); SP_API void* sp_mem_heap_realloc(sp_mem_heap_t* heap, void* ptr, u64 size); SP_API void sp_mem_heap_free(sp_mem_heap_t* heap, void* ptr); @@ -1783,7 +1773,7 @@ SP_API void sp_da_push_ex(void** arr, void* val, u32 stride); ((__T*)sp_da_init_ex((__a), sizeof(__T))) #define sp_da_free(__arr) \ - sp_mem_allocator_free(sp_da_mem(__arr), sp_da_head(__arr)) + sp_mem_allocator_free(sp_da_mem(__arr), sp_da_head(__arr), sp_da_capacity(__arr) * sp_da_stride(__arr) + sizeof(sp_da_header_t)) #define sp_da_grow(__ARR, __N)\ sp_da_grow_ex((__ARR), sp_da_stride(__ARR), (__N)) @@ -1876,7 +1866,7 @@ SP_API void* sp_rb_grow_ex(void* arr, u32 stride, u32 new_cap); #define sp_rb_free(__ARR)\ do {\ if (__ARR) {\ - sp_mem_allocator_free(sp_rb_mem(__ARR), sp_rb_head(__ARR));\ + sp_mem_allocator_free(sp_rb_mem(__ARR), sp_rb_head(__ARR), sp_rb_capacity(__ARR) * sizeof(*(__ARR)) + sizeof(sp_ring_buffer_t));\ (__ARR) = SP_NULLPTR;\ }\ } while (0) @@ -2095,9 +2085,9 @@ SP_BEGIN_EXTERN_C() #define sp_ht_free(ht) \ do { \ if ((ht)) { \ - sp_mem_allocator_free((ht)->info.allocator, (ht)->data); \ + sp_mem_allocator_free((ht)->info.allocator, (ht)->data, (ht)->capacity * sizeof((ht)->data[0])); \ (ht)->data = SP_NULLPTR;\ - sp_mem_allocator_free((ht)->info.allocator, (ht)); \ + sp_mem_allocator_free((ht)->info.allocator, (ht), sizeof(*(ht))); \ (ht) = SP_NULLPTR; \ } \ } while (0) @@ -3432,6 +3422,7 @@ SP_API sp_err_t sp_io_dyn_mem_writer_seek(sp_io_dyn_mem_writer_t* w, s64 o SP_API sp_err_t sp_io_dyn_mem_writer_size(sp_io_dyn_mem_writer_t* w, u64* size); SP_API sp_err_t sp_io_dyn_mem_writer_close(sp_io_dyn_mem_writer_t* w); SP_API sp_str_t sp_io_dyn_mem_writer_as_str(sp_io_dyn_mem_writer_t* w); +SP_API sp_str_t sp_io_dyn_mem_writer_take_str(sp_io_dyn_mem_writer_t* w); SP_API const c8* sp_io_dyn_mem_writer_as_cstr(sp_io_dyn_mem_writer_t* w); SP_API sp_io_stream_writer_t sp_io_get_std_out(); @@ -3747,11 +3738,9 @@ SP_IMP sp_fmt_arg_t sp_fmt_arg_from_argv(sp_fmt_argv_t v); SP_IMP sp_hash_t sp_hash_str(sp_str_t str); // @memory -SP_IMP sp_mem_arena_block_t* sp_mem_arena_block_new(sp_mem_arena_t* arena, u64 capacity); -SP_IMP void* sp_mem_arena_align_block(sp_mem_arena_block_t* block, u8 alignment); -SP_IMP sp_mem_arena_block_t* sp_mem_arena_get_block(sp_mem_arena_t* arena, u64 alloc_size); -SP_IMP void* sp_mem_arena_alloc_with_header(sp_mem_arena_t* arena, u64 size); -SP_IMP void* sp_mem_arena_alloc_no_header(sp_mem_arena_t* arena, u64 size); +SP_IMP sp_mem_arena_block_t* sp_mem_arena_block_new(sp_mem_arena_t* arena, u64 block_size); +SP_IMP u64 sp_mem_arena_block_align(sp_mem_arena_block_t* block, u8 alignment); +SP_IMP sp_mem_arena_block_t* sp_mem_arena_get_block(sp_mem_arena_t* arena, u64 size); SP_IMP u32 sp_mem_heap_bucket_of(u64 size); SP_IMP u64 sp_mem_heap_bucket_size(u32 bucket); SP_IMP void sp_mem_heap_track_reserve(sp_mem_heap_t* heap, u64 bytes); @@ -6930,7 +6919,7 @@ void sp_ht_resize_impl(void** data, u64 old_cap, u64 new_cap, sp_ht_info_t info) *(sp_ht_entry_state*)((c8*)new_data + new_idx * info.stride.entry + info.stride.kv) = SP_HT_ENTRY_ACTIVE; } - sp_free(info.allocator, old_data); + sp_free(info.allocator, old_data, old_cap * info.stride.entry); *data = new_data; } @@ -7021,7 +7010,8 @@ void* sp_da_resize(void* arr, u32 stride, u64 cap) { cap = sp_max(cap, 4); sp_da_header_t* header = sp_da_head(arr); - header = sp_cast(sp_da_header_t*, sp_realloc(header->allocator, header, cap * stride + sizeof(sp_da_header_t))); + u64 old_size = header->capacity * stride + sizeof(sp_da_header_t); + header = sp_cast(sp_da_header_t*, sp_realloc(header->allocator, header, old_size, cap * stride + sizeof(sp_da_header_t))); if (!header) return SP_NULLPTR; @@ -7110,7 +7100,7 @@ void* sp_rb_grow_ex(void* arr, u32 stride, u32 capacity) { sp_mem_copy(new_arr + first_chunk * stride, old_arr, second_chunk * stride); } - sp_mem_allocator_free(mem, old); + sp_mem_allocator_free(mem, old, old_cap * stride + sizeof(sp_ring_buffer_t)); return (u8*)(rb + 1); } @@ -8003,8 +7993,8 @@ void sp_rt_init() { void sp_tls_rt_deinit(void* ptr) { if (!ptr) return; sp_tls_rt_t* tls = (sp_tls_rt_t*)ptr; - if (tls->std.out) sp_mem_allocator_free(tls->mem, tls->std.out); - if (tls->std.err) sp_mem_allocator_free(tls->mem, tls->std.err); + if (tls->std.out) sp_mem_allocator_free(tls->mem, tls->std.out, sizeof(sp_io_stream_writer_t)); + if (tls->std.err) sp_mem_allocator_free(tls->mem, tls->std.err, sizeof(sp_io_stream_writer_t)); sp_str_ht_free(tls->format.directives); sp_carr_for(tls->scratch, it) { sp_mem_arena_destroy(tls->scratch[it]); @@ -8168,45 +8158,49 @@ void sp_tls_once(sp_tls_once_t* once, sp_tls_once_fn_t fn) { // @memory void* sp_mem_allocator_alloc(sp_mem_t allocator, u64 size) { - return allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_ALLOC, size, NULL); + return allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_ALLOC, size, NULL, 0); } -void* sp_mem_allocator_realloc(sp_mem_t allocator, void* memory, u64 size) { - return allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_RESIZE, size, memory); +void* sp_mem_allocator_realloc(sp_mem_t allocator, void* memory, u64 old_size, u64 size) { + return allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_RESIZE, size, memory, old_size); } -void sp_mem_allocator_free(sp_mem_t allocator, void* buffer) { - allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_FREE, 0, buffer); +void sp_mem_allocator_free(sp_mem_t allocator, void* buffer, u64 size) { + allocator.on_alloc(allocator.user_data, SP_ALLOCATOR_MODE_FREE, 0, buffer, size); } -typedef struct { - u64 size; - u8 padding [8]; -} sp_mem_arena_header_t; +u8* sp_mem_arena_block_buffer(sp_mem_arena_block_t* block) { + return (u8*)(block + 1); +} -sp_mem_arena_block_t* sp_mem_arena_block_new(sp_mem_arena_t* arena, u64 capacity) { - sp_mem_arena_block_t* block = sp_mem_allocator_alloc_type(arena->allocator, sp_mem_arena_block_t); +sp_mem_arena_block_t* sp_mem_arena_block_new(sp_mem_arena_t* arena, u64 block_size) { + sp_mem_arena_block_t* block = (sp_mem_arena_block_t*)sp_mem_allocator_alloc(arena->allocator, block_size); + if (!block) return SP_NULLPTR; block->next = SP_NULLPTR; - block->buffer = sp_mem_allocator_alloc_n(arena->allocator, u8, capacity); - block->capacity = capacity; + block->capacity = block_size - sizeof(sp_mem_arena_block_t); block->bytes_used = 0; return block; } sp_mem_arena_t* sp_mem_arena_new(sp_mem_t mem) { - return sp_mem_arena_new_ex(mem, 4096, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + return sp_mem_arena_new_ex(mem, 4096, SP_MEM_ALIGNMENT); } -sp_mem_arena_t* sp_mem_arena_new_ex(sp_mem_t mem, u64 block_size, sp_mem_arena_mode_t mode, u8 alignment) { +sp_mem_arena_t* sp_mem_arena_new_ex(sp_mem_t mem, u64 block_size, u8 alignment) { sp_mem_arena_t* arena = (sp_mem_arena_t*)sp_mem_allocator_alloc(mem, sizeof(sp_mem_arena_t)); + if (!arena) return SP_NULLPTR; arena->allocator = mem; - arena->mode = mode; arena->alignment = alignment == 0 ? SP_MEM_ALIGNMENT : alignment; + sp_assert((arena->alignment & (arena->alignment - 1)) == 0); + arena->block_size = sp_max(block_size, sizeof(sp_mem_arena_block_t) + arena->alignment); - sp_mem_arena_block_t* block = sp_mem_arena_block_new(arena, block_size); + sp_mem_arena_block_t* block = sp_mem_arena_block_new(arena, arena->block_size); + if (!block) { + sp_mem_allocator_free(mem, arena, sizeof(sp_mem_arena_t)); + return SP_NULLPTR; + } arena->head = block; arena->current = block; - arena->block_size = block_size; return arena; } @@ -8226,16 +8220,13 @@ void sp_mem_arena_destroy(sp_mem_arena_t* arena) { sp_mem_arena_block_t* block = arena->head; while (block) { sp_mem_arena_block_t* next = block->next; - if (block->buffer) { - sp_mem_allocator_free(arena->allocator, block->buffer); - } - sp_mem_allocator_free(arena->allocator, block); + sp_mem_allocator_free(arena->allocator, block, sizeof(sp_mem_arena_block_t) + block->capacity); block = next; } arena->head = SP_NULLPTR; arena->current = SP_NULLPTR; - sp_mem_allocator_free(arena->allocator, arena); + sp_mem_allocator_free(arena->allocator, arena, sizeof(sp_mem_arena_t)); } u64 sp_mem_arena_capacity(sp_mem_arena_t* arena) { @@ -8255,94 +8246,101 @@ u64 sp_mem_arena_bytes_used(sp_mem_arena_t* arena) { return total; } -sp_mem_arena_header_t* sp_mem_arena_get_header(void* ptr) { - return (sp_mem_arena_header_t*)((u8*)ptr - sizeof(sp_mem_arena_header_t)); +u64 sp_mem_arena_block_align(sp_mem_arena_block_t* block, u8 alignment) { + u8* buffer = sp_mem_arena_block_buffer(block); + u8* ptr = (u8*)sp_align_up(buffer + block->bytes_used, alignment); + return (u64)(ptr - buffer); } -void* sp_mem_arena_get_ptr(sp_mem_arena_header_t* header) { - return (void*)(header + 1); +bool sp_mem_arena_block_fits(sp_mem_arena_block_t* block, u64 offset, u64 size) { + return offset <= block->capacity && size <= block->capacity - offset; } -void* sp_mem_arena_align_block(sp_mem_arena_block_t* block, u8 alignment) { - block->bytes_used = sp_align_offset(block->bytes_used, alignment); - return block->buffer + block->bytes_used; -} - -sp_mem_arena_block_t* sp_mem_arena_get_block(sp_mem_arena_t* arena, u64 alloc_size) { +sp_mem_arena_block_t* sp_mem_arena_get_block(sp_mem_arena_t* arena, u64 size) { sp_mem_arena_block_t* block = arena->current; - u64 offset = sp_align_offset(block->bytes_used, arena->alignment); - - if (offset + alloc_size <= block->capacity) { + u64 offset = sp_mem_arena_block_align(block, arena->alignment); + if (sp_mem_arena_block_fits(block, offset, size)) { block->bytes_used = offset; return block; } - u64 new_capacity = sp_max(arena->block_size, alloc_size); - - if (block->next && block->next->capacity >= alloc_size) { - block->next->bytes_used = 0; - block = block->next; - } - else { - sp_mem_arena_block_t* new_block = sp_mem_arena_block_new(arena, new_capacity); - new_block->next = block->next; - block->next = new_block; - block = new_block; + if (block->next) { + sp_mem_arena_block_t* next = block->next; + next->bytes_used = 0; + u64 next_offset = sp_mem_arena_block_align(next, arena->alignment); + if (sp_mem_arena_block_fits(next, next_offset, size)) { + next->bytes_used = next_offset; + arena->current = next; + return next; + } } - arena->current = block; - return block; + if (arena->block_size < SP_MEM_ARENA_MAX_BLOCK_SIZE) { + arena->block_size = sp_min(arena->block_size * 2, (u64)SP_MEM_ARENA_MAX_BLOCK_SIZE); + } + u64 required = sizeof(sp_mem_arena_block_t) + arena->alignment + size; + sp_mem_arena_block_t* new_block = sp_mem_arena_block_new(arena, sp_max(arena->block_size, required)); + if (!new_block) return SP_NULLPTR; + new_block->next = block->next; + block->next = new_block; + new_block->bytes_used = sp_mem_arena_block_align(new_block, arena->alignment); + arena->current = new_block; + return new_block; } -void* sp_mem_arena_alloc_with_header(sp_mem_arena_t* arena, u64 size) { - u64 total = sizeof(sp_mem_arena_header_t) + size; +void* sp_mem_arena_alloc_size(sp_mem_arena_t* arena, u64 size) { + if (size > ((u64)-1) - SP_MEM_ARENA_MAX_BLOCK_SIZE) return SP_NULLPTR; - sp_mem_arena_block_t* block = sp_mem_arena_get_block(arena, total); - sp_mem_arena_header_t* header = (sp_mem_arena_header_t*)sp_mem_arena_align_block(block, arena->alignment); - header->size = size; + sp_mem_arena_block_t* block = sp_mem_arena_get_block(arena, size); + if (!block) return SP_NULLPTR; - void* ptr = sp_mem_arena_get_ptr(header); + void* ptr = sp_mem_arena_block_buffer(block) + block->bytes_used; + block->bytes_used += size; sp_mem_zero(ptr, size); - block->bytes_used += total; - return ptr; } -void* sp_mem_arena_alloc_no_header(sp_mem_arena_t* arena, u64 size) { - sp_mem_arena_block_t* block = sp_mem_arena_get_block(arena, size); - void* ptr = sp_mem_arena_align_block(block, arena->alignment); - sp_mem_zero(ptr, size); - block->bytes_used += size; - - return ptr; +bool sp_mem_arena_is_top(sp_mem_arena_t* arena, void* ptr, u64 size) { + sp_mem_arena_block_t* block = arena->current; + u8* buffer = sp_mem_arena_block_buffer(block); + return (u8*)ptr >= buffer && (u8*)ptr + size == buffer + block->bytes_used; } -void* sp_mem_arena_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* old_memory) { +void* sp_mem_arena_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* old_memory, u64 old_size) { sp_mem_arena_t* arena = (sp_mem_arena_t*)user_data; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: { - switch (arena->mode) { - case SP_MEM_ARENA_MODE_DEFAULT: { - return sp_mem_arena_alloc_with_header(arena, size); - } - case SP_MEM_ARENA_MODE_NO_REALLOC: { - return sp_mem_arena_alloc_no_header(arena, size); - } - } - SP_UNREACHABLE_RETURN(SP_NULLPTR); + return sp_mem_arena_alloc_size(arena, size); } case SP_ALLOCATOR_MODE_RESIZE: { - if (arena->mode == SP_MEM_ARENA_MODE_NO_REALLOC) return SP_NULLPTR; + if (!old_memory) return sp_mem_arena_alloc_size(arena, size); - void* ptr = sp_mem_arena_alloc_with_header(arena, size); - if (old_memory) { - sp_mem_arena_header_t* header = sp_mem_arena_get_header(old_memory); - sp_mem_move(ptr, old_memory, sp_min(header->size, size)); + sp_mem_arena_block_t* block = arena->current; + if (sp_mem_arena_is_top(arena, old_memory, old_size)) { + if (size <= old_size) { + block->bytes_used -= old_size - size; + return old_memory; + } + u64 grow = size - old_size; + if (grow <= block->capacity - block->bytes_used) { + sp_mem_zero(sp_mem_arena_block_buffer(block) + block->bytes_used, grow); + block->bytes_used += grow; + return old_memory; + } } - return ptr; + + if (size <= old_size) return old_memory; + + void* fresh = sp_mem_arena_alloc_size(arena, size); + if (!fresh) return SP_NULLPTR; + sp_mem_move(fresh, old_memory, old_size); + return fresh; } case SP_ALLOCATOR_MODE_FREE: { + if (old_memory && sp_mem_arena_is_top(arena, old_memory, old_size)) { + arena->current->bytes_used -= old_size; + } return SP_NULLPTR; } } @@ -8351,15 +8349,15 @@ void* sp_mem_arena_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, } void* sp_mem_arena_alloc(sp_mem_arena_t* arena, u64 size) { - return sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR); + return sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR, 0); } -void* sp_mem_arena_realloc(sp_mem_arena_t* arena, void* ptr, u64 size) { - return sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_RESIZE, size, ptr); +void* sp_mem_arena_realloc(sp_mem_arena_t* arena, void* ptr, u64 old_size, u64 size) { + return sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_RESIZE, size, ptr, old_size); } -void sp_mem_arena_free(sp_mem_arena_t* arena, void* ptr) { - sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_FREE, 0, ptr); +void sp_mem_arena_free(sp_mem_arena_t* arena, void* ptr, u64 size) { + sp_mem_arena_on_alloc(arena, SP_ALLOCATOR_MODE_FREE, 0, ptr, size); } sp_mem_fixed_t sp_mem_fixed(void* buffer, u64 capacity) { @@ -8390,21 +8388,42 @@ u64 sp_mem_fixed_bytes_used(sp_mem_fixed_t* fixed) { return fixed->bytes_used; } -void* sp_mem_fixed_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* old_memory) { - (void)old_memory; +void* sp_mem_fixed_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* old_memory, u64 old_size) { sp_mem_fixed_t* fixed = (sp_mem_fixed_t*)user_data; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: { u8* ptr = (u8*)sp_align_up(fixed->buffer + fixed->bytes_used, fixed->alignment); u64 offset = (u64)(ptr - fixed->buffer); - if (offset + size > fixed->capacity) return SP_NULLPTR; + if (offset > fixed->capacity || size > fixed->capacity - offset) return SP_NULLPTR; fixed->bytes_used = offset + size; sp_mem_zero(ptr, size); return ptr; } - case SP_ALLOCATOR_MODE_RESIZE: + case SP_ALLOCATOR_MODE_RESIZE: { + if (!old_memory) return sp_mem_fixed_on_alloc(user_data, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR, 0); + + bool is_top = (u8*)old_memory + old_size == fixed->buffer + fixed->bytes_used; + if (is_top) { + u64 offset = (u64)((u8*)old_memory - fixed->buffer); + if (size <= fixed->capacity - offset) { + if (size > old_size) sp_mem_zero((u8*)old_memory + old_size, size - old_size); + fixed->bytes_used = offset + size; + return old_memory; + } + } + + if (size <= old_size) return old_memory; + + void* fresh = sp_mem_fixed_on_alloc(user_data, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR, 0); + if (!fresh) return SP_NULLPTR; + sp_mem_move(fresh, old_memory, old_size); + return fresh; + } case SP_ALLOCATOR_MODE_FREE: { + if (old_memory && (u8*)old_memory + old_size == fixed->buffer + fixed->bytes_used) { + fixed->bytes_used -= old_size; + } return SP_NULLPTR; } } @@ -8489,34 +8508,26 @@ void sp_mem_zero(void* buffer, u64 buffer_size) { } void* sp_mem_os_alloc(u64 size) { - sp_mem_os_header_t* h = (sp_mem_os_header_t*)sp_sys_alloc(size + sizeof(sp_mem_os_header_t)); - if (!h) return SP_NULLPTR; - h->size = size; - return h + 1; + return sp_sys_alloc(size); } -void sp_mem_os_free(void* ptr) { +void sp_mem_os_free(void* ptr, u64 size) { if (!ptr) return; - sp_mem_os_header_t* h = sp_mem_os_get_header(ptr); - sp_sys_free(h, h->size + sizeof(sp_mem_os_header_t)); + sp_sys_free(ptr, size); } -void* sp_mem_os_realloc(void* ptr, u64 size) { +void* sp_mem_os_realloc(void* ptr, u64 old_size, u64 size) { if (!ptr) return sp_mem_os_alloc(size); if (!size) { - sp_mem_os_free(ptr); + sp_mem_os_free(ptr, old_size); return SP_NULLPTR; } - - sp_mem_os_header_t* header = sp_mem_os_get_header(ptr); - if (header->size >= size) { - return ptr; - } + if (size == old_size) return ptr; void* mem = sp_mem_os_alloc(size); if (!mem) return SP_NULLPTR; - sp_mem_copy(mem, ptr, header->size); - sp_mem_os_free(ptr); + sp_mem_copy(mem, ptr, sp_min(old_size, size)); + sp_mem_os_free(ptr, old_size); return mem; } @@ -8890,7 +8901,7 @@ sp_wide_str_t sp_wtf8_to_wtf16(sp_mem_t mem, sp_str_t wtf8) { return (sp_wide_str_t) { .data = buf, .len = n }; error: - sp_free(mem, buf); + sp_free(mem, buf, (wtf8.len + 1) * sizeof(u16)); return result; } @@ -10314,7 +10325,7 @@ void sp_os_env_it_next(sp_os_env_it_t* it) { if (state->cursor[0] != L'\0') { sp_win32_env_it_set_current(it); } else { - sp_mem_os_free(state); + sp_mem_os_free(state, sizeof(sp_win32_env_it_t)); *it = sp_zero_s(sp_os_env_it_t); } } @@ -10355,7 +10366,7 @@ sp_os_env_it_t sp_os_env_it_begin() { os->it = sp_str_ht_it_init(os->env.vars); if (!sp_str_ht_it_valid(os->env.vars, os->it)) { - sp_mem_os_free(os); + sp_mem_os_free(os, sizeof(sp_linux_env_it_t)); return sp_zero_s(sp_os_env_it_t); } @@ -10379,7 +10390,7 @@ void sp_os_env_it_next(sp_os_env_it_t* it) { } else { it->key = sp_zero_s(sp_str_t); it->value = sp_zero_s(sp_str_t); - sp_mem_os_free(state); + sp_mem_os_free(state, sizeof(sp_linux_env_it_t)); it->os = SP_NULLPTR; } } @@ -10474,7 +10485,7 @@ void sp_sys_env(const c8** env, u32* len) { void sp_env_init(sp_mem_t mem, sp_env_t* env) { *env = sp_zero_s(sp_env_t); env->mem = mem; - env->arena = sp_mem_arena_new_ex(mem, 4096, SP_MEM_ARENA_MODE_NO_REALLOC, SP_MEM_ALIGNMENT); + env->arena = sp_mem_arena_new_ex(mem, 4096, SP_MEM_ALIGNMENT); sp_str_ht_init(mem, env->vars); } @@ -11208,13 +11219,13 @@ void sp_thread_init(sp_thread_t* thread, sp_thread_fn_t fn, void* userdata) { *thread = CreateThread(SP_NULLPTR, 0, sp_win32_thread_launch, launch, 0, SP_NULLPTR); if (!*thread) { sp_semaphore_destroy(&launch->semaphore); - sp_mem_os_free(launch); + sp_mem_os_free(launch, sizeof(sp_thread_launch_t)); return; } sp_semaphore_wait(&launch->semaphore); sp_semaphore_destroy(&launch->semaphore); - sp_mem_os_free(launch); + sp_mem_os_free(launch, sizeof(sp_thread_launch_t)); } s32 sp_thread_launch(void* args) { @@ -11861,8 +11872,8 @@ sp_ps_output_t sp_ps_output(sp_ps_t* ps) { } } - result.out = sp_io_dyn_mem_writer_as_str(&write.out); - result.err = sp_io_dyn_mem_writer_as_str(&write.err); + result.out = sp_io_dyn_mem_writer_take_str(&write.out); + result.err = sp_io_dyn_mem_writer_take_str(&write.err); result.status = sp_ps_wait(ps); return result; } @@ -11876,14 +11887,14 @@ bool sp_ps_kill(sp_ps_t* ps) { void sp_ps_free(sp_ps_t* ps) { if (!ps || !ps->os) return; - sp_free(ps->mem, ps->os); + sp_free(ps->mem, ps->os, sizeof(*ps->os)); ps->os = SP_NULLPTR; } void sp_ps_output_free(sp_mem_t mem, sp_ps_output_t* output) { if (!output) return; - sp_free(mem, (void*)output->out.data); - sp_free(mem, (void*)output->err.data); + sp_free(mem, (void*)output->out.data, output->out.len); + sp_free(mem, (void*)output->err.data, output->err.len); *output = sp_zero_s(sp_ps_output_t); } @@ -12493,8 +12504,8 @@ sp_ps_output_t sp_ps_output(sp_ps_t* ps) { ps->os->pid = SP_NULLPTR; } - result.out = sp_io_dyn_mem_writer_as_str(&out); - result.err = sp_io_dyn_mem_writer_as_str(&err); + result.out = sp_io_dyn_mem_writer_take_str(&out); + result.err = sp_io_dyn_mem_writer_take_str(&err); result.status = (sp_ps_status_t) { .state = SP_PS_STATE_DONE, .exit_code = process_done ? (s32)exit_code : -1, @@ -12523,14 +12534,14 @@ void sp_ps_free(sp_ps_t* ps) { CloseHandle(ps->os->pid); ps->os->pid = SP_NULLPTR; } - sp_free(ps->mem, ps->os); + sp_free(ps->mem, ps->os, sizeof(*ps->os)); ps->os = SP_NULLPTR; } void sp_ps_output_free(sp_mem_t mem, sp_ps_output_t* output) { if (!output) return; - sp_free(mem, (void*)output->out.data); - sp_free(mem, (void*)output->err.data); + sp_free(mem, (void*)output->out.data, output->out.len); + sp_free(mem, (void*)output->err.data, output->err.len); *output = sp_zero_s(sp_ps_output_t); } @@ -12793,12 +12804,12 @@ void sp_fmon_os_deinit(sp_fmon_t* monitor) { CloseHandle(info->overlapped.hEvent); } if (info->notify_information) { - sp_free(monitor->mem, info->notify_information); + sp_free(monitor->mem, info->notify_information, SP_FILE_MONITOR_BUFFER_SIZE); } } sp_da_free(os->dirs); sp_da_free(os->watch_files); - sp_free(monitor->mem, os); + sp_free(monitor->mem, os, sizeof(sp_fmon_os_t)); monitor->os = NULL; } @@ -13235,8 +13246,8 @@ void sp_fmon_os_init(sp_fmon_t* monitor) { os->queue = dispatch_queue_create("sp.fmon", DISPATCH_QUEUE_SERIAL); os->monitor = monitor; sp_mutex_init(&os->mutex, SP_MUTEX_PLAIN); - os->watch_arena = sp_mem_arena_new_ex(monitor->mem, SP_FMON_ARENA_SIZE, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); - os->event_arena = sp_mem_arena_new_ex(monitor->mem, SP_FMON_ARENA_SIZE, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + os->watch_arena = sp_mem_arena_new_ex(monitor->mem, SP_FMON_ARENA_SIZE, SP_MEM_ALIGNMENT); + os->event_arena = sp_mem_arena_new_ex(monitor->mem, SP_FMON_ARENA_SIZE, SP_MEM_ALIGNMENT); os->mem.watch = sp_mem_arena_as_allocator(os->watch_arena); os->mem.event = sp_mem_arena_as_allocator(os->event_arena); sp_da_init(monitor->mem, os->watch_paths); @@ -13258,7 +13269,7 @@ void sp_fmon_os_deinit(sp_fmon_t* monitor) { sp_mutex_destroy(&os->mutex); sp_mem_arena_destroy(os->watch_arena); sp_mem_arena_destroy(os->event_arena); - sp_free(monitor->mem, os); + sp_free(monitor->mem, os, sizeof(sp_fmon_os_t)); monitor->os = SP_NULLPTR; } @@ -14350,7 +14361,7 @@ SP_API s32 sp_app_run(sp_app_config_t config) { s32 rc = (app->mode == SP_APP_MODE_FREE) ? sp_app_run_free(app) : sp_app_run_locked(app); - sp_mem_os_free(app); + sp_mem_os_free(app, sizeof(sp_app_t)); return rc; } @@ -14368,16 +14379,12 @@ SP_API s32 sp_app_run(sp_app_config_t config) { -sp_mem_os_header_t* sp_mem_os_get_header(void* ptr) { - return ((sp_mem_os_header_t*)ptr) - 1; -} - -void* sp_mem_os_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +void* sp_mem_os_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { (void)user_data; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: return sp_mem_os_alloc(size); - case SP_ALLOCATOR_MODE_RESIZE: return sp_mem_os_realloc(ptr, size); - case SP_ALLOCATOR_MODE_FREE: sp_mem_os_free(ptr); return SP_NULLPTR; + case SP_ALLOCATOR_MODE_RESIZE: return sp_mem_os_realloc(ptr, old_size, size); + case SP_ALLOCATOR_MODE_FREE: sp_mem_os_free(ptr, old_size); return SP_NULLPTR; default: return SP_NULLPTR; } } @@ -14618,7 +14625,8 @@ void* sp_mem_heap_realloc(sp_mem_heap_t* heap, void* ptr, u64 size) { return fresh; } -void* sp_mem_heap_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +void* sp_mem_heap_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { + sp_unused(old_size); sp_mem_heap_t* heap = (sp_mem_heap_t*)user_data; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: return sp_mem_heap_alloc(heap, size); @@ -14639,12 +14647,12 @@ void* sp_alloc(sp_mem_t allocator, u64 size) { return sp_mem_allocator_alloc(allocator, size); } -void* sp_realloc(sp_mem_t allocator, void* memory, u64 size) { - return sp_mem_allocator_realloc(allocator, memory, size); +void* sp_realloc(sp_mem_t allocator, void* memory, u64 old_size, u64 size) { + return sp_mem_allocator_realloc(allocator, memory, old_size, size); } -void sp_free(sp_mem_t allocator, void* memory) { - sp_mem_allocator_free(allocator, memory); +void sp_free(sp_mem_t allocator, void* memory, u64 size) { + sp_mem_allocator_free(allocator, memory, size); } sp_err_t sp_io_mem_writer_write(sp_io_writer_t* writer, const void* ptr, u64 size, u64* bytes_written) { @@ -14723,7 +14731,7 @@ sp_err_t sp_io_dyn_mem_writer_write(sp_io_writer_t* writer, const void* ptr, u64 while (new_capacity < required) { new_capacity *= 2; } - w->storage.data = (u8*)sp_mem_allocator_realloc(w->allocator, w->storage.data, new_capacity); + w->storage.data = (u8*)sp_mem_allocator_realloc(w->allocator, w->storage.data, w->storage.capacity, new_capacity); w->storage.capacity = new_capacity; } @@ -14781,7 +14789,7 @@ sp_err_t sp_io_dyn_mem_writer_close(sp_io_dyn_mem_writer_t* w) { sp_io_flush(&w->base); if (w->storage.data) { - sp_mem_allocator_free(w->allocator, w->storage.data); + sp_mem_allocator_free(w->allocator, w->storage.data, w->storage.capacity); w->storage = sp_zero_s(sp_mem_buffer_t); } return SP_OK; @@ -14802,6 +14810,15 @@ sp_str_t sp_io_dyn_mem_writer_as_str(sp_io_dyn_mem_writer_t* w) { return sp_mem_buffer_as_str(&w->storage); } +sp_str_t sp_io_dyn_mem_writer_take_str(sp_io_dyn_mem_writer_t* w) { + sp_str_t str = sp_mem_buffer_as_str(&w->storage); + if (w->storage.data && w->storage.capacity > str.len) { + str.data = (c8*)sp_mem_allocator_realloc(w->allocator, w->storage.data, w->storage.capacity, str.len); + } + w->storage = sp_zero_s(sp_mem_buffer_t); + return str; +} + const c8* sp_io_dyn_mem_writer_as_cstr(sp_io_dyn_mem_writer_t* w) { return sp_mem_buffer_as_cstr(&w->storage); } @@ -15604,12 +15621,15 @@ sp_err_t sp_io_read_file(sp_mem_t mem, sp_str_t path, sp_str_t* content) { buffer = sp_alloc_n(mem, c8, size); sp_try_goto(sp_io_read(&reader.base, buffer, size, &bytes_read), err, cleanup); + if (bytes_read < size) { + buffer = (c8*)sp_realloc(mem, buffer, size, bytes_read); + } content->data = buffer; content->len = (u32)bytes_read; buffer = SP_NULLPTR; cleanup: - if (buffer) sp_mem_allocator_free(mem, buffer); + if (buffer) sp_mem_allocator_free(mem, buffer, size); sp_io_file_reader_close(&reader); return err; } diff --git a/sp/sp_asset.h b/sp/sp_asset.h index c840a76..08cef60 100644 --- a/sp/sp_asset.h +++ b/sp/sp_asset.h @@ -74,7 +74,7 @@ struct sp_asset_registry { }; void sp_asset_registry_init(sp_asset_registry_t* r, sp_mem_t mem, sp_asset_registry_config_t config); -void* sp_asset_registry_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old); +void* sp_asset_registry_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old, u64 old_size); void sp_asset_registry_shutdown(sp_asset_registry_t* r); sp_asset_t* sp_asset_registry_import(sp_asset_registry_t* r, sp_asset_kind_t k, sp_str_t name, void* user_data); sp_asset_t* sp_asset_registry_add(sp_asset_registry_t* r, sp_asset_kind_t k, sp_str_t name, void* data); @@ -92,10 +92,10 @@ s32 sp_asset_registry_thread_fn(void* user_data); #endif #if defined(SP_ASSET_IMPLEMENTATION) -void* sp_asset_registry_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old) { +void* sp_asset_registry_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* old, u64 old_size) { sp_asset_registry_t* r = (sp_asset_registry_t*)ud; sp_mutex_lock(&r->alloc_mutex); - void* result = sp_mem_arena_on_alloc(r->arena, mode, size, old); + void* result = sp_mem_arena_on_alloc(r->arena, mode, size, old, old_size); sp_mutex_unlock(&r->alloc_mutex); return result; } diff --git a/sp/sp_prompt.h b/sp/sp_prompt.h index ddfce79..68af15f 100644 --- a/sp/sp_prompt.h +++ b/sp/sp_prompt.h @@ -959,7 +959,7 @@ sp_prompt_ctx_t* sp_prompt_new(sp_mem_t mem) { sp_prompt_ctx_t* sp_prompt_begin(sp_mem_t mem) { sp_prompt_ctx_t* ctx = sp_prompt_new(mem); if (sp_prompt_begin_ex(ctx)) { - sp_free(mem, ctx); + sp_free(mem, ctx, sizeof(sp_prompt_ctx_t)); return SP_NULLPTR; } return ctx; @@ -1014,7 +1014,7 @@ void sp_prompt_ctx_init(sp_prompt_ctx_t* ctx, sp_mem_t mem, u32 cols, u32 rows) sp_da_init(ctx->mem, ctx->frames); sp_mutex_init(&ctx->channel.lock, SP_MUTEX_PLAIN); - ctx->channel.arena = sp_mem_arena_new_ex(mem, 4096, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + ctx->channel.arena = sp_mem_arena_new_ex(mem, 4096, SP_MEM_ALIGNMENT); // Write buffering is really important, because our rendering algorithm is extremely // naive. It's not much more than this: diff --git a/test/array.c b/test/array.c index c402122..103d230 100644 --- a/test/array.c +++ b/test/array.c @@ -150,7 +150,7 @@ UTEST_F(dyn_array, pointer_type) { } for (u64 i = 0; i < sp_da_size(arr); i++) { - sp_free(ut.mem, arr[i]); + sp_free(ut.mem, arr[i], sp_cstr_len(arr[i]) + 1); } sp_da_free(arr); diff --git a/test/bench/heap.c b/test/bench/heap.c index 7acf82f..798c7bf 100644 --- a/test/bench/heap.c +++ b/test/bench/heap.c @@ -105,14 +105,14 @@ static void bench_alloc_slot(const bench_workload_t* w, u32 slot) { } static void bench_free_slot(u32 slot) { - sp_free(state.mem, state.ptrs[slot]); + sp_free(state.mem, state.ptrs[slot], state.sizes[slot]); state.live_req -= state.sizes[slot]; state.ptrs[slot] = SP_NULLPTR; state.sizes[slot] = 0; } static void bench_realloc_slot(u32 slot, u64 size) { - state.ptrs[slot] = sp_realloc(state.mem, state.ptrs[slot], size); + state.ptrs[slot] = sp_realloc(state.mem, state.ptrs[slot], state.sizes[slot], size); SP_ASSERT(state.ptrs[slot]); bench_touch(state.ptrs[slot], size); state.live_req -= state.sizes[slot]; @@ -140,8 +140,9 @@ static bool bench_heap_sample(void* ctx, u64* used, u64* reserved) { } #if !defined(SP_FREESTANDING) -static void* bench_malloc_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +static void* bench_malloc_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { sp_unused(user_data); + sp_unused(old_size); switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: return malloc(size); case SP_ALLOCATOR_MODE_RESIZE: return realloc(ptr, size); @@ -189,10 +190,10 @@ typedef struct { static bench_os_counters_t bench_os_counters = sp_zero; static u64 bench_os_reservation(u64 size) { - return sp_align_offset(size + sizeof(sp_mem_os_header_t), 4096); + return sp_align_offset(size, 4096); } -static void* bench_os_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +static void* bench_os_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { bench_os_counters_t* counters = (bench_os_counters_t*)user_data; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: { @@ -205,25 +206,22 @@ static void* bench_os_on_alloc(void* user_data, sp_mem_alloc_mode_t mode, u64 si return p; } case SP_ALLOCATOR_MODE_RESIZE: { - if (!ptr) return bench_os_on_alloc(user_data, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR); - u64 old = sp_mem_os_get_header(ptr)->size; - void* p = sp_mem_os_realloc(ptr, size); + if (!ptr) return bench_os_on_alloc(user_data, SP_ALLOCATOR_MODE_ALLOC, size, SP_NULLPTR, 0); + void* p = sp_mem_os_realloc(ptr, old_size, size); if (p) { - u64 now = sp_mem_os_get_header(p)->size; - counters->used -= old; - counters->used += now; - counters->reserved -= bench_os_reservation(old); - counters->reserved += bench_os_reservation(now); + counters->used -= old_size; + counters->used += size; + counters->reserved -= bench_os_reservation(old_size); + counters->reserved += bench_os_reservation(size); counters->peak_reserved = sp_max(counters->peak_reserved, counters->reserved); } return p; } case SP_ALLOCATOR_MODE_FREE: { if (ptr) { - u64 old = sp_mem_os_get_header(ptr)->size; - counters->used -= old; - counters->reserved -= bench_os_reservation(old); - sp_mem_os_free(ptr); + counters->used -= old_size; + counters->reserved -= bench_os_reservation(old_size); + sp_mem_os_free(ptr, old_size); } return SP_NULLPTR; } diff --git a/test/bench/ubench.h b/test/bench/ubench.h index 956411b..41b4b29 100644 --- a/test/bench/ubench.h +++ b/test/bench/ubench.h @@ -551,7 +551,7 @@ void ubench_register_benchmark(sp_str_t name, ubench_body_t body, const ubench_f const ubench_size_t i = ubench_state.benchmarks_length++; ubench_state.benchmarks = sp_ptr_cast( ubench_benchmark_state_t*, - sp_realloc(ubench_state.mem, ubench_state.benchmarks, sizeof(ubench_benchmark_state_t) * ubench_state.benchmarks_length) + sp_realloc(ubench_state.mem, ubench_state.benchmarks, sizeof(ubench_benchmark_state_t) * i, sizeof(ubench_benchmark_state_t) * ubench_state.benchmarks_length) ); ubench_state.benchmarks[i].name = name; @@ -1190,7 +1190,7 @@ bench_store* bench_store_open(const c8 *path) { return s; error: - if (s) sp_mem_allocator_free(mem, s); + if (s) sp_mem_allocator_free(mem, s, sizeof(bench_store)); return SP_NULLPTR; } @@ -1200,7 +1200,7 @@ void bench_store_close(bench_store* s) { if (s->db) sqlite3_close(s->db); sp_mem_t mem = sp_mem_os_new(); - sp_mem_allocator_free(mem, s); + sp_mem_allocator_free(mem, s, sizeof(bench_store)); } s64 bench_store_begin_run(bench_store* s, const bench_machine_info* mi, const bench_run_info* ri) { @@ -1777,6 +1777,7 @@ s32 ubench_main(s32 argc, const c8 *const argv[]) { ubench_size_t *, sp_realloc(ubench_state.mem, sp_ptr_cast(void *, failed_benchmarks), + sizeof(ubench_size_t) * failed_benchmark_index, sizeof(ubench_size_t) * failed_benchmarks_length)); failed_benchmarks[failed_benchmark_index] = index; failed++; @@ -1857,8 +1858,8 @@ s32 ubench_main(s32 argc, const c8 *const argv[]) { } cleanup: - sp_free(ubench_state.mem, sp_ptr_cast(void *, failed_benchmarks)); - sp_free(ubench_state.mem, sp_ptr_cast(void *, ubench_state.benchmarks)); + sp_free(ubench_state.mem, sp_ptr_cast(void *, failed_benchmarks), sizeof(ubench_size_t) * failed_benchmarks_length); + sp_free(ubench_state.mem, sp_ptr_cast(void *, ubench_state.benchmarks), sizeof(ubench_benchmark_state_t) * ubench_state.benchmarks_length); #if defined(UBENCH_ENABLE_PERF_COUNTERS) && defined(SP_LINUX) ubench_perf_close(&perf); diff --git a/test/ht.c b/test/ht.c index 262bbdc..8b78f71 100644 --- a/test/ht.c +++ b/test/ht.c @@ -603,7 +603,7 @@ UTEST_F(siphash, collision_resistance) { EXPECT_EQ(collisions, 0); - sp_free(ut.mem, hashes); + sp_free(ut.mem, hashes, count * sizeof(u64)); } UTEST_F(sp_ht, hash_table_with_dyn_array_values) { diff --git a/test/leak.c b/test/leak.c index 38a74ae..06bfc8e 100644 --- a/test/leak.c +++ b/test/leak.c @@ -38,7 +38,7 @@ UTEST(tracking, alloc_free_balance) { EXPECT_EQ(t.live_count, 1u); EXPECT_EQ(t.live_bytes, 64u); - sp_free(mem, p); + sp_free(mem, p, 64); EXPECT_EQ(t.live_count, 0u); EXPECT_EQ(t.live_bytes, 0u); EXPECT_EQ(t.double_frees, 0u); @@ -55,7 +55,7 @@ UTEST(tracking, detects_leak) { sp_alloc(mem, 16); sp_alloc(mem, 32); void* freed = sp_alloc(mem, 8); - sp_free(mem, freed); + sp_free(mem, freed, 8); EXPECT_EQ(t.live_count, 2u); EXPECT_EQ(t.live_bytes, 48u); @@ -69,9 +69,9 @@ UTEST(tracking, detects_double_free) { sp_mem_t mem = sp_mem_tracking_as_allocator(&t); void* p = sp_alloc(mem, 64); - sp_free(mem, p); - sp_free(mem, p); - sp_free(mem, p); + sp_free(mem, p, 64); + sp_free(mem, p, 64); + sp_free(mem, p, 64); EXPECT_EQ(t.double_frees, 2u); EXPECT_EQ(t.live_count, 0u); @@ -90,7 +90,7 @@ UTEST(tracking, detects_wild_free) { // large enough for the back-step, and the bytes there won't match either // sentinel (we zero-init the buffer). static u8 buf[256] = {0}; - sp_free(mem, &buf[200]); + sp_free(mem, &buf[200], 8); EXPECT_EQ(t.wild_frees, 1u); EXPECT_EQ(t.double_frees, 0u); @@ -104,7 +104,7 @@ UTEST(tracking, free_null_is_noop) { sp_mem_tracking_init(&t); sp_mem_t mem = sp_mem_tracking_as_allocator(&t); - sp_free(mem, SP_NULLPTR); + sp_free(mem, SP_NULLPTR, 0); EXPECT_EQ(t.double_frees, 0u); EXPECT_EQ(t.wild_frees, 0u); @@ -121,14 +121,14 @@ UTEST(tracking, realloc_grows_and_preserves) { u8* p = sp_alloc_n(mem, u8, 4); sp_for(i, 4) p[i] = (u8)(i + 1); - u8* g = sp_void_cast(g, sp_realloc(mem, p, 64)); + u8* g = sp_void_cast(g, sp_realloc(mem, p, 4, 64)); EXPECT_NE(g, SP_NULLPTR); sp_for(i, 4) EXPECT_EQ(g[i], (u8)(i + 1)); EXPECT_EQ(t.live_count, 1u); EXPECT_EQ(t.live_bytes, 64u); - sp_free(mem, g); + sp_free(mem, g, 64); EXPECT_EQ(t.live_count, 0u); sp_mem_tracking_deinit(&t); @@ -139,12 +139,12 @@ UTEST(tracking, realloc_null_is_alloc) { sp_mem_tracking_init(&t); sp_mem_t mem = sp_mem_tracking_as_allocator(&t); - void* p = sp_realloc(mem, SP_NULLPTR, 32); + void* p = sp_realloc(mem, SP_NULLPTR, 0, 32); EXPECT_NE(p, SP_NULLPTR); EXPECT_EQ(t.live_count, 1u); EXPECT_EQ(t.live_bytes, 32u); - sp_free(mem, p); + sp_free(mem, p, 32); sp_mem_tracking_deinit(&t); } @@ -154,7 +154,7 @@ UTEST(tracking, realloc_zero_is_free) { sp_mem_t mem = sp_mem_tracking_as_allocator(&t); void* p = sp_alloc(mem, 32); - void* r = sp_realloc(mem, p, 0); + void* r = sp_realloc(mem, p, 32, 0); EXPECT_EQ(r, SP_NULLPTR); EXPECT_EQ(t.live_count, 0u); EXPECT_EQ(t.live_bytes, 0u); @@ -200,11 +200,11 @@ UTEST_F(leak, multiple_allocs_independent) { EXPECT_EQ(ut.tracker.live_count, 3u); EXPECT_EQ(ut.tracker.live_bytes, 56u); - sp_free(ut.mem, b); + sp_free(ut.mem, b, 16); EXPECT_EQ(ut.tracker.live_count, 2u); EXPECT_EQ(ut.tracker.live_bytes, 40u); - sp_free(ut.mem, a); - sp_free(ut.mem, c); + sp_free(ut.mem, a, 8); + sp_free(ut.mem, c, 32); EXPECT_EQ(ut.tracker.live_count, 0u); } diff --git a/test/mem/arena.c b/test/mem/arena.c index bb99e5c..39cffdc 100644 --- a/test/mem/arena.c +++ b/test/mem/arena.c @@ -29,11 +29,11 @@ UTEST_F(mem, arena_padding_mixed_sizes) { } UTEST_F(mem, arena_basic_alloc) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); EXPECT_EQ(sp_mem_arena_bytes_used(arena), 0u); - EXPECT_EQ(sp_mem_arena_capacity(arena), 256u); + EXPECT_EQ(sp_mem_arena_capacity(arena), 256u - sizeof(sp_mem_arena_block_t)); u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); EXPECT_ALIGNED(first); @@ -43,7 +43,7 @@ UTEST_F(mem, arena_basic_alloc) { } UTEST_F(mem, arena_allocations_are_zeroed) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 64)); @@ -53,8 +53,24 @@ UTEST_F(mem, arena_allocations_are_zeroed) { sp_mem_arena_destroy(arena); } +UTEST_F(mem, arena_packed_no_header_overhead) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); + EXPECT_ALIGNED(first); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 16u); + + u8* second = sp_void_cast(second, sp_mem_allocator_alloc(allocator, 32)); + EXPECT_ALIGNED(second); + EXPECT_EQ(second, first + 16); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 48u); + + sp_mem_arena_destroy(arena); +} + UTEST_F(mem, arena_pop_resets_bytes_used) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); sp_mem_arena_marker_t marker = sp_mem_arena_mark(arena); @@ -70,7 +86,7 @@ UTEST_F(mem, arena_pop_resets_bytes_used) { } UTEST_F(mem, arena_block_chaining) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 32)); @@ -89,13 +105,13 @@ UTEST_F(mem, arena_block_chaining) { EXPECT_EQ(b[0], 0xBB); EXPECT_EQ(c[0], 0xCC); - EXPECT_GT(sp_mem_arena_capacity(arena), 64u); + EXPECT_GT(sp_mem_arena_capacity(arena), 64u - sizeof(sp_mem_arena_block_t)); sp_mem_arena_destroy(arena); } UTEST_F(mem, arena_pop_across_blocks) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); sp_mem_arena_marker_t marker = sp_mem_arena_mark(arena); @@ -118,15 +134,36 @@ UTEST_F(mem, arena_pop_across_blocks) { sp_mem_arena_destroy(arena); } -UTEST_F(mem, arena_realloc_copies_data) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); +UTEST_F(mem, arena_realloc_extends_top_in_place) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); + sp_mem_fill_u8(first, 16, 0xAA); + + u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 16, 32)); + + EXPECT_EQ(resized, first); + EXPECT_EQ(resized[0], 0xAA); + EXPECT_EQ(resized[15], 0xAA); + EXPECT_EQ(resized[16], 0x00); + EXPECT_EQ(resized[31], 0x00); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 32u); + + sp_mem_arena_destroy(arena); +} + +UTEST_F(mem, arena_realloc_copies_when_not_top) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); sp_mem_fill_u8(first, 16, 0xAA); + sp_mem_allocator_alloc(allocator, 16); - u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 32)); + u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 16, 32)); + EXPECT_NE(resized, first); EXPECT_EQ(resized[0], 0xAA); EXPECT_EQ(resized[15], 0xAA); EXPECT_EQ(resized[16], 0x00); @@ -135,8 +172,40 @@ UTEST_F(mem, arena_realloc_copies_data) { sp_mem_arena_destroy(arena); } +UTEST_F(mem, arena_realloc_shrink_returns_same_pointer) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 32)); + sp_mem_fill_u8(first, 32, 0xAA); + + u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 32, 16)); + + EXPECT_EQ(resized, first); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 16u); + + sp_mem_arena_destroy(arena); +} + +UTEST_F(mem, arena_free_reclaims_top) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ALIGNMENT); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 32)); + u8* second = sp_void_cast(second, sp_mem_allocator_alloc(allocator, 32)); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 64u); + + sp_mem_allocator_free(allocator, first, 32); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 64u); + + sp_mem_allocator_free(allocator, second, 32); + EXPECT_EQ(sp_mem_arena_bytes_used(arena), 32u); + + sp_mem_arena_destroy(arena); +} + UTEST_F(mem, arena_clear_resets_all_blocks) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); sp_mem_allocator_alloc(allocator, 32); @@ -153,7 +222,7 @@ UTEST_F(mem, arena_clear_resets_all_blocks) { } UTEST_F(mem, arena_block_reuse_after_pop) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); sp_mem_arena_marker_t marker = sp_mem_arena_mark(arena); @@ -175,124 +244,66 @@ UTEST_F(mem, arena_block_reuse_after_pop) { sp_mem_arena_destroy(arena); } -UTEST_F(mem, arena_reuse_logic_check) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); +UTEST_F(mem, arena_block_reuse_after_clear) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); sp_mem_allocator_alloc(allocator, 40); - sp_mem_allocator_alloc(allocator, 40); u64 cap_initial = sp_mem_arena_capacity(arena); - EXPECT_EQ(cap_initial, 128u); sp_mem_arena_clear(arena); sp_mem_allocator_alloc(allocator, 40); - sp_mem_allocator_alloc(allocator, 40); u64 cap_after = sp_mem_arena_capacity(arena); - EXPECT_EQ(cap_after, 128u); + EXPECT_EQ(cap_after, cap_initial); sp_mem_arena_destroy(arena); } -UTEST_F(mem, arena_wrappers) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_DEFAULT, SP_MEM_ALIGNMENT); - EXPECT_NE(sp_mem_arena_alloc(arena, 8), SP_NULLPTR); - void* ptr = sp_mem_arena_alloc(arena, 8); - EXPECT_NE(sp_mem_arena_realloc(arena, ptr, 72), SP_NULLPTR); - sp_mem_arena_free(arena, ptr); -} - -UTEST_F(mem, arena_no_realloc_basic) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 0); +UTEST_F(mem, arena_block_size_grows_geometrically) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); - EXPECT_EQ(sp_mem_arena_bytes_used(arena), 0u); + sp_for(it, 64) { + sp_mem_allocator_alloc(allocator, 32); + } - u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); - EXPECT_ALIGNED(first); - EXPECT_EQ(sp_mem_arena_bytes_used(arena), 16u); + u32 num_blocks = 0; + for (sp_mem_arena_block_t* block = arena->head; block; block = block->next) { + num_blocks++; + } - u8* second = sp_void_cast(second, sp_mem_allocator_alloc(allocator, 32)); - EXPECT_ALIGNED(second); - EXPECT_EQ(sp_mem_arena_bytes_used(arena), 48u); + EXPECT_LT(num_blocks, 16u); + EXPECT_GE(sp_mem_arena_capacity(arena), 64u * 32u); sp_mem_arena_destroy(arena); } -UTEST_F(mem, arena_no_realloc_no_header_overhead) { - sp_mem_arena_t* no_realloc = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 0); - sp_mem_arena_t* normal = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_DEFAULT, 0); - - sp_mem_arena_alloc(no_realloc, 16); - sp_mem_arena_alloc(normal, 16); - - u64 no_realloc_used = sp_mem_arena_bytes_used(no_realloc); - u64 normal_used = sp_mem_arena_bytes_used(normal); - - EXPECT_LT(no_realloc_used, normal_used); - - sp_mem_arena_destroy(no_realloc); - sp_mem_arena_destroy(normal); -} - -UTEST_F(mem, arena_no_realloc_allocations_zeroed) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 0); - sp_mem_t allocator = sp_mem_arena_as_allocator(arena); - - u8* buf = sp_void_cast(buf, sp_mem_allocator_alloc(allocator, 64)); - EXPECT_EQ(buf[0], 0x00); - EXPECT_EQ(buf[63], 0x00); - - sp_mem_arena_destroy(arena); -} - -UTEST_F(mem, arena_no_realloc_block_chaining) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_NO_REALLOC, 0); - sp_mem_t allocator = sp_mem_arena_as_allocator(arena); - - u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 32)); - u8* b = sp_void_cast(b, sp_mem_allocator_alloc(allocator, 32)); - u8* c = sp_void_cast(c, sp_mem_allocator_alloc(allocator, 32)); - - EXPECT_ALIGNED(a); - EXPECT_ALIGNED(b); - EXPECT_ALIGNED(c); - - sp_mem_fill_u8(a, 32, 0xAA); - sp_mem_fill_u8(b, 32, 0xBB); - sp_mem_fill_u8(c, 32, 0xCC); - - EXPECT_EQ(a[0], 0xAA); - EXPECT_EQ(b[0], 0xBB); - EXPECT_EQ(c[0], 0xCC); - - EXPECT_GT(sp_mem_arena_capacity(arena), 64u); - +UTEST_F(mem, arena_wrappers) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); + EXPECT_NE(sp_mem_arena_alloc(arena, 8), SP_NULLPTR); + void* ptr = sp_mem_arena_alloc(arena, 8); + EXPECT_NE(sp_mem_arena_realloc(arena, ptr, 8, 72), SP_NULLPTR); + sp_mem_arena_free(arena, ptr, 8); sp_mem_arena_destroy(arena); } -UTEST_F(mem, arena_no_realloc_mark_pop) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 0); - sp_mem_t allocator = sp_mem_arena_as_allocator(arena); - - sp_mem_arena_marker_t marker = sp_mem_arena_mark(arena); - - sp_mem_allocator_alloc(allocator, 64); - EXPECT_EQ(sp_mem_arena_bytes_used(arena), 64u); +UTEST_F(mem, arena_huge_alloc_returns_null) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ALIGNMENT); - sp_mem_arena_pop(marker); + EXPECT_EQ(sp_mem_arena_alloc(arena, (u64)-8), SP_NULLPTR); EXPECT_EQ(sp_mem_arena_bytes_used(arena), 0u); sp_mem_arena_destroy(arena); } UTEST_F(mem, arena_unaligned_basic) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 1); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 1); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); EXPECT_EQ(sp_mem_arena_bytes_used(arena), 0u); @@ -308,7 +319,7 @@ UTEST_F(mem, arena_unaligned_basic) { } UTEST_F(mem, arena_unaligned_no_padding) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 1); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 1); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 3)); @@ -323,7 +334,7 @@ UTEST_F(mem, arena_unaligned_no_padding) { } UTEST_F(mem, arena_unaligned_allocations_zeroed) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 1); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 1); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* buf = sp_void_cast(buf, sp_mem_allocator_alloc(allocator, 64)); @@ -334,7 +345,7 @@ UTEST_F(mem, arena_unaligned_allocations_zeroed) { } UTEST_F(mem, arena_unaligned_block_chaining) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, SP_MEM_ARENA_MODE_NO_REALLOC, 1); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 64, 1); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 60)); @@ -346,13 +357,13 @@ UTEST_F(mem, arena_unaligned_block_chaining) { EXPECT_EQ(a[0], 0xAA); EXPECT_EQ(b[0], 0xBB); - EXPECT_GT(sp_mem_arena_capacity(arena), 64u); + EXPECT_GT(sp_mem_arena_capacity(arena), 64u - sizeof(sp_mem_arena_block_t)); sp_mem_arena_destroy(arena); } UTEST_F(mem, arena_custom_alignment_4) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 4); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 4); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 1)); @@ -370,7 +381,7 @@ UTEST_F(mem, arena_custom_alignment_4) { } UTEST_F(mem, arena_custom_alignment_8) { - sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, SP_MEM_ARENA_MODE_NO_REALLOC, 8); + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 8); sp_mem_t allocator = sp_mem_arena_as_allocator(arena); u8* a = sp_void_cast(a, sp_mem_allocator_alloc(allocator, 3)); @@ -383,3 +394,29 @@ UTEST_F(mem, arena_custom_alignment_8) { sp_mem_arena_destroy(arena); } + +UTEST_F(mem, arena_custom_alignment_64) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 4096, 64); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + sp_for(it, 8) { + u8* p = sp_void_cast(p, sp_mem_allocator_alloc(allocator, 24)); + EXPECT_EQ((uintptr_t)p % 64, 0u); + } + + sp_mem_arena_destroy(arena); +} + +UTEST_F(mem, arena_custom_alignment_64_across_blocks) { + sp_mem_arena_t* arena = sp_mem_arena_new_ex(sp_mem_os_new(), 256, 64); + sp_mem_t allocator = sp_mem_arena_as_allocator(arena); + + sp_for(it, 8) { + u8* p = sp_void_cast(p, sp_mem_allocator_alloc(allocator, 100)); + EXPECT_EQ((uintptr_t)p % 64, 0u); + } + + EXPECT_GT(sp_mem_arena_capacity(arena), 256u); + + sp_mem_arena_destroy(arena); +} diff --git a/test/mem/builtin.c b/test/mem/builtin.c index a18e276..16a3384 100644 --- a/test/mem/builtin.c +++ b/test/mem/builtin.c @@ -341,9 +341,10 @@ UTEST_F(mem, zero_large) { run_mem_zero_test(utest_result, (mem_zero_test_t){ .buffer_size = 400 }); } -static void* mock_alloc_record_size(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +static void* mock_alloc_record_size(void* user_data, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { (void)mode; (void)ptr; + (void)old_size; *(u64*)user_data = size; return SP_NULLPTR; } @@ -361,15 +362,14 @@ UTEST_F(mem, alloc_preserves_u64_size) { EXPECT_EQ(recorded_size, requested); } -UTEST_F(mem, libc_metadata_stores_u64_size) { - sp_mem_t libc = sp_mem_os_new(); +UTEST_F(mem, os_alloc_roundtrip) { + sp_mem_t os = sp_mem_os_new(); u64 size = 64; - void* ptr = sp_mem_allocator_alloc(libc, size); + u8* ptr = sp_void_cast(ptr, sp_mem_allocator_alloc(os, size)); ASSERT_TRUE(ptr); + EXPECT_EQ(ptr[0], 0x00); + EXPECT_EQ(ptr[63], 0x00); - sp_mem_os_header_t* meta = sp_mem_os_get_header(ptr); - EXPECT_EQ(meta->size, size); - - sp_mem_allocator_free(libc, ptr); + sp_mem_allocator_free(os, ptr, size); } diff --git a/test/mem/fixed.c b/test/mem/fixed.c index f84565c..faf0d9b 100644 --- a/test/mem/fixed.c +++ b/test/mem/fixed.c @@ -123,17 +123,20 @@ UTEST_F(mem, fixed_overflow_returns_null) { EXPECT_EQ(overflow, SP_NULLPTR); } -UTEST_F(mem, fixed_free_is_noop) { +UTEST_F(mem, fixed_free_reclaims_top) { u8 storage [256]; sp_mem_fixed_t fixed = sp_mem_fixed(storage, sizeof(storage)); sp_mem_t allocator = sp_mem_fixed_as_allocator(&fixed); u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 32)); + u8* second = sp_void_cast(second, sp_mem_allocator_alloc(allocator, 32)); u64 used_before = sp_mem_fixed_bytes_used(&fixed); - sp_mem_allocator_free(allocator, first); - + sp_mem_allocator_free(allocator, first, 32); EXPECT_EQ(sp_mem_fixed_bytes_used(&fixed), used_before); + + sp_mem_allocator_free(allocator, second, 32); + EXPECT_LT(sp_mem_fixed_bytes_used(&fixed), used_before); } UTEST_F(mem, fixed_unaligned_basic) { @@ -207,12 +210,42 @@ UTEST_F(mem, fixed_unaligned_base_returns_aligned_ptrs) { EXPECT_GE((uintptr_t)b, (uintptr_t)(a + 8)); } -UTEST_F(mem, fixed_resize_returns_null) { +UTEST_F(mem, fixed_resize_extends_top_in_place) { + SP_ALIGNED u8 storage [256]; + sp_mem_fixed_t fixed = sp_mem_fixed(storage, sizeof(storage)); + sp_mem_t allocator = sp_mem_fixed_as_allocator(&fixed); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); + sp_mem_fill_u8(first, 16, 0xAA); + u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 16, 32)); + EXPECT_EQ(resized, first); + EXPECT_EQ(resized[15], 0xAA); + EXPECT_EQ(resized[16], 0x00); + EXPECT_EQ(sp_mem_fixed_bytes_used(&fixed), 32u); +} + +UTEST_F(mem, fixed_resize_copies_when_not_top) { u8 storage [256]; sp_mem_fixed_t fixed = sp_mem_fixed(storage, sizeof(storage)); sp_mem_t allocator = sp_mem_fixed_as_allocator(&fixed); u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); - void* resized = sp_mem_allocator_realloc(allocator, first, 32); + sp_mem_fill_u8(first, 16, 0xAA); + sp_mem_allocator_alloc(allocator, 16); + + u8* resized = sp_void_cast(resized, sp_mem_allocator_realloc(allocator, first, 16, 32)); + EXPECT_NE(resized, first); + EXPECT_EQ(resized[0], 0xAA); + EXPECT_EQ(resized[15], 0xAA); + EXPECT_EQ(resized[16], 0x00); +} + +UTEST_F(mem, fixed_resize_fails_when_full) { + u8 storage [32]; + sp_mem_fixed_t fixed = sp_mem_fixed(storage, sizeof(storage)); + sp_mem_t allocator = sp_mem_fixed_as_allocator(&fixed); + + u8* first = sp_void_cast(first, sp_mem_allocator_alloc(allocator, 16)); + void* resized = sp_mem_allocator_realloc(allocator, first, 16, 256); EXPECT_EQ(resized, SP_NULLPTR); } diff --git a/test/mem/heap.c b/test/mem/heap.c index 735b05a..ab7f69d 100644 --- a/test/mem/heap.c +++ b/test/mem/heap.c @@ -688,9 +688,9 @@ UTEST_F(mem, heap_as_allocator_routes_through_sp_alloc) { EXPECT_NE(p, SP_NULLPTR); EXPECT_EQ((uintptr_t)p & (SP_MEM_ALIGNMENT - 1), 0u); - u8* q = sp_ptr_cast(u8*, sp_realloc(mem, p, 128)); + u8* q = sp_ptr_cast(u8*, sp_realloc(mem, p, 64, 128)); EXPECT_NE(q, SP_NULLPTR); - sp_free(mem, q); + sp_free(mem, q, 128); sp_mem_heap_destroy(heap); } diff --git a/test/prompt.c b/test/prompt.c index 2fb7ae9..d04f153 100644 --- a/test/prompt.c +++ b/test/prompt.c @@ -2375,7 +2375,7 @@ UTEST_F(prompt, prompt_end_frees_channel) { sp_prompt_send_status(ctx, "halfway"); sp_prompt_complete(ctx); sp_prompt_end(ctx); - sp_free(ut.mem.tracking, ctx); + sp_free(ut.mem.tracking, ctx, sizeof(sp_prompt_ctx_t)); } typedef struct { diff --git a/test/tools/stress.c b/test/tools/stress.c index 568de61..f8d13ff 100644 --- a/test/tools/stress.c +++ b/test/tools/stress.c @@ -320,14 +320,14 @@ UTEST(stress, sp_context) { u8* ptr = sp_alloc(s.mem, 16); sp_mem_fill_u8(ptr, 16, 0x11); - ptr = sp_mem_allocator_realloc(s.mem, ptr, 32); + ptr = sp_mem_allocator_realloc(s.mem, ptr, 16, 32); sp_for(it, 16) EXPECT_EQ(ptr[it], 0x11); sp_mem_fill_u8(ptr + 16, 16, 0x22); - ptr = sp_mem_allocator_realloc(s.mem, ptr, 8); + ptr = sp_mem_allocator_realloc(s.mem, ptr, 32, 8); sp_for(it, 8) ASSERT_EQ(ptr[it], 0x11); - ptr = sp_mem_allocator_realloc(s.mem, ptr, 8000); + ptr = sp_mem_allocator_realloc(s.mem, ptr, 8, 8000); sp_for(it, 8) ASSERT_EQ(ptr[it], 0x11); sp_mem_end_scratch(s); @@ -508,7 +508,7 @@ UTEST(stress, fmon) { // Cleanup sp_fmon_deinit(monitor); - sp_free(sp_mem_os_new(), monitor); + sp_free(sp_mem_os_new(), monitor, sizeof(sp_fmon_t)); sp_da_free(files); sp_da_free(dirs); sp_test_file_manager_cleanup(&file_manager); diff --git a/test/tools/test.h b/test/tools/test.h index 0561e0d..2a1686c 100644 --- a/test/tools/test.h +++ b/test/tools/test.h @@ -129,6 +129,7 @@ typedef struct sp_mem_tracking_t { u32 live_count; u32 double_frees; u32 wild_frees; + u32 bad_sizes; u32 next_id; } sp_mem_tracking_t; @@ -137,7 +138,7 @@ void sp_mem_tracking_init_ex(sp_mem_tracking_t* t, sp_mem_t backing); sp_mem_t sp_mem_tracking_as_allocator(sp_mem_tracking_t* t); void sp_mem_tracking_dump(sp_mem_tracking_t* t); void sp_mem_tracking_deinit(sp_mem_tracking_t* t); -void* sp_mem_tracking_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr); +void* sp_mem_tracking_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size); bool sp_mem_tracking_ok(sp_mem_tracking_t* mem); #endif @@ -308,12 +309,13 @@ static u32 sp_mem_tracking_peek_magic(void* ptr) { return magic; } -static void sp_mem_tracking_do_free(sp_mem_tracking_t* t, void* ptr) { +static void sp_mem_tracking_do_free(sp_mem_tracking_t* t, void* ptr, u64 size) { if (!ptr) return; u32 magic = sp_mem_tracking_peek_magic(ptr); if (magic == SP_MEM_TRACKING_LIVE_MAGIC) { sp_mem_tracking_node_t* node = sp_mem_tracking_header(ptr); + if (node->size != size) t->bad_sizes++; sp_mem_tracking_unlink(&t->live, node); node->magic = SP_MEM_TRACKING_FREED_MAGIC; t->live_count--; @@ -331,9 +333,9 @@ static void sp_mem_tracking_do_free(sp_mem_tracking_t* t, void* ptr) { } } -static void* sp_mem_tracking_do_realloc(sp_mem_tracking_t* t, void* old, u64 size) { +static void* sp_mem_tracking_do_realloc(sp_mem_tracking_t* t, void* old, u64 size, u64 old_size) { if (!old) return sp_mem_tracking_do_alloc(t, size); - if (!size) { sp_mem_tracking_do_free(t, old); return SP_NULLPTR; } + if (!size) { sp_mem_tracking_do_free(t, old, old_size); return SP_NULLPTR; } u32 magic = sp_mem_tracking_peek_magic(old); if (magic != SP_MEM_TRACKING_LIVE_MAGIC) { @@ -342,21 +344,22 @@ static void* sp_mem_tracking_do_realloc(sp_mem_tracking_t* t, void* old, u64 siz return SP_NULLPTR; } sp_mem_tracking_node_t* node = sp_mem_tracking_header(old); - if (node->size >= size) return old; + if (node->size != old_size) t->bad_sizes++; + if (node->size == size) return old; void* fresh = sp_mem_tracking_do_alloc(t, size); if (!fresh) return SP_NULLPTR; - sp_mem_copy(fresh, old, node->size); - sp_mem_tracking_do_free(t, old); + sp_mem_copy(fresh, old, sp_min(node->size, size)); + sp_mem_tracking_do_free(t, old, node->size); return fresh; } -void* sp_mem_tracking_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr) { +void* sp_mem_tracking_on_alloc(void* ud, sp_mem_alloc_mode_t mode, u64 size, void* ptr, u64 old_size) { sp_mem_tracking_t* t = (sp_mem_tracking_t*)ud; switch (mode) { case SP_ALLOCATOR_MODE_ALLOC: return sp_mem_tracking_do_alloc(t, size); - case SP_ALLOCATOR_MODE_RESIZE: return sp_mem_tracking_do_realloc(t, ptr, size); - case SP_ALLOCATOR_MODE_FREE: sp_mem_tracking_do_free(t, ptr); return SP_NULLPTR; + case SP_ALLOCATOR_MODE_RESIZE: return sp_mem_tracking_do_realloc(t, ptr, size, old_size); + case SP_ALLOCATOR_MODE_FREE: sp_mem_tracking_do_free(t, ptr, old_size); return SP_NULLPTR; default: return SP_NULLPTR; } } @@ -378,11 +381,12 @@ sp_mem_t sp_mem_tracking_as_allocator(sp_mem_tracking_t* t) { } void sp_mem_tracking_dump(sp_mem_tracking_t* t) { - sp_log("tracking: live={} bytes={} double_frees={} wild_frees={}", + sp_log("tracking: live={} bytes={} double_frees={} wild_frees={} bad_sizes={}", sp_fmt_uint(t->live_count), sp_fmt_uint(t->live_bytes), sp_fmt_uint(t->double_frees), - sp_fmt_uint(t->wild_frees)); + sp_fmt_uint(t->wild_frees), + sp_fmt_uint(t->bad_sizes)); for (sp_mem_tracking_node_t* n = t->live; n; n = n->next) { sp_log(" #{} size={}", sp_fmt_uint(n->id), sp_fmt_uint(n->size)); } @@ -392,13 +396,13 @@ void sp_mem_tracking_deinit(sp_mem_tracking_t* t) { sp_mem_tracking_node_t* n = t->live; while (n) { sp_mem_tracking_node_t* next = n->next; - sp_free(t->backing, n); + sp_free(t->backing, n, n->size + sizeof(sp_mem_tracking_node_t)); n = next; } n = t->freed; while (n) { sp_mem_tracking_node_t* next = n->next; - sp_free(t->backing, n); + sp_free(t->backing, n, n->size + sizeof(sp_mem_tracking_node_t)); n = next; } sp_mem_zero(t, sizeof(*t)); @@ -408,7 +412,8 @@ bool sp_mem_tracking_ok(sp_mem_tracking_t* mem) { bool ok = (mem->live_count == 0) && (mem->double_frees == 0) && - (mem->wild_frees == 0); + (mem->wild_frees == 0) && + (mem->bad_sizes == 0); if (!ok) sp_mem_tracking_dump(mem); return ok; } diff --git a/test/tools/utest.h b/test/tools/utest.h index 92e511d..fabf20d 100644 --- a/test/tools/utest.h +++ b/test/tools/utest.h @@ -91,10 +91,38 @@ #endif +typedef struct SP_ALIGNED utest_alloc_header_s { + u64 size; +} utest_alloc_header_t; + +static UTEST_INLINE void *utest_malloc(u64 size) { + utest_alloc_header_t *header = UTEST_PTR_CAST( + utest_alloc_header_t *, sp_mem_os_alloc(size + sizeof(utest_alloc_header_t))); + if (UTEST_NULL == header) { + return UTEST_NULL; + } + header->size = size; + return header + 1; +} + +static UTEST_INLINE void utest_free(void *const pointer) { + if (UTEST_NULL == pointer) { + return; + } + utest_alloc_header_t *header = UTEST_PTR_CAST(utest_alloc_header_t *, pointer) - 1; + sp_mem_os_free(header, header->size + sizeof(utest_alloc_header_t)); +} + static UTEST_INLINE void *utest_realloc(void *const pointer, u64 new_size) { - void *const new_pointer = sp_mem_os_realloc(pointer, new_size); + void *const new_pointer = utest_malloc(new_size); if (UTEST_NULL == new_pointer) { - sp_mem_os_free(pointer); + utest_free(pointer); + return UTEST_NULL; + } + if (UTEST_NULL != pointer) { + utest_alloc_header_t *header = UTEST_PTR_CAST(utest_alloc_header_t *, pointer) - 1; + sp_mem_copy(new_pointer, pointer, sp_min(header->size, new_size)); + utest_free(pointer); } return new_pointer; } @@ -580,9 +608,9 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { const u64 set_size = sizeof(set_part); \ const c8 test_part[] = #NAME; \ const u64 test_size = sizeof(test_part); \ - c8 *name = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(name_size)); \ - c8 *set = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(set_size)); \ - c8 *test = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(test_size)); \ + c8 *name = UTEST_PTR_CAST(c8 *, utest_malloc(name_size)); \ + c8 *set = UTEST_PTR_CAST(c8 *, utest_malloc(set_size)); \ + c8 *test = UTEST_PTR_CAST(c8 *, utest_malloc(test_size)); \ utest_state.tests = UTEST_PTR_CAST( \ struct utest_test_state_s *, \ utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ @@ -599,13 +627,13 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { sp_mem_copy(test, test_part, test_size); \ } else { \ if (utest_state.tests) { \ - sp_mem_os_free(utest_state.tests); \ + utest_free(utest_state.tests); \ utest_state.tests = UTEST_NULL; \ } \ if (name) { \ - sp_mem_os_free(name); \ - sp_mem_os_free(set); \ - sp_mem_os_free(test); \ + utest_free(name); \ + utest_free(set); \ + utest_free(test); \ } \ } \ } \ @@ -651,9 +679,9 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { const u64 set_size = sizeof(set_part); \ const c8 test_part[] = #NAME; \ const u64 test_size = sizeof(test_part); \ - c8 *name = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(name_size)); \ - c8 *set = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(set_size)); \ - c8 *test = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(test_size)); \ + c8 *name = UTEST_PTR_CAST(c8 *, utest_malloc(name_size)); \ + c8 *set = UTEST_PTR_CAST(c8 *, utest_malloc(set_size)); \ + c8 *test = UTEST_PTR_CAST(c8 *, utest_malloc(test_size)); \ \ utest_state.tests = UTEST_PTR_CAST( \ struct utest_test_state_s *, \ @@ -671,13 +699,13 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { sp_mem_copy(test, test_part, test_size); \ } else { \ if (utest_state.tests) { \ - sp_mem_os_free(utest_state.tests); \ + utest_free(utest_state.tests); \ utest_state.tests = UTEST_NULL; \ } \ if (name) { \ - sp_mem_os_free(name); \ - sp_mem_os_free(set); \ - sp_mem_os_free(test); \ + utest_free(name); \ + utest_free(set); \ + utest_free(test); \ } \ } \ } \ @@ -716,7 +744,7 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { sp_str_t fmtd = sp_fmt(sp_mem_get_scratch(), "{}/{}", sp_fmt_cstr(name_part), \ sp_fmt_uint(i)).value; \ u64 name_size = fmtd.len + 1; \ - c8 *name = UTEST_PTR_CAST(c8 *, sp_mem_os_alloc(name_size)); \ + c8 *name = UTEST_PTR_CAST(c8 *, utest_malloc(name_size)); \ utest_state.tests = UTEST_PTR_CAST( \ struct utest_test_state_s *, \ utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ @@ -730,11 +758,11 @@ static UTEST_INLINE int utest_strncmp(const c8 *a, const c8 *b, u32 n) { name[fmtd.len] = '\0'; \ } else { \ if (utest_state.tests) { \ - sp_mem_os_free(utest_state.tests); \ + utest_free(utest_state.tests); \ utest_state.tests = UTEST_NULL; \ } \ if (name) { \ - sp_mem_os_free(name); \ + utest_free(name); \ } \ } \ } \ @@ -1099,12 +1127,12 @@ s32 utest_main(s32 argc, const c8 **argv) { cleanup: for (index = 0; index < utest_state.tests_length; index++) { - sp_mem_os_free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); + utest_free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); } - sp_mem_os_free(UTEST_PTR_CAST(void *, skipped_testcases)); - sp_mem_os_free(UTEST_PTR_CAST(void *, failed_testcases)); - sp_mem_os_free(UTEST_PTR_CAST(void *, utest_state.tests)); + utest_free(UTEST_PTR_CAST(void *, skipped_testcases)); + utest_free(UTEST_PTR_CAST(void *, failed_testcases)); + utest_free(UTEST_PTR_CAST(void *, utest_state.tests)); if (utest_state.has_output) { sp_io_file_writer_close(&utest_state.output); diff --git a/tools/wip/sp_elf.h b/tools/wip/sp_elf.h index f4ed53c..9724c54 100644 --- a/tools/wip/sp_elf.h +++ b/tools/wip/sp_elf.h @@ -266,8 +266,8 @@ void sp_elf_buffer_grow(sp_elf_buffer_t* buffer, u64 size) { capacity *= 2; } + buffer->data = (u8*)sp_mem_allocator_realloc(buffer->mem, buffer->data, buffer->capacity, capacity); buffer->capacity = capacity; - buffer->data = (u8*)sp_mem_allocator_realloc(buffer->mem, buffer->data, capacity); } void* sp_elf_section_reserve_aligned(sp_elf_section_t* section, u64 size, u64 align) { @@ -707,7 +707,7 @@ sp_elf_t* sp_elf_read_from_file(sp_mem_t mem, sp_str_t path) { return SP_NULLPTR; } sp_elf_t* elf = sp_elf_read(mem, (const u8*)bytes.data, bytes.len); - sp_free(mem, (void*)bytes.data); + sp_free(mem, (void*)bytes.data, bytes.len); return elf; }