aboutsummaryrefslogtreecommitdiff
path: root/src/common/libkogata/slab_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/libkogata/slab_alloc.c')
-rw-r--r--src/common/libkogata/slab_alloc.c20
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;
}