Linux Slob分配器(三)--释放对象

水平有限,描述不当之处还请指出,转载请注明出处http://blog.csdn.net/vanbreaker/article/details/7705792


slob释放对象由函数slob_free()来完成,分为三种情况进行处理:

  • slob中已有的空闲单元加上释放对象块的空闲单元正好等于一个空闲的page,那么将直接将该page释放回伙伴系统
  • slob中已无空闲单元,那么这次释放将更新slob的信息
  • 普通情况,即slob处于部分满状态,那么更新slob的信息的同时还要将释放的块插入到相应的位置,要注意插入后是否能和相邻块进行合并!

下面来看具体的代码

/*
 * 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);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值