将新分配的page切割成chunk,并将chunk连接到slabclass[id]的slots链表头。
static int do_slabs_newslab(const unsigned int id)
为slabclass[id]增加一个新的page,它会调用grow_slab_list确保slab_list空间,从slabclass[0]或者其它方式获得新的page,调用split_slab_page_into_freelist处理新的page。
static void *do_slabs_alloc(const size_t size, unsigned int id, uint64_t *total_bytes, unsigned int flags)
从slabclass[id]中获取一个未使用的chunk,除了做一些必要的检查之外,获取的方式相当简单,直接从slots链表头获取一个chunk即可。另外返回的chunk会做一些初始化设置,如清除ITEM_SLABBED标志,表示该chunk已被使用,设置引用计数为1等。
static void do_slabs_free(void *ptr, const size_t size, unsigned int id)
释放ptr指向的item,新该chunk重新插入到slots链表头。初始化一些参数,如flag设置为ITEM_SLABBED表示该chunk未被使用。参数size为item实际使用的内存大小,用作一些信息统计,并非chunk的大小。另外有一种称为chunked的item(见其它解析),它的flag被设置为ITEM_CHUNKED,释放时需要调用do_slabs_free_chunked函数,以释放相关的chunk。
static int slab_rebalance_move(void)
做移动page时的处理操作,确保要移动的page中存储的item已被移动到其它的page中。
memcached中有一个称为slab_rebalance_thread的线程,该线程的作为即在各个slabclass_t中移动page,平衡内存分配。线程中使用一个条件信号量slab_rebalance_cond,当没有平衡任务时,线程一直等待该信号量,处于休眠状态。外界调用slabs_reassign函数启动平衡任务,该函数将发送条件信号量,激活线程。线程按照图3-1的流程,调用slab_rebalance_start设置内存检查pos等,然后调用slab_rebalance_move完成page清理工作,最后调用函数slab_rebalance_finish完成平衡任务,线程再次进入休眠,等待新的平衡任务。