《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); }
发表评论