创建SlabContext
分配对象
创建对象池
- 分配空间
- 初始化分配的空间
- 将block加入循环双向链表
从对象池中获取对象
从双向循环链表中获取一个block
/* grab the block from the freelist (even the new block is there) */
block = dlist_head_element(SlabBlock, node,&slab->freelist[slab->minFreeChunks]);
从block中获取空闲chunk的索引
/* we know index of the first free chunk in the block */
idx = block->firstFreeChunk;
获取chunk
/* compute the chunk location block start (after the block header) */chunk = SlabBlockGetChunk(slab, block, idx);
减少空用chunk个数
/** Update the block nfree count, and also the minFreeChunks as we've* decreased nfree for a block with the minimum number of free chunks* (because that's how we chose the block).*/block->nfree--;slab->minFreeChunks = block->nfree;
更新下一个空闲chunk索引
block->firstFreeChunk = *(int32 *) SlabChunkGetPointer(chunk);
将block重新更新到下一个循环双向链表中
/* move the whole block to the right place in the freelist */dlist_delete(&block->node);dlist_push_head(&slab->freelist[block->nfree], &block->node);
当block中的chunk分配完后,整个block就移动到了freelist[0]的位置,freelist[0]下的循环双向链表的节点都是分配完的block
释放对象
根据释放对象,获取到对应的block以及chunk
SlabChunk *chunk = SlabPointerGetChunk(pointer);
SlabBlock *block = chunk->block;
计算当前chunk相对于block的索引
/* compute index of the chunk with respect to block start */
idx = SlabChunkIndex(slab, block, chunk);
更新空闲chunk索引以及空闲chunk个数
/* add chunk to freelist, and update block nfree count */
*(int32 *) pointer = block->firstFreeChunk;
block->firstFreeChunk = idx;
block->nfree++;
将当前block从现有循环双向链表中删除
/* remove the block from a freelist */
dlist_delete(&block->node);
如果释放的chunk所属的block是正用于申请空间的freelist,并且freelist也空了,则更新minFreeChunks
/** See if we need to update the minFreeChunks field for the slab - we only* need to do that if there the block had that number of free chunks* before we freed one. In that case, we check if there still are blocks* in the original freelist and we either keep the current value (if there* still are blocks) or increment it by one (the new block is still the* one with minimum free chunks).** The one exception is when the block will get completely free - in that* case we will free it, se we can't use it for minFreeChunks. It however* means there are no more blocks with free chunks.*/if (slab->minFreeChunks == (block->nfree - 1)){/* Have we removed the last chunk from the freelist? */if (dlist_is_empty(&slab->freelist[slab->minFreeChunks])){/* but if we made the block entirely free, we'll free it */if (block->nfree == slab->chunksPerBlock)slab->minFreeChunks = 0;elseslab->minFreeChunks++;}}
释放block或这加入另外一个循环双向链表中
/* If the block is now completely empty, free it. */if (block->nfree == slab->chunksPerBlock){free(block);slab->nblocks--;context->mem_allocated -= slab->blockSize;}elsedlist_push_head(&slab->freelist[block->nfree], &block->node);