Add memory pool to cia-mem, use it for FILE

This commit is contained in:
flysand7 2023-07-31 04:17:57 +11:00
parent 80fde89a6f
commit d9f530fe58
5 changed files with 142 additions and 9 deletions

View File

@ -3,6 +3,8 @@
void *cia_ptr_alignf(void *ptr, u64 alignment);
void *cia_ptr_alignb(void *ptr, u64 alignment);
u64 cia_size_alignf(u64 size, u64 alignment);
u64 cia_size_alignb(u64 size, u64 alignment);
#define CIA_MEM_OP_ALLOC 1
#define CIA_MEM_OP_FREE 2
@ -37,3 +39,31 @@ void *cia_arena_alloc(Cia_Arena *arena, u64 size);
void *cia_arena_alloc_aligned(Cia_Arena *arena, u64 size, u64 align);
void cia_arena_free_all(Cia_Arena *arena);
void cia_arena_destroy(Cia_Arena *arena);
struct Cia_Pool_Bucket typedef Cia_Pool_Bucket;
struct Cia_Pool_Bucket {
Cia_Pool_Bucket *next;
};
struct Cia_Pool_Buffer_Header typedef Cia_Pool_Buffer_Header;
struct Cia_Pool_Buffer_Header {
Cia_Pool_Buffer_Header *next;
u64 free_buckets_count;
Cia_Pool_Bucket *free_head;
};
struct Cia_Pool typedef Cia_Pool;
struct Cia_Pool {
Cia_Allocator allocator;
Cia_Pool_Buffer_Header *first;
u64 buffer_size;
u64 bucket_size;
u64 alignment;
};
void cia_pool_create(Cia_Pool *pool, Cia_Allocator backing_allocator, u64 buffer_size, u64 element_size, u64 alignment);
void *cia_pool_alloc(Cia_Pool *pool);
void cia_pool_free(Cia_Pool *pool, void *ptr);
void cia_pool_free_all(Cia_Pool *pool);
void cia_pool_destroy(Cia_Pool *pool);

94
src/impl/cia-mem/pool.c Normal file
View File

@ -0,0 +1,94 @@
static void pool_reinit_buffer(Cia_Pool *pool, u8 *buffer) {
Cia_Pool_Buffer_Header *header = (Cia_Pool_Buffer_Header *)buffer;
u64 header_size = sizeof(Cia_Pool_Buffer_Header);
u64 header_size_aligned = cia_size_alignf(header_size, pool->alignment);
u8 *buckets = buffer + header_size_aligned;
u64 remaining_size = pool->buffer_size - header_size_aligned;
u64 buckets_count = remaining_size / pool->bucket_size;
header->free_buckets_count = buckets_count;
u64 buckets_size = buckets_count * pool->bucket_size;
// Initialize every bucket as free
u64 bucket_offset = header_size_aligned + buckets_size;
Cia_Pool_Bucket *next_bucket = NULL;
do {
bucket_offset -= pool->bucket_size;
Cia_Pool_Bucket *bucket = (Cia_Pool_Bucket *)(buffer + bucket_offset);
bucket->next = next_bucket;
next_bucket = bucket;
} while(bucket_offset > header_size_aligned);
header->free_head = next_bucket;
}
void cia_pool_create(Cia_Pool *pool, Cia_Allocator backing_allocator, u64 buffer_size, u64 bucket_size, u64 alignment) {
pool->allocator = backing_allocator;
pool->buffer_size = buffer_size;
pool->bucket_size = bucket_size;
pool->alignment = alignment;
// If the unallocated element can't hold a bucket, increase the size of the element
if(pool->bucket_size < sizeof(Cia_Pool_Bucket)) {
pool->bucket_size = sizeof(Cia_Pool_Bucket);
}
// Make element size a multiple of the alignment
pool->bucket_size = cia_size_alignf(pool->bucket_size, pool->alignment);
// Allocate and initialize the first buffer
pool->first = allocator_alloc(&pool->allocator, pool->buffer_size, pool->alignment);
pool_reinit_buffer(pool, (u8 *)pool->first);
}
void *cia_pool_alloc(Cia_Pool *pool) {
Cia_Pool_Buffer_Header *buffer = pool->first;
// Find buffer with free data in it
while(buffer != NULL) {
if(buffer->free_buckets_count > 0) {
break;
}
buffer = buffer->next;
}
// If none have it, then create a new buffer
if(buffer == NULL) {
void *buffer_mem = allocator_alloc(&pool->allocator, pool->buffer_size, pool->alignment);
pool_reinit_buffer(pool, buffer_mem);
Cia_Pool_Buffer_Header *header = buffer_mem;
header->next = pool->first;
pool->first = header;
buffer = header;
}
// Remove item from free list and return it
void *addr = buffer->free_head;
buffer->free_head = buffer->free_head->next;
return addr;
}
void cia_pool_free(Cia_Pool *pool, void *ptr) {
// Check which buffer the allocation is from
Cia_Pool_Buffer_Header *source = NULL;
for(Cia_Pool_Buffer_Header *buffer = pool->first; buffer != NULL; buffer = buffer->next) {
void *buffer_start = buffer;
void *buffer_end = (u8 *)buffer + pool->buffer_size;
if(buffer_start < ptr && ptr < buffer_end) {
source = buffer;
break;
}
}
// Add bucket to free list
Cia_Pool_Bucket *bucket = ptr;
bucket->next = source->free_head;
source->free_head = bucket;
}
void cia_pool_free_all(Cia_Pool *pool) {
// Deallocate all buffers except the first one
for(Cia_Pool_Buffer_Header *buffer = pool->first->next; buffer != NULL; buffer = buffer->next) {
allocator_free_size(&pool->allocator, buffer, pool->buffer_size);
}
// Reinit the first buffer
pool_reinit_buffer(pool, (u8 *)pool->first);
}
void cia_pool_destroy(Cia_Pool *pool) {
// Simply deallocate all the buffers
for(Cia_Pool_Buffer_Header *buffer = pool->first; buffer != NULL; buffer = buffer->next) {
allocator_free_size(&pool->allocator, buffer, pool->buffer_size);
}
}

View File

@ -9,4 +9,12 @@ void *cia_ptr_alignb(void *ptr, u64 alignment) {
u64 addr = (u64)ptr;
u64 aligned = addr & ~(alignment - 1);
return (void *)aligned;
}
u64 cia_size_alignf(u64 size, u64 alignment) {
return (size + alignment - 1) & ~(alignment - 1);
}
u64 cia_size_alignb(u64 size, u64 alignment) {
return size & ~(alignment - 1);
}

View File

@ -3,17 +3,17 @@ FILE *stdin;
FILE *stdout;
FILE *stderr;
// TODO: memory allocation
static FILE _files[64];
static int _files_cnt = 0;
static Cia_Pool _page_allocator;
static Cia_Pool _file_pool;
static void _fileapi_init() {
cia_pool_create(&_file_pool, cia_allocator_pages(), 0x1000, sizeof(FILE), 16);
FILE *stdin = cia_pool_alloc(&_file_pool);
FILE *stdout = cia_pool_alloc(&_file_pool);
FILE *stderr = cia_pool_alloc(&_file_pool);
_rt_file_std_handles_init();
stdin = &_files[_files_cnt++];
stdin->rt_file = _rt_file_stdin;
stdout = &_files[_files_cnt++];
stdout->rt_file = _rt_file_stdout;
stderr = &_files[_files_cnt++];
stderr->rt_file = _rt_file_stderr;
}
@ -30,8 +30,7 @@ FILE *fopen(char const *restrict filename, char const *restrict mode) {
if(status != _RT_STATUS_OK) {
return NULL;
}
FILE *file = &_files[_files_cnt];
_files_cnt += 1;
FILE *file = cia_pool_alloc(&_file_pool);
file->rt_file = rt_file;
return file;
}

View File

@ -61,6 +61,7 @@ apis: [
"util.c",
"allocator.c",
"arena.c",
"pool.c",
],
reqs: [
"rt_api_memory"
@ -84,7 +85,8 @@ apis: [
"file.c"
],
reqs: [
"rt_api_file"
"rt_api_file",
"cia_memory",
]
}
]