Chinaunix首页 | 论坛 | 博客
  • 博客访问: 169214
  • 博文数量: 50
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 123
  • 用 户 组: 普通用户
  • 注册时间: 2013-11-01 16:03
文章分类

全部博文(50)

文章存档

2016年(3)

2015年(5)

2014年(35)

2013年(7)

我的朋友

分类: LINUX

2014-04-04 11:54:48

销毁一个cache节点。通常这只发生在卸载module时。

 

kmem_cache_destroy

销毁一个cache节点。

void kmem_cache_destroy(struct kmem_cache *cachep)

{

       BUG_ON(!cachep || in_interrupt());

 

       /* Find the cache in the chain of caches. */

       get_online_cpus();

       mutex_lock(&cache_chain_mutex);

       /*

        * the chain is never empty, cache_cache is never destroyed

        */

       /* cache节点从cache_chain链表中摘除 */

       list_del(&cachep->next);

      /* 释放空slab链中的slab,并检查其他两个链表。在销毁cache前,必须先销毁其中的slab */

       if (__cache_shrink(cachep)) {

                      /* slab链或部分满slab链不为空 */

                      slab_error(cachep, "Can't free all objects");

                      /* cache非空,重新加入到cache_chain链表中 */

                      list_add(&cachep->next, &cache_chain);

                      mutex_unlock(&cache_chain_mutex);

                      put_online_cpus();

                      return;

       }

 

       if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))

                      rcu_barrier();

 

       __kmem_cache_destroy(cachep);

       mutex_unlock(&cache_chain_mutex);

       put_online_cpus();

}

 

 __cache_shrink

释放空slab链表中的slab

static int __cache_shrink(struct kmem_cache *cachep)

{

       int ret = 0, i = 0;

       struct kmem_list3 *l3;

       /* 释放local cache中对象 */

       drain_cpu_caches(cachep);

 

       check_irq_on();

       for_each_online_node(i) {

                      l3 = cachep->nodelists[i];

                      if (!l3)

                                    continue;

                      /* 释放空slab链表中的slab */

                      drain_freelist(cachep, l3, l3->free_objects);

                      /* 检查满slab链表和部分满slab链表中是否还有slab */

                      ret += !list_empty(&l3->slabs_full) ||

                                    !list_empty(&l3->slabs_partial);

       }

       return (ret ? 1 : 0);

}

 

drain_cpu_caches

释放local cacheshared local cache中的对象。

static void drain_cpu_caches(struct kmem_cache *cachep)

{

       struct kmem_list3 *l3;

       int node;

       /* 释放每个cpu local cache中的对象 */

       on_each_cpu(do_drain, cachep, 1);

       check_irq_on();

       /* NUMA相关 */

       for_each_online_node(node) {

                      l3 = cachep->nodelists[node];

                      if (l3 && l3->alien)

                                    drain_alien_cache(cachep, l3->alien);

       }

       /* 释放shared local cache中的对象 */

       for_each_online_node(node) {

                      l3 = cachep->nodelists[node];

                      if (l3)

                                    drain_array(cachep, l3, l3->shared, 1, node);

       }

}

 

do_drain

释放local cache中的对象。

static void do_drain(void *arg)

{

       struct kmem_cache *cachep = arg;

       struct array_cache *ac;

       int node = numa_mem_id();

 

       check_irq_off();

       /* 获得本cpulocal cache */

       ac = cpu_cache_get(cachep);

       spin_lock(&cachep->nodelists[node]->list_lock);

       /* 释放local cache中的对象 */

       free_block(cachep, ac->entry, ac->avail, node);

       spin_unlock(&cachep->nodelists[node]->list_lock);

       ac->avail = 0;

}

 

drain_array

释放local cache中一定数目的对象。

void drain_array(struct kmem_cache *cachep, struct kmem_list3 *l3,

                                     struct array_cache *ac, int force, int node)

{

       int tofree;

 

       if (!ac || !ac->avail)

                      return;

       if (ac->touched && !force) {

                      ac->touched = 0;

       } else {

                      spin_lock_irq(&l3->list_lock);

                      if (ac->avail) {

                                    /* 计算释放对象的数目 */

                                    tofree = force ? ac->avail : (ac->limit + 4) / 5;

                                    if (tofree > ac->avail)

                                                  tofree = (ac->avail + 1) / 2;

                                    /* 释放对象,从entry前面开始 */

                                    free_block(cachep, ac->entry, tofree, node);

                                    ac->avail -= tofree;

                                    /* 后面的对象前移 */

                                    memmove(ac->entry, &(ac->entry[tofree]),

                                                  sizeof(void *) * ac->avail);

                      }

                      spin_unlock_irq(&l3->list_lock);

       }

}

 

drain_freelist

销毁空slab链表中的slab

static int drain_freelist(struct kmem_cache *cache,

                                    struct kmem_list3 *l3, int tofree)

{

       struct list_head *p;

       int nr_freed;

       struct slab *slabp;

 

       nr_freed = 0;

       /* 释放空slab链表中的slab */

       while (nr_freed < tofree && !list_empty(&l3->slabs_free)) {

 

                      spin_lock_irq(&l3->list_lock);

                      p = l3->slabs_free.prev;

                      if (p == &l3->slabs_free) {

                                    spin_unlock_irq(&l3->list_lock);

                                    goto out;

                      }

 

                      slabp = list_entry(p, struct slab, list);

#if DEBUG

                      BUG_ON(slabp->inuse);

#endif

                      /* slab从空slab链表中摘除 */

                      list_del(&slabp->list);

                      /*

                       * Safe to drop the lock. The slab is no longer linked

                       * to the cache.

                       */

                      /* 总空闲对象数减去每个slab中对象数 */

                      l3->free_objects -= cache->num;

                      spin_unlock_irq(&l3->list_lock);

                      /* 销毁slab,包括slab管理对象和slab对象 */

                      slab_destroy(cache, slabp);

                      nr_freed++;

       }

out:

       return nr_freed;

}

 

__kmem_cache_destroy

 

static void __kmem_cache_destroy(struct kmem_cache *cachep)

{

       int i;     

       struct kmem_list3 *l3;

       /* 释放每个cpu local cache使用的struct array_cache对象,注意此时是online cpu cpu如果是down

      态,并没有释放 */

       for_each_online_cpu(i)

           kfree(cachep->array[i]);

 

       /* NUMA: free the list3 structures */

       for_each_online_node(i) {

                      l3 = cachep->nodelists[i];

                      if (l3) {

                                    /* 释放shared local cache使用的struct array_cache对象 */

                                    kfree(l3->shared);

                                    free_alien_cache(l3->alien);

                                    kfree(l3);

                      }

       }

       /* 释放cache节点使用的struct kmem_cache对象 */

       kmem_cache_free(&cache_cache, cachep);

}

 

 

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