mirror of https://github.com/flysand7/ciabatta.git
Add memory pool to cia-mem, use it for FILE
This commit is contained in:
parent
80fde89a6f
commit
d9f530fe58
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -10,3 +10,11 @@ void *cia_ptr_alignb(void *ptr, u64 alignment) {
|
|||
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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue