作者:永远在等一个人--嘉儿 | 来源:互联网 | 2023-07-18 13:52
do_slab_free一、快速路径if(likely(pagec-page)){void**freelistREAD_ONCE(c-freelist);set_freep
do_slab_free
一、快速路径
if (likely(page == c->page)) {void **freelist = READ_ONCE(c->freelist);set_freepointer(s, tail_obj, freelist);if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,freelist, tid,head, next_tid(tid)))) {note_cmpxchg_failure("slab_free", s, tid);goto redo;}stat(s, FREE_FASTPATH);
} else__slab_free(s, page, head, tail_obj, cnt, addr);
1、要释放的对象正好在cpu本地缓存中;
2、set_freepointer函数:将要释放的object加入到空闲的object链表中,并且为链表中代替freelist为第一个空闲的object,即相当于object->next = c->freelist;
3、重新分配freelist,这里是将c->freelist = head(head即目标object);
二、慢速路径
进入__slab_free函数,大致框架如下:
do {if (unlikely(n)) {spin_unlock_irqrestore(&n->list_lock, flags);n = NULL;}prior = page->freelist;counters = page->counters;set_freepointer(s, tail, prior);new.counters = counters;was_frozen = new.frozen;new.inuse -= cnt;if ((!new.inuse || !prior) && !was_frozen) { if (kmem_cache_has_cpu_partial(s) && !prior) { new.frozen = 1;} else { n = get_node(s, page_to_nid(page));spin_lock_irqsave(&n->list_lock, flags);}
} while (!cmpxchg_double_slab(s, page,prior, counters,head, new.counters,"__slab_free"));
if (likely(!n)) {if (new.frozen && !was_frozen) { put_cpu_partial(s, page, 1);stat(s, CPU_PARTIAL_FREE);}if (was_frozen) stat(s, FREE_FROZEN);return;
}
if (unlikely(!new.inuse && n->nr_partial >= s->min_partial))goto slab_empty;
if (!kmem_cache_has_cpu_partial(s) && unlikely(!prior)) {remove_full(s, n, page);add_partial(n, page, DEACTIVATE_TO_TAIL);stat(s, FREE_ADD_PARTIAL);
}
spin_unlock_irqrestore(&n->list_lock, flags);
return;
slab_empty:if (prior) {remove_partial(n, page);stat(s, FREE_REMOVE_PARTIAL);} else {remove_full(s, n, page);}spin_unlock_irqrestore(&n->list_lock, flags);stat(s, FREE_SLAB);discard_slab(s, page);
}
所以从代码来看,主要分成以下几种情况:
1、目标object在s->slab_cpu->partital中,直接释放即可,无需后续的处理;
2、目标object在s->node中,释放完object后slab中的object全为free;此时需要考虑空的slab如何处理
(1)s->node->partital中slab的个数大于等于min_partital时,将该slab释放到伙伴系统;
(2)s->node->partital中slab的个数小于min_partital时,该slab依然保留在s->node->partital链表中;
3、目标object在s->node中,释放object前slab为full,没有可分配object,释放完后为半满状态;此时需要将半满的slab从full链表中删除并加入到s->slab_cpu的链表中,需要注意s->slab_cpu->partital中也需要判断下所有的free的object的数量是否超过了规定的水位,判断后在决定是否加入;
lab从full链表中删除并加入到s->slab_cpu的链表中,需要注意s->slab_cpu->partital中也需要判断下所有的free的object的数量是否超过了规定的水位,判断后在决定是否加入;