static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, ...) {
if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))
return NULL;
struct kmem_cache *cachep = kmalloc_slab(size, flags);
void * ret = slab_alloc(cachep, flags, ...);
return ret;}
第一级分配
struct array_cache __percpu *cpu_cache;struct array_cache {
unsigned int avail;
unsigned int limit;
void *entry[];
};

void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) {
void *objp;
struct array_cache *ac = cpu_cache_get(cachep);
if (likely(ac->avail)) {
objp = ac->entry[--ac->avail];
return objp;
}
objp = cache_alloc_refill(cachep, flags);
...}
第二级分配
全部分配完,没有空闲objects的full slabs。
分配了一部分,尚有部分空闲的partial slabs。 完全空闲可用的free slabs。
struct kmem_cache_node *node[MAX_NUMNODES]; struct kmem_cache_node {
struct list_head slabs_partial;
struct list_head slabs_full;
struct list_head slabs_free;
...}

第三级分配

void ___cache_free(struct kmem_cache *cachep, void *objp, ..) {
struct array_cache *ac = cpu_cache_get(cachep);
if (ac->avail >= ac->limit) {
// 归还到对应的slab
cache_flusharray(cachep, ac);
}
ac->entry[ac->avail++] = objp;}
void kfree(const void *objp) {
struct kmem_cache *c = virt_to_cache(objp);
__cache_free(c, (void *)objp, _RET_IP_);
...} struct kmem_cache *virt_to_cache(const void *obj) {
struct page *page = virt_to_head_page(obj);
return page->slab_cache;} struct page *virt_to_head_page(const void *x) {
// object所在的page frame
struct page *page = virt_to_page(x);
// 所在compound page的head page
return compound_head(page);}
size_t __ksize(const void *objp) {
struct kmem_cache *c= virt_to_cache(objp);
size_t size = c ? c->object_size : 0;}

文章转载自术道经纬,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




