⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bootmem.c

📁 最新最稳定的Linux内存管理模块源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * @pgdat: node the range resides on * @physaddr: starting address of the range * @size: size of the range in bytes * @flags: reservation flags (see linux/bootmem.h) * * Partial pages will be reserved. * * The range must reside completely on the specified node. */int __init reserve_bootmem_node(pg_data_t *pgdat, unsigned long physaddr,				 unsigned long size, int flags){	unsigned long start, end;	start = PFN_DOWN(physaddr);	end = PFN_UP(physaddr + size);	return mark_bootmem_node(pgdat->bdata, start, end, 1, flags);}#ifndef CONFIG_HAVE_ARCH_BOOTMEM_NODE/** * reserve_bootmem - mark a page range as usable * @addr: starting address of the range * @size: size of the range in bytes * @flags: reservation flags (see linux/bootmem.h) * * Partial pages will be reserved. * * The range must be contiguous but may span node boundaries. */int __init reserve_bootmem(unsigned long addr, unsigned long size,			    int flags){	unsigned long start, end;	start = PFN_DOWN(addr);	end = PFN_UP(addr + size);	return mark_bootmem(start, end, 1, flags);}#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */static unsigned long align_idx(struct bootmem_data *bdata, unsigned long idx,			unsigned long step){	unsigned long base = bdata->node_min_pfn;	/*	 * Align the index with respect to the node start so that the	 * combination of both satisfies the requested alignment.	 */	return ALIGN(base + idx, step) - base;}static unsigned long align_off(struct bootmem_data *bdata, unsigned long off,			unsigned long align){	unsigned long base = PFN_PHYS(bdata->node_min_pfn);	/* Same as align_idx for byte offsets */	return ALIGN(base + off, align) - base;}static void * __init alloc_bootmem_core(struct bootmem_data *bdata,				unsigned long size, unsigned long align,				unsigned long goal, unsigned long limit){	unsigned long fallback = 0;	unsigned long min, max, start, sidx, midx, step;	bdebug("nid=%td size=%lx [%lu pages] align=%lx goal=%lx limit=%lx\n",		bdata - bootmem_node_data, size, PAGE_ALIGN(size) >> PAGE_SHIFT,		align, goal, limit);	BUG_ON(!size);	BUG_ON(align & (align - 1));	BUG_ON(limit && goal + size > limit);	if (!bdata->node_bootmem_map)		return NULL;	min = bdata->node_min_pfn;	max = bdata->node_low_pfn;	goal >>= PAGE_SHIFT;	limit >>= PAGE_SHIFT;	if (limit && max > limit)		max = limit;	if (max <= min)		return NULL;	step = max(align >> PAGE_SHIFT, 1UL);	if (goal && min < goal && goal < max)		start = ALIGN(goal, step);	else		start = ALIGN(min, step);	sidx = start - bdata->node_min_pfn;	midx = max - bdata->node_min_pfn;	if (bdata->hint_idx > sidx) {		/*		 * Handle the valid case of sidx being zero and still		 * catch the fallback below.		 */		fallback = sidx + 1;		sidx = align_idx(bdata, bdata->hint_idx, step);	}	while (1) {		int merge;		void *region;		unsigned long eidx, i, start_off, end_off;find_block:		sidx = find_next_zero_bit(bdata->node_bootmem_map, midx, sidx);		sidx = align_idx(bdata, sidx, step);		eidx = sidx + PFN_UP(size);		if (sidx >= midx || eidx > midx)			break;		for (i = sidx; i < eidx; i++)			if (test_bit(i, bdata->node_bootmem_map)) {				sidx = align_idx(bdata, i, step);				if (sidx == i)					sidx += step;				goto find_block;			}		if (bdata->last_end_off & (PAGE_SIZE - 1) &&				PFN_DOWN(bdata->last_end_off) + 1 == sidx)			start_off = align_off(bdata, bdata->last_end_off, align);		else			start_off = PFN_PHYS(sidx);		merge = PFN_DOWN(start_off) < sidx;		end_off = start_off + size;		bdata->last_end_off = end_off;		bdata->hint_idx = PFN_UP(end_off);		/*		 * Reserve the area now:		 */		if (__reserve(bdata, PFN_DOWN(start_off) + merge,				PFN_UP(end_off), BOOTMEM_EXCLUSIVE))			BUG();		region = phys_to_virt(PFN_PHYS(bdata->node_min_pfn) +				start_off);		memset(region, 0, size);		return region;	}	if (fallback) {		sidx = align_idx(bdata, fallback - 1, step);		fallback = 0;		goto find_block;	}	return NULL;}static void * __init ___alloc_bootmem_nopanic(unsigned long size,					unsigned long align,					unsigned long goal,					unsigned long limit){	bootmem_data_t *bdata;restart:	list_for_each_entry(bdata, &bdata_list, list) {		void *region;		if (goal && bdata->node_low_pfn <= PFN_DOWN(goal))			continue;		if (limit && bdata->node_min_pfn >= PFN_DOWN(limit))			break;		region = alloc_bootmem_core(bdata, size, align, goal, limit);		if (region)			return region;	}	if (goal) {		goal = 0;		goto restart;	}	return NULL;}/** * __alloc_bootmem_nopanic - allocate boot memory without panicking * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * Returns NULL on failure. */void * __init __alloc_bootmem_nopanic(unsigned long size, unsigned long align,					unsigned long goal){	return ___alloc_bootmem_nopanic(size, align, goal, 0);}static void * __init ___alloc_bootmem(unsigned long size, unsigned long align,					unsigned long goal, unsigned long limit){	void *mem = ___alloc_bootmem_nopanic(size, align, goal, limit);	if (mem)		return mem;	/*	 * Whoops, we cannot satisfy the allocation request.	 */	printk(KERN_ALERT "bootmem alloc of %lu bytes failed!\n", size);	panic("Out of memory");	return NULL;}/** * __alloc_bootmem - allocate boot memory * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * The function panics if the request can not be satisfied. */void * __init __alloc_bootmem(unsigned long size, unsigned long align,			      unsigned long goal){	return ___alloc_bootmem(size, align, goal, 0);}static void * __init ___alloc_bootmem_node(bootmem_data_t *bdata,				unsigned long size, unsigned long align,				unsigned long goal, unsigned long limit){	void *ptr;	ptr = alloc_bootmem_core(bdata, size, align, goal, limit);	if (ptr)		return ptr;	return ___alloc_bootmem(size, align, goal, limit);}/** * __alloc_bootmem_node - allocate boot memory from a specific node * @pgdat: node to allocate from * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may fall back to any node in the system if the specified node * can not hold the requested memory. * * The function panics if the request can not be satisfied. */void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size,				   unsigned long align, unsigned long goal){	return ___alloc_bootmem_node(pgdat->bdata, size, align, goal, 0);}#ifdef CONFIG_SPARSEMEM/** * alloc_bootmem_section - allocate boot memory from a specific section * @size: size of the request in bytes * @section_nr: sparse map section to allocate from * * Return NULL on failure. */void * __init alloc_bootmem_section(unsigned long size,				    unsigned long section_nr){	bootmem_data_t *bdata;	unsigned long pfn, goal, limit;	pfn = section_nr_to_pfn(section_nr);	goal = pfn << PAGE_SHIFT;	limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;	bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];	return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);}#endifvoid * __init __alloc_bootmem_node_nopanic(pg_data_t *pgdat, unsigned long size,				   unsigned long align, unsigned long goal){	void *ptr;	ptr = alloc_bootmem_core(pgdat->bdata, size, align, goal, 0);	if (ptr)		return ptr;	return __alloc_bootmem_nopanic(size, align, goal);}#ifndef ARCH_LOW_ADDRESS_LIMIT#define ARCH_LOW_ADDRESS_LIMIT	0xffffffffUL#endif/** * __alloc_bootmem_low - allocate low boot memory * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may happen on any node in the system. * * The function panics if the request can not be satisfied. */void * __init __alloc_bootmem_low(unsigned long size, unsigned long align,				  unsigned long goal){	return ___alloc_bootmem(size, align, goal, ARCH_LOW_ADDRESS_LIMIT);}/** * __alloc_bootmem_low_node - allocate low boot memory from a specific node * @pgdat: node to allocate from * @size: size of the request in bytes * @align: alignment of the region * @goal: preferred starting address of the region * * The goal is dropped if it can not be satisfied and the allocation will * fall back to memory below @goal. * * Allocation may fall back to any node in the system if the specified node * can not hold the requested memory. * * The function panics if the request can not be satisfied. */void * __init __alloc_bootmem_low_node(pg_data_t *pgdat, unsigned long size,				       unsigned long align, unsigned long goal){	return ___alloc_bootmem_node(pgdat->bdata, size, align,				goal, ARCH_LOW_ADDRESS_LIMIT);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -