好记性不如铅笔头

kernel, linux, 操作系统

Linux每CPU页框高速缓存简单笔记

《ULK》中P317页讲解了每CPU高速缓存,这里作者也简单的注释下代码。

page_alloc.c部分内容:

/*
 * Really, prep_compound_page() should be called from __rmqueue_bulk().  But
 * we cheat by calling it from here, in the order > 0 path.  Saves a branch
 * or two.
 */
static struct page *
buffered_rmqueue(struct zone *zone, int order, int gfp_flags)
{
	unsigned long flags;
	struct page *page = NULL;
	int cold = !!(gfp_flags & __GFP_COLD);

/*
如果是申请一个页大小的内存空间(2^0=1),那么就从每CPU告诉缓存中去找
*/
	if (order == 0) {
		struct per_cpu_pages *pcp;
		/*找到当前CPU对应的每CPU高速缓存,然后根据热冷找到对应的数组
		*/
		pcp = &zone->pageset[get_cpu()].pcp[cold];
		local_irq_save(flags);
		/*根据 ULK P317 讲解,当CPU高速缓存用尽时,就申请新的补充进去*/
		if (pcp->count <= pcp->low)
			pcp->count += rmqueue_bulk(zone, 0,
						pcp->batch, &pcp->list);
		/*申请一个页,然后返回*/
		if (pcp->count) {
			page = list_entry(pcp->list.next, struct page, lru);
			list_del(&page->lru);
			pcp->count--;
		}
		local_irq_restore(flags);
		put_cpu();
	}

	if (page == NULL) {
		spin_lock_irqsave(&zone->lock, flags);
		page = __rmqueue(zone, order);
		spin_unlock_irqrestore(&zone->lock, flags);
	}

	if (page != NULL) {
		BUG_ON(bad_range(zone, page));
		mod_page_state_zone(zone, pgalloc, 1 << order);
		prep_new_page(page, order);

		if (gfp_flags & __GFP_ZERO)
			prep_zero_page(page, order, gfp_flags);

		if (order && (gfp_flags & __GFP_COMP))
			prep_compound_page(page, order);
	}
	return page;
}


/*
 * Free a 0-order page
 */
 /*释放一个高速缓存页*/
static void FASTCALL(free_hot_cold_page(struct page *page, int cold));
static void fastcall free_hot_cold_page(struct page *page, int cold)
{
	struct zone *zone = page_zone(page);
	struct per_cpu_pages *pcp;
	unsigned long flags;

	arch_free_page(page, 0);

	kernel_map_pages(page, 1, 0);
	inc_page_state(pgfree);
	if (PageAnon(page))
		page->mapping = NULL;
	free_pages_check(__FUNCTION__, page);

	/* 根据该高速缓存页的信息,获取对应的高速缓存管理指针 */
	
	pcp = &zone->pageset[get_cpu()].pcp[cold];
	local_irq_save(flags);
	/* 如果该CPU高速缓存数量太多了,就释放一部分 */
	if (pcp->count >= pcp->high)
		pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
	list_add(&page->lru, &pcp->list);
	pcp->count++;
	local_irq_restore(flags);
	put_cpu();
}

void fastcall free_hot_page(struct page *page)
{
	free_hot_cold_page(page, 0);
}
	
void fastcall free_cold_page(struct page *page)
{
	free_hot_cold_page(page, 1);
}

 

发表评论

3 + 12 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据