SLUB 02:frozen
2017-01-14
本文假定没有打开CONFIGSLUBDEBUG, 没有配置CONFIG_NUMA.
1. 什么是frozen
linux-3.10.86/mm/slub.c
* If a slab is frozen then it is exempt(免除) from list management. It is not
* on any list. It is not on any list. The processor that froze the slab is the one who can
* perform list operations on the page. Other processors may put objects
* onto the freelist but the processor that froze the slab is the only
* one that can retrieve the objects from the page's freelist.
cpu01的c->page是frozen, 那么cpu01可以从该page中取出或放回obj, cpu02不能从该page中取obj, 只能把obj还给该page.
2. cpu partial上的page都是frozen状态
linux-3.10.86/include/linux/slub_def.h
struct kmem_cache_cpu {
...
struct page *partial; /* Partially allocated frozen slabs */
...
};
c->partial 都是 冻住的?
答:是的:
__slab_alloc
|--new_slab:
| |--if (c->partial)
| | |--page = c->page = c->partial;
| | |--c->partial = page->next;
| | |--c->freelist = NULL;
|--redo:
| |--freelist = c->freelist;
|--freelist = get_freelist(s, page); //obj01 -> obj02 -> obj03 -> NULL, get_freelist返回obj01
| |--...
| |--page->freelist = NULL; //为后续归还obj到该page做好准备.
| |--return page_bk->freelist;
|--load_freelist:
| |--VM_BUG_ON(!c->page->frozen); //c->partial上的page都是frozen的. page只有frozen的才可作为c->page
| |-- c->freelist = get_freepointer(s, freelist);//c->freelist指向obj02
| |-- c->tid = next_tid(c->tid);
| |-- return freelist; //freelist指向obj01
3. node partial上的page都是unfrozen
get_partial_node
{
list_for_each_entry_safe(page, page2, &n->partial, lru) {
acquire_slab
{
VM_BUG_ON(new.frozen); //n->partial上的page都是 没有冻 的.
new.frozen = 1;
remove_partial(n, page);
}
...
c->page = page or put_cpu_partial 两相宜. page都是frozen的.
}
}
4. c->page要求frozen
__slab_alloc
|--local_irq_save(flags);
|--freelist =new_slab_objects //buddy的page的首个obj
| |--page = new_slab(s, flags, node); //假定在cpu0上
| | |--page->frozen = 1;
| |--c = __this_cpu_ptr(s->cpu_slab) //new_slab()比较慢, 现在进程可能迁移到cpu1上
| |--freelist = page->freelist;
| |--page->freelist = NULL;
| |--c->page = page; //c->page的page 其freelist 为 NULL, 且frozen 为 1.
|--goto load_freelist
| |--That page must be frozen for per cpu allocations to work.
| |--VM_BUG_ON(!c->page->frozen);
| |--修改c->freelist c->tid
| |--local_irq_restore(flags);
| |--return freelist
这个设计牛逼了, 允许同时从同一个page 一端取出 , 而在另一端放回.
取出通过c->freelist;
把某obj放回, 比如把objt2放回, 通过objt2找到其所属的page, 然后放回page->freepointer, 形成链表:
objt2 -> objt1 -> NULL.
5. 耗尽c->page的obj后解冻page
static inline void *get_freelist(struct kmem_cache *s, struct page *page)
{
VM_BUG_ON(!new.frozen);
...
/*
if NULL, then unfreeze. 解冻
if !NULL, then 维持frozen
*/
new.frozen = freelist != NULL;
}
如果c->page没有obj供分配了, 那么就解冻了.
本文地址: https://awakening-fong.github.io/posts/mm/slub_frozen
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.