diff --git a/platform/exports/librr/alloc/generic.h b/platform/exports/librr/alloc/generic.h index 5829cac..3daf82c 100644 --- a/platform/exports/librr/alloc/generic.h +++ b/platform/exports/librr/alloc/generic.h @@ -24,7 +24,6 @@ struct rr_generic_pool void * (*fn_alloc) (rr_generic_pool_s *pool); void (*fn_free) (rr_generic_pool_s *pool, void *block); void (*fn_destruct) (rr_generic_pool_s *pool); - usz_t (*fn_get_unit_size) (rr_generic_pool_s *pool); void *specifics; }; @@ -35,4 +34,26 @@ struct rr_generic_arena void *specifics; }; +void * rr_alloc(rr_generic_allocator_s *allocator, usz_t size); +void rr_free(rr_generic_allocator_s *allocator, void *allocation); + +void * rr_arena_alloc(rr_generic_arena_s *arena, usz_t size); + +void * rr_pool_alloc(rr_generic_pool_s *pool); +void rr_pool_free(rr_generic_pool_s *pool, void *allocation); + + +#ifndef __RR_AVOID_STDLIB +rr_generic_allocator_s rr_provide_stdlib_allocator(); +#endif // __RR_AVOID_STDLIB + +rr_generic_arena_s rr_provide_arena(rr_generic_allocator_s *allocator, usz_t len_allocation); +rr_generic_pool_s rr_provide_dynamic_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity); +rr_generic_pool_s rr_provide_static_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity); + +rr_generic_arena_s rr_provide_arena_from_malloc(usz_t len_allocation); +rr_generic_pool_s rr_provide_dynamic_pool_from_malloc(usz_t item_size, usz_t capacity); +rr_generic_pool_s rr_provide_static_pool_from_malloc(usz_t item_size, usz_t capacity); + #endif // RR_GENERIC_ALLOCATOR_H + diff --git a/platform/exports/librr/alloc/arena.h b/platform/inc-c/alloc/arena.h similarity index 60% rename from platform/exports/librr/alloc/arena.h rename to platform/inc-c/alloc/arena.h index e9f7145..03b1638 100644 --- a/platform/exports/librr/alloc/arena.h +++ b/platform/inc-c/alloc/arena.h @@ -5,7 +5,17 @@ #include #include -rr_generic_arena_s rr_new_arena(usz_t capacity); +typedef struct rr_arena rr_arena_s; + +struct rr_arena +{ + usz_t capacity; + usz_t offset; + char *allocation; + rr_generic_allocator_s *allocator; +}; + +rr_generic_arena_s rr_new_arena(rr_generic_allocator_s *allocator, usz_t capacity); void rr_destruct_arena(rr_generic_arena_s *generic_arena); void * rr_arena_alloc(rr_generic_arena_s *generic_arena, usz_t length); diff --git a/platform/inc-c/alloc/pool.h b/platform/inc-c/alloc/pool.h new file mode 100644 index 0000000..640063e --- /dev/null +++ b/platform/inc-c/alloc/pool.h @@ -0,0 +1,32 @@ + +#ifndef RR_POOL_PROVIDER_H +#define RR_POOL_PROVIDER_H + +#include +#include + +typedef struct rr_pool_unit_header rr_pool_unit_header_s; +typedef struct rr_pool rr_pool_s; + +struct rr_pool_unit_header +{ + rr_pool_unit_header_s *next; +}; + +struct rr_pool +{ + usz_t capacity; + usz_t item_size; + rr_pool_unit_header_s *first_free; + void *allocation; + rr_generic_allocator_s *allocator; +}; + +rr_generic_pool_s rr_new_dynamic_pool(rr_generic_allocator_s *allocator, usz_t unit_size, usz_t capacity); +rr_generic_pool_s rr_new_static_pool(rr_generic_allocator_s *allocator, usz_t unit_size, usz_t capacity); +void rr_destruct_pool(rr_generic_pool_s *pool); + +void * rr_pool_alloc_slot(rr_generic_pool_s *pool); +void rr_pool_free_slot(rr_generic_pool_s *pool, void *block); + +#endif // RR_POOL_PROVIDER_H diff --git a/platform/src-c/alloc/arena.c b/platform/src-c/alloc/arena.c index 1cbbea1..b495708 100644 --- a/platform/src-c/alloc/arena.c +++ b/platform/src-c/alloc/arena.c @@ -1,25 +1,15 @@ -#include +#include #include #include -#include - -typedef struct rr_arena rr_arena_s; - -struct rr_arena +rr_generic_arena_s rr_new_arena(rr_generic_allocator_s *allocator, usz_t capacity) { - usz_t capacity; - usz_t offset; - char *allocation; -}; - -rr_generic_arena_s rr_new_arena(usz_t capacity) -{ - rr_arena_s *specifics = malloc(sizeof(rr_arena_s) + capacity); + rr_arena_s *specifics = rr_alloc(allocator, sizeof(rr_arena_s) + capacity); specifics->capacity = capacity; specifics->offset = 0; // The arena allocation is right after the head structure. specifics->allocation = (void *) (specifics + sizeof(rr_arena_s)); + specifics->allocator = allocator; rr_generic_arena_s arena; arena.fn_alloc = &rr_arena_alloc; @@ -31,7 +21,8 @@ rr_generic_arena_s rr_new_arena(usz_t capacity) void rr_destruct_arena(rr_generic_arena_s *generic_arena) { - free(generic_arena->specifics); + rr_arena_s *arena = generic_arena->specifics; + rr_free(arena->allocator, generic_arena->specifics); } diff --git a/platform/src-c/alloc/pool.c b/platform/src-c/alloc/pool.c new file mode 100644 index 0000000..a13cebb --- /dev/null +++ b/platform/src-c/alloc/pool.c @@ -0,0 +1,88 @@ +#include +#include +#include + +void rr_initialize_pool_allocation(rr_pool_s *pool) +{ + usz_t slot_size = sizeof(rr_pool_unit_header_s) + pool->item_size; + slot_size = (slot_size + (32 - slot_size % 32)); + + usz_t slot_index = 0; + while(slot_index < pool->capacity) + { + rr_pool_unit_header_s *current_header = pool->allocation + (slot_index * slot_size); + current_header->next = current_header + slot_size; + ++slot_index; + } + rr_pool_unit_header_s *last_header = pool->allocation + ((pool->capacity - 1) * slot_size); + last_header->next = NULL; +} + +rr_generic_pool_s rr_new_dynamic_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity) +{ + // Size of (header + item) rounded up to 32 + usz_t slot_size = sizeof(rr_pool_unit_header_s) + item_size; + slot_size = (slot_size + (32 - slot_size % 32)); + + rr_pool_s pool; + pool.allocator = allocator; + pool.allocation = rr_alloc(allocator, slot_size * capacity); + pool.item_size = item_size; + pool.capacity = capacity; + pool.first_free = pool.allocation; + rr_initialize_pool_allocation(&pool); + + rr_generic_pool_s generic_pool; + generic_pool.fn_alloc = &rr_pool_alloc_slot; + generic_pool.fn_free = &rr_pool_free_slot; + generic_pool.fn_destruct = &rr_destruct_pool; + return generic_pool; +} + +rr_generic_pool_s rr_new_static_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity) +{ + // Size of (header + item) rounded up to 32 + usz_t slot_size = sizeof(rr_pool_unit_header_s) + item_size; + slot_size = (slot_size + (32 - slot_size % 32)); + + rr_pool_s pool; + pool.allocator = allocator; + pool.allocation = rr_alloc(allocator, slot_size * capacity); + pool.item_size = item_size; + pool.capacity = capacity; + pool.first_free = pool.allocation; + rr_initialize_pool_allocation(&pool); + + rr_generic_pool_s generic_pool; + generic_pool.fn_alloc = &rr_pool_alloc_slot; + generic_pool.fn_free = &rr_pool_free_slot; + generic_pool.fn_destruct = &rr_destruct_pool; + return generic_pool; +} + +void rr_destruct_pool(rr_generic_pool_s *generic_pool) +{ + rr_pool_s *specifics = generic_pool->specifics; + rr_free(specifics->allocator, specifics->allocation); + rr_free(specifics->allocator, specifics); +} + + + +void * rr_pool_alloc_slot(rr_generic_pool_s *generic_pool) +{ + rr_pool_s *specifics = generic_pool->specifics; + rr_pool_unit_header_s *header = specifics->first_free; + specifics->first_free = header->next; + void *item = header + sizeof(rr_pool_unit_header_s); + rr_memset(item, specifics->item_size, 0x00); + return item; +} + +void rr_pool_free_slot(rr_generic_pool_s *generic_pool, void *block) +{ + rr_pool_s *specifics = generic_pool->specifics; + rr_pool_unit_header_s *header = block - sizeof(rr_pool_unit_header_s); + header->next = specifics->first_free; + specifics->first_free = header; +} diff --git a/platform/src-c/alloc/providers.c b/platform/src-c/alloc/providers.c new file mode 100644 index 0000000..69c0047 --- /dev/null +++ b/platform/src-c/alloc/providers.c @@ -0,0 +1,66 @@ +#include +#include +#include + +#ifndef __RR_BAREMETAL +#include + +/// @brief An allocator for the sole purpose of preventing warnings because of an unused +/// parameter in the standard allocator proxying functions. +rr_generic_allocator_s *rr_last_used_proxy_allocator; + +void * rr_proxy_malloc(rr_generic_allocator_s *allocator, usz_t num_bytes) +{ + rr_last_used_proxy_allocator = allocator; + return malloc(num_bytes); +} + +void rr_proxy_free(rr_generic_allocator_s *allocator, void *block) +{ + rr_last_used_proxy_allocator = allocator; + free(block); +} + +rr_generic_allocator_s rr_provide_stdlib_allocator() +{ + rr_generic_allocator_s allocator; + allocator.fn_alloc = &rr_proxy_malloc; + allocator.fn_free = &rr_proxy_free; + allocator.specifics = NULL; + allocator.fn_destruct = NULL; + return allocator; +} +#endif // __RR_BAREMETAL + +rr_generic_arena_s rr_provide_arena(rr_generic_allocator_s *allocator, usz_t len_allocation) +{ + return rr_new_arena(allocator, len_allocation); +} + +rr_generic_pool_s rr_provide_dynamic_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity) +{ + return rr_new_dynamic_pool(allocator, item_size, capacity); +} + +rr_generic_pool_s rr_provide_static_pool(rr_generic_allocator_s *allocator, usz_t item_size, usz_t capacity) +{ + return rr_new_dynamic_pool(allocator, item_size, capacity); +} + +rr_generic_arena_s rr_provide_arena_from_malloc(usz_t len_allocation) +{ + rr_generic_allocator_s allocator = rr_provide_stdlib_allocator(); + return rr_new_arena(&allocator, len_allocation); +} + +rr_generic_pool_s rr_provide_dynamic_pool_from_malloc(usz_t item_size, usz_t capacity) +{ + rr_generic_allocator_s allocator = rr_provide_stdlib_allocator(); + return rr_new_dynamic_pool(&allocator, item_size, capacity); +} + +rr_generic_pool_s rr_provide_static_pool_from_malloc(usz_t item_size, usz_t capacity) +{ + rr_generic_allocator_s allocator = rr_provide_stdlib_allocator(); + return rr_new_static_pool(&allocator, item_size, capacity); +} diff --git a/platform/src-c/alloc/shortcuts.c b/platform/src-c/alloc/shortcuts.c new file mode 100644 index 0000000..686e07e --- /dev/null +++ b/platform/src-c/alloc/shortcuts.c @@ -0,0 +1,30 @@ +#include + +void * rr_alloc(rr_generic_allocator_s *allocator, usz_t size) +{ + return allocator->fn_alloc(allocator, size); +} + +void rr_free(rr_generic_allocator_s *allocator, void *allocation) +{ + return allocator->fn_free(allocator, allocation); +} + + + +void * rr_arena_alloc(rr_generic_arena_s *arena, usz_t size) +{ + return arena->fn_alloc(arena, size); +} + + + +void * rr_pool_alloc(rr_generic_pool_s *pool) +{ + return pool->fn_alloc(pool); +} + +void rr_pool_free(rr_generic_pool_s *pool, void *allocation) +{ + return pool->fn_free(pool, allocation); +}