水平有限,描述不当之处还请指出,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7705792
slob释放对象由函数slob_free()来完成,分为三种情况进行处理:
- slob中已有的空闲单元加上释放对象块的空闲单元正好等于一个空闲的page,那么将直接将该page释放回伙伴系统
- slob中已无空闲单元,那么这次释放将更新slob的信息
- 普通情况,即slob处于部分满状态,那么更新slob的信息的同时还要将释放的块插入到相应的位置,要注意插入后是否能和相邻块进行合并!
下面来看具体的代码
- <SPAN style="FONT-SIZE: 12px">/*
- * slob_free: entry point into the slob allocator.
- */
- static void slob_free(void *block, int size)
- {
- struct slob_page *sp;
- slob_t *prev, *next, *b = (slob_t *)block;
- slobidx_t units;
- unsigned long flags;
- if (unlikely(ZERO_OR_NULL_PTR(block)))
- return;
- BUG_ON(!size);
- sp = slob_page(block);//获取slob地址
- units = SLOB_UNITS(size);//计算释放的单元数
- spin_lock_irqsave(&slob_lock, flags);
- /*slob剩余的单元数加上待释放的单元数正好等于一个slob本有的总单元数,
- 直接将slob占用的页框释放回伙伴系统*/
- if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
- /* Go directly to page allocator. Do not pass slob allocator */
- if (slob_page_free(sp))
- clear_slob_page_free(sp);
- spin_unlock_irqrestore(&slob_lock, flags);
- clear_slob_page(sp);
- free_slob_page(sp);
- slob_free_pages(b, 0);
- return;
- }
- if (!slob_page_free(sp)) {//slob没有空闲块
- /* This slob page is about to become partially free. Easy! */
- sp->units = units;//设置slob的单元数为释放对象的单元数
- sp->free = b;//设置首对象为释放对象
- set_slob(b, units,//最后一个对象的空闲对象设置为下一个页的首个单元
- (void *)((unsigned long)(b +
- SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
- set_slob_page_free(sp, &free_slob_small);//将slob链入free_slob_small链表
- goto out;
- }
- /*
- * Otherwise the page is already partially free, so find reinsertion
- * point.
- */
- sp->units += units;//空闲单元总数增加units
- if (b < sp->free) {//待释放块的地址小于sp->free
- if (b + units == sp->free) {//可以合并
- units += slob_units(sp->free);
- sp->free = slob_next(sp->free);//取free的下一个空闲对象作为free
- }
- /*将释放块插入在free前面,并将其作为首个空闲块赋给free*/
- set_slob(b, units, sp->free);
- sp->free = b;
- } else {
- prev = sp->free;//取首个空闲块
- next = slob_next(prev);//取第二个空闲块
- while (b > next) {//扫描至待释放块处
- prev = next;
- next = slob_next(prev);
- }
- /*将b插在prev和next中间,prev-->b-->next,要考虑是否能够合并*/
- /*如果prev不是最后一个空闲块并且b可以和next合并,则进行合并*/
- if (!slob_last(prev) && b + units == next) {
- units += slob_units(next);
- set_slob(b, units, slob_next(next));
- } else//否则将b插入在next前面
- set_slob(b, units, next);
- if (prev + slob_units(prev) == b) {//如果prev可以和b合并,则进行合并
- units = slob_units(b) + slob_units(prev);
- set_slob(prev, units, slob_next(b));
- } else//否则,将b插在prev后面
- set_slob(prev, slob_units(prev), b);
- }
- out:
- spin_unlock_irqrestore(&slob_lock, flags);
- }
- </SPAN>
<span style="font-size:12px;">/*
* slob_free: entry point into the slob allocator.
*/
static void slob_free(void *block, int size)
{
struct slob_page *sp;
slob_t *prev, *next, *b = (slob_t *)block;
slobidx_t units;
unsigned long flags;
if (unlikely(ZERO_OR_NULL_PTR(block)))
return;
BUG_ON(!size);
sp = slob_page(block);//获取slob地址
units = SLOB_UNITS(size);//计算释放的单元数
spin_lock_irqsave(&slob_lock, flags);
/*slob剩余的单元数加上待释放的单元数正好等于一个slob本有的总单元数,
直接将slob占用的页框释放回伙伴系统*/
if (sp->units + units == SLOB_UNITS(PAGE_SIZE)) {
/* Go directly to page allocator. Do not pass slob allocator */
if (slob_page_free(sp))
clear_slob_page_free(sp);
spin_unlock_irqrestore(&slob_lock, flags);
clear_slob_page(sp);
free_slob_page(sp);
slob_free_pages(b, 0);
return;
}
if (!slob_page_free(sp)) {//slob没有空闲块
/* This slob page is about to become partially free. Easy! */
sp->units = units;//设置slob的单元数为释放对象的单元数
sp->free = b;//设置首对象为释放对象
set_slob(b, units,//最后一个对象的空闲对象设置为下一个页的首个单元
(void *)((unsigned long)(b +
SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
set_slob_page_free(sp, &free_slob_small);//将slob链入free_slob_small链表
goto out;
}
/*
* Otherwise the page is already partially free, so find reinsertion
* point.
*/
sp->units += units;//空闲单元总数增加units
if (b < sp->free) {//待释放块的地址小于sp->free
if (b + units == sp->free) {//可以合并
units += slob_units(sp->free);
sp->free = slob_next(sp->free);//取free的下一个空闲对象作为free
}
/*将释放块插入在free前面,并将其作为首个空闲块赋给free*/
set_slob(b, units, sp->free);
sp->free = b;
} else {
prev = sp->free;//取首个空闲块
next = slob_next(prev);//取第二个空闲块
while (b > next) {//扫描至待释放块处
prev = next;
next = slob_next(prev);
}
/*将b插在prev和next中间,prev-->b-->next,要考虑是否能够合并*/
/*如果prev不是最后一个空闲块并且b可以和next合并,则进行合并*/
if (!slob_last(prev) && b + units == next) {
units += slob_units(next);
set_slob(b, units, slob_next(next));
} else//否则将b插入在next前面
set_slob(b, units, next);
if (prev + slob_units(prev) == b) {//如果prev可以和b合并,则进行合并
units = slob_units(b) + slob_units(prev);
set_slob(prev, units, slob_next(b));
} else//否则,将b插在prev后面
set_slob(prev, slob_units(prev), b);
}
out:
spin_unlock_irqrestore(&slob_lock, flags);
}
</span>