free_bootmem_node

假如内存的物理起始地址为:0x30000000, 大小为:0x1000000

void __init free_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,
			      unsigned long size)
{
	unsigned long start, end;

	//空函数
	kmemleak_free_part(__va(physaddr), size);

	start = PFN_UP(physaddr);  //=0x30000
	end = PFN_DOWN(physaddr + size); //=0x31000

	mark_bootmem_node(pgdat->bdata, start, end, 0, 0);
}


#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
PFN_UP()返回大于 x 的第 1 个页面号
PFN_DOWN()返回小于 x 的第 1 个页面号


那么:
start = PFN_UP(physaddr) = 0x30000
end = PFN_DOWN(physaddr + size) = 0x31000
然后调用mark_bootmem_node函数

static int __init mark_bootmem_node(bootmem_data_t *bdata,
				unsigned long start, unsigned long end,
				int reserve, int flags)
{
	unsigned long sidx, eidx;

	bdebug("nid=%td start=%lx end=%lx reserve=%d flags=%x\n",
		bdata - bootmem_node_data, start, end, reserve, flags);

	BUG_ON(start < bdata->node_min_pfn);
	BUG_ON(end > bdata->node_low_pfn);

	sidx = start - bdata->node_min_pfn;//sidx=0x0 eidx=0x1000
	eidx = end - bdata->node_min_pfn;//sidx=0x0 eidx=0x1000

	if (reserve)
		return __reserve(bdata, sidx, eidx, flags);
	else
		__free(bdata, sidx, eidx);
	return 0;
}

先看一下传进来的参数值:
bdata->node_min_pfn = 0x30000
bdata->node_low_pfn = 0x31000
bdata->node_bootmem_map = 0xc0431000
start = 0x30000
end = 0x31000
reserve = 0
flags = 0
根据上面的参数值可以计算出:
sidx = start - bdata->node_min_pfn = 0x30000 - 0x30000 = 0
eidx = end - bdata->node_min_pfn = 0x31000 - 0x30000 = 0x1000
最后调用__free函数

static void __init __free(bootmem_data_t *bdata,
			unsigned long sidx, unsigned long eidx)
{
	unsigned long idx;

	bdebug("nid=%td start=%lx end=%lx\n", bdata - bootmem_node_data,
		sidx + bdata->node_min_pfn,
		eidx + bdata->node_min_pfn);

	if (bdata->hint_idx > sidx)
		bdata->hint_idx = sidx;

	for (idx = sidx; idx < eidx; idx++)
		if (!test_and_clear_bit(idx, bdata->node_bootmem_map))
			BUG();
}
先看一下传进来的参数值:
bdata->node_min_pfn = 0x30000
bdata->node_low_pfn = 0x31000
bdata->node_bootmem_map = 0xc0431000
sidx = 0
eidx = 0x1000[4096]
而bdata->hint_idx还没有被赋过值,所以值为0
然后就开始for循环

for (idx = 0; idx < 4096; idx++) {
	test_and_clear_bit(idx, 0xc0431000);
}


#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)

#define	ATOMIC_BITOP_BE(name,nr,p)		\
	(__builtin_constant_p(nr) ?		\
	 ____atomic_##name(nr, p) :		\
	 _##name##_be(nr,p))

static inline int
____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long flags;
	unsigned int res;
	unsigned long mask = 1UL << (bit & 31);

	p += bit >> 5;

	raw_local_irq_save(flags);
	res = *p;
	*p = res & ~mask;
	raw_local_irq_restore(flags);

	return (res & mask) != 0;
}
我们先来看一下bit取0 ~ 31之间的时候的情况
bit mask(二进制表示)
0 1
1 10
2 100
. .
. .
. .
31 1000...0[31个0]


而 bit >> 5 在0~31时为0, 32~63时为1 ...依次类推
也即说明这是进行位操作
然后关中断
保存地址p中原有的值
然后清0相应的位
开中断


____atomic_test_and_clear_bit函数的主要作用:
把相应的位清0




所以当上面的函数操作完成后,地址bdata->node_bootmem_map = 0xc0431000处的512个字节的数据又重新被赋值为0,
表示所有的内存都是空闲[free]的


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值