Linux SLUB分配器之三(释放对象的代码分析)

来源:互联网 发布:js取小数点前面的数字 编辑:程序博客网 时间:2024/05/22 13:55

void kfree(constvoid *x)

{

       structpage *page;

       if(unlikely(ZERO_OR_NULL_PTR(x)))

              return;

       page = virt_to_head_page(x);/*注意,对于SLAB而言,假设这个SLAB有多个Page,则除首Page之外的其它的所有Page都通过其first_page成员指向首Page(见Page数据结构) ,故而这里就得到该SLAB的首Page*/

       if(unlikely(!PageSlab(page))) {

              put_page(page);

              return;

       }

       slab_free(page->slab, page, (void *)x,__builtin_return_address(0));

}

 

static void__always_inline slab_free(struct kmem_cache *s,

                     struct page *page, void *x,void *addr)

{

       void**object = (void *)x;

       unsignedlong flags;

       structkmem_cache_cpu *c;

 

       local_irq_save(flags);

       debug_check_no_locks_freed(object,s->objsize);

       c =get_cpu_slab(s, smp_processor_id());

       if (likely(page == c->page &&c->node >= 0)) {/*如果释放的对象在当前的SLAB上,就直接放到kmem_cache->cpu_slab->freelist*/

              object[c->offset]= c->freelist;

              c->freelist= object;

       } else

              __slab_free(s,page, x, addr, c->offset);

 

       local_irq_restore(flags);

}

 

static void__slab_free(struct kmem_cache *s, struct page *page,

                            void *x, void *addr,unsigned int offset)

{

       void*prior;

       void**object = (void *)x;

       slab_lock(page);

       if(unlikely(SlabDebug(page)))

              gotodebug;

checks_ok:

       prior = object[offset] =page->freelist;/*这里请注意,page为该object所在的SLAB的首Page,同时,此SLAB不是当前的SLAB,故而释放的对象不能放到kmem_cache->cpu_slab->freelist里,而需要放到该首Pagefreelist结构里,见3.2节的分析;同时,另一点很重要,如果这里priorNULL,则说明此前此SLAB上的对象已经被分配光了,即此SLABdeactivate了,故而后面要把该SLAB加入到Partial链表里*/

       page->freelist= object;

       page->inuse--;/*因为是放到了Pagefreelist里,故而在使用的对象计数要减1*/

       if(unlikely(SlabFrozen(page)))

              gotoout_unlock;

       if (unlikely(!page->inuse))/*SLAB上的对象已经都被释放了,即都是空闲对象了,且该SLAB不是当前SLAB,这样,这个SLAB所占用的空间就可以释放给系统了*/

              goto slab_empty;

       /*

        * Objects left in the slab. If it

        * was not on the partial list before

        * then add it.

        */

       if (unlikely(!prior))

              add_partial_tail(get_node(s,page_to_nid(page)), page);/* 此前此SLAB上的对象已经被分配光了,即此SLABdeactivate了,故而后面要把该SLAB加入到Partial链表里 */

out_unlock:

       slab_unlock(page);

       return;

slab_empty:

       if(prior)

              /*

               * Slab still on the partial list.

               */

              remove_partial(s, page);

       slab_unlock(page);

       discard_slab(s, page);/* 释放给系统*/

       return;

debug:

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

              gotoout_unlock;

       gotochecks_ok;

}