SLUB 03:partial和cpu partial
2017-01-14
主要介绍partial和cpu partial的产生.
内核未定义 CONFIG_NUMA
partial没有指明是node partial还是cpu partial时, 则指的是node partial.
1. node partial的产生
在cpu0上执行newslabobjects -> new_slab, 由于可能睡眠, 之后可能运行在cpu1上. 这时若cpu1的c->page非空, 则根据情况, 可能将其放入node partial中.
linux-3.10.86/mm/slub.c
__slab_alloc
|--local_irq_save(flags);
|--freelist =new_slab_objects //buddy的page的首个obj
| |--page = new_slab(s, flags, node); //在cpu0上
| |--c = __this_cpu_ptr(s->cpu_slab) //进程可能迁移到cpu1上
| |--if (c->page) flush_slab(s, c);
flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
|-- deactivate_slab(s, c->page, c->freelist)
static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist)
{
/*
while循环前:
obj_t2 -> obj_t1 -> NULL
^
@page->freelist
obj_03 -> obj_02 -> obj_01 -> NULL
^
@freelist
循环单次后:
obj_03 -> obj_t2 -> obj_t1 -> NULL
^
page->freelist
obj_02 -> obj_01 -> NULL
^
freelist
再来一回:
obj_02 -> obj_03 -> obj_t2 -> obj_t1 -> NULL
^
page->freelist
obj_01 -> NULL
^
freelist
问题:为何不直接修改指针把两个链表串起来, 而是要一个一个object的放到链表中?
答:因为要修改counters, 所以要一个一个数.
*/
while (freelist && (nextfree = get_freepointer(s, freelist))) {
...
}
....
/*
如果这里freelist为NULL, 说明@freelist传入时就为NULL
*/
/*把the last one也接上*/
if (freelist) {
new.inuse--;
/*
new->freelist
v
obj_01 -> obj_02 -> obj_03 -> obj_t2 -> obj_t1 -> NULL
^
freelist
*/
set_freepointer(s, freelist, old.freelist);
new.freelist = freelist;
} else
...
new.frozen = 0;
//有M_FREE, M_PARTIAL等情况, 这里只看M_PARTIAL
...
if (m == M_PARTIAL) {
/*问题:为何不是put_cpu_partial()?*/
add_partial(n, page, tail);
}
}
2. cpu partial的产生
kmem_cache_free -> slab_free(s, virt_to_head_page(x), x, ...)
|-- if (page != c->page) __slab_free
| |--n = NULL
| |-- 原先obj链表为: -> NULL , 释放obj_t3后为: -> obj_t3 -> NULL
| |-- new.inuse--;
| |--if (!prior) && !was_frozen)new.frozen = 1;//obj_t3所属的page, 除obj_t3外, 没有其他obj可供分配了.
| |--if (!new.inuse)&& !was_frozen) n = get_node //obj放回page后, page就是完整的, 打算把page放到node partial中
|--if (likely(!n)) //不放回node
| |--if (new.frozen && !was_frozen) put_cpu_partial(s, page, 1)//当前page没人接管, 则放回cpu partial
什么情况下wasfrozen会是0?
答: c->page把obj分配光了, c->page就处于unforzen状态, 接下来其他page作为c->page.
这时的page处于比较有趣的一种状态, struct kmemcache没有字段管理这个page,
struct kmemcachecpu也没有链表管理这个page. 我们只能通过obj来找到该page.
现在释放obj, 我们就有机会把这些特殊状态的page收集起来, 将其放入cpu partial.
__slab_alloc
|--page = c->page;
|--freelist = c->freelist;
|-- if freelist 为空
| |--freelist = get_freelist(s, page);
| | |--/*if NULL, then unfreeze 解冻. if !NULL, then 维持frozen */
| | |--new.frozen = freelist != NULL;
本文地址: https://awakening-fong.github.io/posts/mm/slub_partial
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.
blog comments powered by Disqus