diff options
Diffstat (limited to 'src/common/libkogata/slab_alloc.c')
-rw-r--r-- | src/common/libkogata/slab_alloc.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/src/common/libkogata/slab_alloc.c b/src/common/libkogata/slab_alloc.c index 2f6cef1..729bdc3 100644 --- a/src/common/libkogata/slab_alloc.c +++ b/src/common/libkogata/slab_alloc.c @@ -251,7 +251,7 @@ void slab_free(mem_allocator_t* a, void* addr) { r->n_free_objs++; if (r->n_free_objs == region_size / a->types[i].obj_size) { - // region is completely unused, free it. + // region is completely unused, free it if we have two that are unused. if (a->slabs[i].first_cache == r) { a->slabs[i].first_cache = r->next_cache; } else { @@ -262,8 +262,22 @@ void slab_free(mem_allocator_t* a, void* addr) { } } } - a->free_fun(r->region_addr); - add_free_descriptor(a, (descriptor_t*)r); + + cache_t *last_cache = a->slabs[i].first_cache; + while (last_cache && last_cache->next_cache) last_cache = last_cache->next_cache; + + if (last_cache == 0) { + ASSERT(a->slabs[i].first_cache == 0); + a->slabs[i].first_cache = r; + r->next_cache = 0; + } else if (last_cache->n_free_objs == region_size / a->types[i].obj_size) { + a->free_fun(r->region_addr); + add_free_descriptor(a, (descriptor_t*)r); + } else { + ASSERT(last_cache->next_cache == 0); + last_cache->next_cache = r; + r->next_cache = 0; + } } return; } |