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

void kfree(const void *x)

{

       struct page *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;

       unsigned long flags;

       struct kmem_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)))

              goto debug;

checks_ok:

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

       page->freelist = object;

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

       if (unlikely(SlabFrozen(page)))

              goto out_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 上的对象已经被分配光了,即此 SLAB deactivate 了,故而后面要把该 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))

              goto out_unlock;

       goto checks_ok;

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值