static int cache_grow(struct kmem_cache *cachep,
gfp_t flags, int nodeid, void *objp)
当SLAB不够时用于分配新的SLAB。
offset = l3->colour_next;
l3->colour_next++;
if (l3->colour_next >= cachep->colour)
l3->colour_next = 0;
spin_unlock(&l3->list_lock);
offset *= cachep->colour_off;
SLAB着色,用以减少CPU缓存 冲突。;
获取下一个颜色号,如果该号大于颜色数,则归0,重新计数,kmem_cache中的颜色数由缓冲创建的时候的剩余页区域计算得到,如下:
cachep->colour = left_over / cachep->colour_off;cachep->colour_off是硬件缓存行大小。
利用颜色号*colour_off,得到偏移。
if (!objp)
objp = kmem_getpages(cachep, local_flags, nodeid);
if (!objp)
goto failed;
利用cachep中的num gfpoder等值分配页,这些值是该缓冲下每个SLAB的页和对象的数目。返回的是页的虚拟地址(线性地址)
/* Get slab management. */
slabp = alloc_slabmgmt(cachep, objp, offset,
local_flags & ~GFP_CONSTRAINT_MASK, nodeid);
if (!slabp)
goto opps1;
分配SLAB管理数据,如果管理数据在里面的话如下计算:
slabp = objp + colour_off;
着色,偏移
colour_off += cachep->slab_size;
着色偏移值加上SLAB头数据大小, 该大小是slab_size = cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
slabp->s_mem = objp + colour_off;
SLAB对象进行着色,偏移。
最终的内存为:
objp起始地址 该SLAB的颜色号*cachep->colour_off大小的偏移SLAB结构cachep->num * sizeof(kmem_bufctl_t)大小的位图对象数据
slab_map_pages(cachep, slabp, objp);
建立每个页的page结构到缓冲和slab结构的关系。
cache_init_objs(cachep, slabp);
在位图中建立下一个可用对象索引数据, 并调用构造函数对每个对象进行构造。
list_add_tail(&slabp->list, &(l3->slabs_free));
STATS_INC_GROWN(cachep);
l3->free_objects += cachep->num;
spin_unlock(&l3->list_lock);
将该SLAB加入缓冲的链表中, 并更新可用对象的数目。
kmalloc
该函数主要用于分配通用大小的数据。
首先选择一个合适size的缓冲,查找每CPU中是否有合适的对象,如果没有则进行分配。
kmem_cache_alloc
该函数是针对特定对象的分配,比kmalloc少了选择缓冲的操作。
两者最后都会执行__cache_alloc中的分配动作。
__cache_free
释放对象,将对象加入每CPU结构中,如果操出limit值则会进行缓冲收缩,释放slab.
cache_flusharray
中会引起缓冲收缩。