slab_free

此文章以slub分配器原理作为理论知识,通过阅读 linux kernel 2.6.34 源码来理解slub分配器具体实现

简介

slab_free()是slub分配器释放object的具体实现

分析源码

slab_free()定义,如下:

/* mm/slub.c */
static __always_inline void slab_free(struct kmem_cache *s,
            struct page *page, void *x, unsigned long addr)
{
    void **object = (void *)x;
    struct kmem_cache_cpu *c;

    c = __this_cpu_ptr(s->cpu_slab);
    if (likely(page == c->page && c->node >= 0)) {
        set_freepointer(s, object, c->freelist);
        c->freelist = object;
        stat(s, FREE_FASTPATH);
    } else
        __slab_free(s, page, x, addr);
}

判断参数page是否等于kmem_cache_cpu结构体的page,如果是,直接把object释放到page对应的slab中;否则,调用__slab_free()

__slab_free()定义,如下:

/* mm/slub.c */
static void __slab_free(struct kmem_cache *s, struct page *page,
            void *x, unsigned long addr)
{
    void *prior;
    void **object = (void *)x;

checks_ok:
    prior = page->freelist;
    set_freepointer(s, object, prior);
    page->freelist = object;
    page->inuse--;

    if (unlikely(PageSlubFrozen(page))) {
        goto out_unlock;
    }

    if (unlikely(!page->inuse))
        goto slab_empty;

    if (unlikely(!prior)) {
        add_partial(get_node(s, page_to_nid(page)), page, 1);
    }

out_unlock:
    return;

slab_empty:
    if (prior) {
        remove_partial(s, page);
    }
    discard_slab(s, page);
    return;
}

进入此函数中,说明object处于partial链表 或 full链表中

先把object释放到page对应的slab中, 通过PageSlubFrozen()判断page对应的slab中是否还有object被使用?如果是,跳转到 out_unlock,直接返回

否则,继续判断page对应的slab是否为空?如果为空,跳转到 slab_empty,通过remove_partial()将page对应的slab从partial链表中删除, 再调用discard_slab() -> free_slab() -> __free_slab() -> __free_pages()释放page对应的slab,最后返回

否则,继续判断prior是否为NULL?如果为NULL,说明page对应的slab在full链表中,因为释放了一个object后,需要通过add_partial()将page对应的slab添加到patial链表中,最后返回

Last updated

Was this helpful?