void mslab_free(struct mempool *pool, struct mslab *slab, void *ptr) { /* put object to garbage list */ *(void **)ptr = slab->free_list; slab->free_list = ptr; slab->nfree++; if (slab->nfree == 1) { /** * Add this slab to the rbtree which contains partially * populated slabs. */ mslab_tree_insert(&pool->free_slabs, slab); } else if (slab->nfree == pool->objcount) { /** Free the slab. */ mslab_tree_remove(&pool->free_slabs, slab); if (pool->spare > slab) { slab_list_del(&pool->slabs, &pool->spare->slab, next_in_list); slab_put(pool->cache, &pool->spare->slab); pool->spare = slab; } else if (pool->spare) { slab_list_del(&pool->slabs, &slab->slab, next_in_list); slab_put(pool->cache, &slab->slab); } else { pool->spare = slab; } } }
/** * Release all memory down to new_size; new_size has to be previously * obtained by calling region_used(). */ void region_truncate(struct region *region, size_t used) { ssize_t cut_size = region_used(region) - used; assert(cut_size >= 0); while (! rlist_empty(®ion->slabs.slabs)) { struct rslab *slab = rlist_first_entry(®ion->slabs.slabs, struct rslab, slab.next_in_list); if (slab->used > cut_size) { /* This is the last slab to trim. */ slab->used -= cut_size; cut_size = 0; break; } cut_size -= slab->used; /* Remove the entire slab. */ slab_list_del(®ion->slabs, &slab->slab, next_in_list); slab_put(region->cache, &slab->slab); } assert(cut_size == 0); region->slabs.stats.used = used; }