[bugfix] Make one freelist per pool, instead of one per buffer

This commit is contained in:
flysand7 2023-07-31 04:47:18 +11:00
parent 344d9f0398
commit 8c0590e517
2 changed files with 17 additions and 37 deletions

View File

@ -48,14 +48,13 @@ struct Cia_Pool_Bucket {
struct Cia_Pool_Buffer_Header typedef Cia_Pool_Buffer_Header; struct Cia_Pool_Buffer_Header typedef Cia_Pool_Buffer_Header;
struct Cia_Pool_Buffer_Header { struct Cia_Pool_Buffer_Header {
Cia_Pool_Buffer_Header *next; Cia_Pool_Buffer_Header *next;
u64 free_buckets_count;
Cia_Pool_Bucket *free_head;
}; };
struct Cia_Pool typedef Cia_Pool; struct Cia_Pool typedef Cia_Pool;
struct Cia_Pool { struct Cia_Pool {
Cia_Allocator allocator; Cia_Allocator allocator;
Cia_Pool_Buffer_Header *first; Cia_Pool_Buffer_Header *first;
Cia_Pool_Bucket *freelist_head;
u64 buffer_size; u64 buffer_size;
u64 bucket_size; u64 bucket_size;
u64 alignment; u64 alignment;

View File

@ -1,5 +1,5 @@
static void pool_reinit_buffer(Cia_Pool *pool, u8 *buffer) { static void *_pool_buffer_freelist_add(Cia_Pool *pool, u8 *buffer) {
Cia_Pool_Buffer_Header *header = (Cia_Pool_Buffer_Header *)buffer; Cia_Pool_Buffer_Header *header = (Cia_Pool_Buffer_Header *)buffer;
u64 header_size = sizeof(Cia_Pool_Buffer_Header); u64 header_size = sizeof(Cia_Pool_Buffer_Header);
u64 header_size_aligned = cia_size_alignf(header_size, pool->alignment); u64 header_size_aligned = cia_size_alignf(header_size, pool->alignment);
@ -10,14 +10,15 @@ static void pool_reinit_buffer(Cia_Pool *pool, u8 *buffer) {
u64 buckets_size = buckets_count * pool->bucket_size; u64 buckets_size = buckets_count * pool->bucket_size;
// Initialize every bucket as free // Initialize every bucket as free
u64 bucket_offset = header_size_aligned + buckets_size; u64 bucket_offset = header_size_aligned + buckets_size;
Cia_Pool_Bucket *next_bucket = NULL; Cia_Pool_Bucket *next_bucket = pool->freelist_head;
do { do {
bucket_offset -= pool->bucket_size; bucket_offset -= pool->bucket_size;
Cia_Pool_Bucket *bucket = (Cia_Pool_Bucket *)(buffer + bucket_offset); Cia_Pool_Bucket *bucket = (Cia_Pool_Bucket *)(buffer + bucket_offset);
bucket->next = next_bucket; bucket->next = next_bucket;
next_bucket = bucket; next_bucket = bucket;
} while(bucket_offset > header_size_aligned); } while(bucket_offset > header_size_aligned);
header->free_head = next_bucket; // Add the head of the newly-created freelist to the existing freelist
pool->freelist_head = next_bucket;
} }
void cia_pool_create(Cia_Pool *pool, Cia_Allocator backing_allocator, u64 buffer_size, u64 bucket_size, u64 alignment) { void cia_pool_create(Cia_Pool *pool, Cia_Allocator backing_allocator, u64 buffer_size, u64 bucket_size, u64 alignment) {
@ -32,49 +33,28 @@ void cia_pool_create(Cia_Pool *pool, Cia_Allocator backing_allocator, u64 buffer
// Make element size a multiple of the alignment // Make element size a multiple of the alignment
pool->bucket_size = cia_size_alignf(pool->bucket_size, pool->alignment); pool->bucket_size = cia_size_alignf(pool->bucket_size, pool->alignment);
// Allocate and initialize the first buffer // Allocate and initialize the first buffer
pool->freelist_head = NULL;
pool->first = allocator_alloc(&pool->allocator, pool->buffer_size, pool->alignment); pool->first = allocator_alloc(&pool->allocator, pool->buffer_size, pool->alignment);
pool_reinit_buffer(pool, (u8 *)pool->first); _pool_buffer_freelist_add(pool, (u8 *)pool->first);
} }
void *cia_pool_alloc(Cia_Pool *pool) { void *cia_pool_alloc(Cia_Pool *pool) {
Cia_Pool_Buffer_Header *buffer = pool->first; // If we don't have enough free buckets, create a new buffer
// Find buffer with free data in it if(pool->freelist_head == NULL) {
while(buffer != NULL) { void *buffer = allocator_alloc(&pool->allocator, pool->buffer_size, pool->alignment);
if(buffer->free_buckets_count > 0) { _pool_buffer_freelist_add(pool, buffer);
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 // Remove item from free list and return it
void *addr = buffer->free_head; void *addr = pool->freelist_head;
buffer->free_head = buffer->free_head->next; pool->freelist_head = pool->freelist_head->next;
return addr; return addr;
} }
void cia_pool_free(Cia_Pool *pool, void *ptr) { 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 // Add bucket to free list
Cia_Pool_Bucket *bucket = ptr; Cia_Pool_Bucket *bucket = ptr;
bucket->next = source->free_head; bucket->next = pool->freelist_head;
source->free_head = bucket; pool->freelist_head = bucket;
} }
void cia_pool_free_all(Cia_Pool *pool) { void cia_pool_free_all(Cia_Pool *pool) {
@ -83,7 +63,8 @@ void cia_pool_free_all(Cia_Pool *pool) {
allocator_free_size(&pool->allocator, buffer, pool->buffer_size); allocator_free_size(&pool->allocator, buffer, pool->buffer_size);
} }
// Reinit the first buffer // Reinit the first buffer
pool_reinit_buffer(pool, (u8 *)pool->first); pool->freelist_head = NULL;
_pool_buffer_freelist_add(pool, (u8 *)pool->first);
} }
void cia_pool_destroy(Cia_Pool *pool) { void cia_pool_destroy(Cia_Pool *pool) {