Chinaunix首页 | 论坛 | 博客
  • 博客访问: 379596
  • 博文数量: 87
  • 博客积分: 983
  • 博客等级: 准尉
  • 技术积分: 685
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-25 07:20
文章分类

全部博文(87)

文章存档

2016年(1)

2015年(3)

2014年(55)

2013年(13)

2012年(15)

分类: LINUX

2014-07-11 16:00:27

 

    本节介绍如何将对象释放回slub分配器。

 

kmem_cache_free

 

void kmem_cache_free(struct kmem_cache *s, void *x)

{

       struct page *page;

       /* 获得对象所在slab的首页 */

       page = virt_to_head_page(x);

       /* 释放一个对象给slab_RET_IP_为调用函数地址 */

       slab_free(s, page, x, _RET_IP_);

 

       trace_kmem_cache_free(_RET_IP_, x);

}

 

slab_free

    释放一个对象。

    参数:

1)        scache指针。

2)        page:待释放对象所在slab的首页。

3)        x:待释放对象指针

4)        addr:最初调用函数的地址

 

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;

       unsigned long flags;

 

       slab_free_hook(s, x);

 

       local_irq_save(flags);

       c = __this_cpu_ptr(s->cpu_slab);

 

       slab_free_hook_irq(s, x);

 

       if (likely(page == c->page && c->node != NUMA_NO_NODE)) {

/* 如果对象所在slab即本cpu local slab,走快速路径,释放到cpu freelist中。与slabfreelist无关,参见__slab_alloc */

              set_freepointer(s, object, c->freelist);

              /* 更新freelist指针,指向刚释放的对象 */

              c->freelist = object;

              stat(s, FREE_FASTPATH);

       } else

              /* 慢速路径释放 */

              __slab_free(s, page, x, addr);

 

       local_irq_restore(flags);

}

 

 __slab_free

    待释放对象所在slab并不是本cpulocal slab时,走慢速路径释放,

static void __slab_free(struct kmem_cache *s, struct page *page,

                     void *x, unsigned long addr)

{

       void *prior;

       void **object = (void *)x;

 

       stat(s, FREE_SLOWPATH);

       slab_lock(page);

 

       if (kmem_cache_debug(s))

              goto debug;

 

checks_ok:

       /* 放回所在slab freelist链表头部 */

       prior = page->freelist;

       /* 待释放对象的下一对象指针指向原freelist */

       set_freepointer(s, object, prior);

       /* freelist指向待释放的对象 */

       page->freelist = object;

       /* 已分配对象数减一 */

       page->inuse--;

/* slab是否是冻结的。该slab有可能是其他cpulocal slab,这种情况下,不能执行后面的语句将local slab添加进部分满slab */

       if (unlikely(PageSlubFrozen(page))) {

              stat(s, FREE_FROZEN);

              goto out_unlock;

       }

/* inuse 0,又不是local slab,说明slab中全部是空闲对象,并且在部分满slab链表上(slab只有一个对象时,在满slab链上)。*/

       if (unlikely(!page->inuse))

              goto slab_empty;

 

       /*

        * Objects left in the slab. If it was not on the partial list before

        * then add it.

        */

       /* 如果slab原本是满slab,现在释放了一个,加入部分满slab */

if (unlikely(!prior)) {

              add_partial(get_node(s, page_to_nid(page)), page, 1);

              stat(s, FREE_ADD_PARTIAL);

       }

 

out_unlock:

       slab_unlock(page);

       return;

 

slab_empty:

       if (prior) {

              /*

               * Slab still on the partial list.

               */

/* prior不为空时,说明slab在部分满slab链表上。prior为空时,说明slab只有一个对象,在满slab链上 */

              remove_partial(s, page);

              stat(s, FREE_REMOVE_PARTIAL);

       }

       slab_unlock(page);

       stat(s, FREE_SLAB);

/* 废除slabslub没有空slab链,slab一旦为空,马上销毁。(这点与去解冻slab时不同,参见unfreeze_slab */

       discard_slab(s, page);

       return;

 

debug:

       if (!free_debug_processing(s, page, x, addr))

              goto out_unlock;

       goto checks_ok;

}

 

阅读(858) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~