__hot void *navi_slab_alloc(struct slab_cache *cache) { struct slab *slab = get_slab(cache); void *obj = slab_pop(cache, slab); // move slab to full/partial list, as appropriate if (++slab->in_use == cache->objs_per_slab) { slab_remove(slab); slab_insert(&cache->full, slab); } else if (slab->in_use == 1) { slab_remove(slab); slab_insert(&cache->partial, slab); } return obj; }
END_TEST START_TEST(slablist) { slabclass_t* psct = &slab.slabclass[1]; // size:144 perslab:58254 void* ps = pool_new(&slab); bool ret = slab_add(&slab, psct, ps); fail_unless(ret); fail_unless(NULL != psct->slab_list); fail_unless(ps == psct->slab_list->ptr); fail_unless(NULL == psct->slab_list->next); size_t need_byte = (size_t)ceil(psct->perslab / 8); void* pv = malloc(need_byte); memset(pv, 0, need_byte); fail_unless(0 == memcmp(pv, psct->slab_list->used_bitmap, need_byte)); void* ps2 = pool_new(&slab); ret = slab_add(&slab, psct, ps2); fail_unless(ret); fail_unless(NULL != psct->slab_list); fail_unless(ps2 == psct->slab_list->ptr); fail_unless(NULL != psct->slab_list->next); fail_unless(NULL == psct->slab_list->next->next); void* ps3 = pool_new(&slab); ret = slab_add(&slab, psct, ps3); fail_unless(ret); slablist_t* pslt = slab_search(&slab, psct, ((char*)ps + 4)); fail_unless(pslt == psct->slab_list->next->next); pslt = slab_search(&slab, psct, ((char*)ps2)); fail_unless(pslt == psct->slab_list->next); pslt = slab_search(&slab, psct, ((char*)ps3 + SETTING_ITEM_SIZE_MAX)); fail_unless(pslt == psct->slab_list); pslt = slab_search(&slab, psct, 0); fail_unless(pslt == NULL); void* ps4 = slab_remove(&slab, psct, psct->slab_list->next); fail_unless(ps4 == ps2); fail_unless(psct->slab_list->ptr == ps3); fail_unless(psct->slab_list->next->ptr == ps); fail_unless(psct->slab_list->next->next == NULL); void* ps5 = slab_remove(&slab, psct, psct->slab_list); fail_unless(ps5 == ps3); fail_unless(psct->slab_list->ptr == ps); fail_unless(psct->slab_list->next == NULL); }
void __hot navi_slab_free(struct slab_cache *cache, void *mem) { struct slab *slab; if (!(slab = find_slab(cache, mem))) navi_die("slab_free: failed to locate slab!\n"); if (cache->flags & NAVI_SLAB_DOUBLY_LINKED) { struct slab_list_entry *obj = mem; NAVI_LIST_INSERT_HEAD(&slab->_free, obj, link); } else { struct slab_slist_entry *obj = mem; NAVI_SLIST_INSERT_HEAD(&slab->free, obj, link); } // update slab status within cache if (--slab->in_use == 0) { slab_remove(slab); slab_insert(&cache->empty, slab); } else if (slab->in_use + 1 == cache->objs_per_slab) { slab_remove(slab); slab_insert(&cache->partial, slab); } }