linux核心分析———SLAB原理及實現二
//填充CPU快取記憶體
static void *cache_alloc_refill(structkmem_cache *cachep, gfp_t flags)
{
int batchcount;
struct kmem_list3 *l3;
struct array_cache *ac;
int node;
ac = cpu_cache_get(cachep);//獲得高所快取所在本地CPU快取
retry:
batchcount = ac->batchcount;
if (!ac->touched && batchcount > BATCHREFILL_LIMIT){
/*如果不經常活動,則部分填充*/
batchcount = BATCHREFILL_LIMIT;//16
}
l3 = cachep->nodelists[node];//獲得相應的kmem_list3結構體
...
/* 先考慮從共享本地CPU快取記憶體*/
if (l3->shared && transfer_objects(ac, l3->shared,batchcount))
goto alloc_done;
while (batchcount > 0) {//老老實實的從本快取記憶體分配
struct list_head *entry;
struct slab *slabp;
/* Get slab alloc is to come from. */
entry = l3->slabs_partial.next;//半滿的連結串列
if (entry == &l3->slabs_partial) {//如果半空的都沒了,找全空的
l3->free_touched = 1;
entry = l3->slabs_free.next;
if (entry == &l3->slabs_free)//全空的也沒了,必須擴充了
cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
}
//此時,已經找到了一個連結串列(半空或者全空)
slabp = list_entry(entry, struct slab, list);//找到一個slab
check_slabp(cachep, slabp);
check_spinlock_acquired(cachep);
while (slabp->inuse < cachep->num &&batchcount--)
{//迴圈從slab中分配物件
ac->entry[ac->avail++] =slab_get_obj(cachep, slabp,node);
}
check_slabp(cachep, slabp);
/*將slab放到合適的鏈中:*/
list_del(&slabp->list);
if (slabp->free == BUFCTL_END)//如果已經沒有空閒物件了,則放到滿連結串列中
list_add(&slabp->list, &l3->slabs_full);
else//否則放在半滿連結串列
list_add(&slabp->list, &l3->slabs_partial);
}
...
ac->touched = 1;
return ac->entry[--ac->avail];
}