|
@@ -1063,6 +1063,15 @@ static bool bulkfree_pcp_prepare(struct page *page)
|
|
|
}
|
|
|
#endif /* CONFIG_DEBUG_VM */
|
|
|
|
|
|
+static inline void prefetch_buddy(struct page *page)
|
|
|
+{
|
|
|
+ unsigned long pfn = page_to_pfn(page);
|
|
|
+ unsigned long buddy_pfn = __find_buddy_pfn(pfn, 0);
|
|
|
+ struct page *buddy = page + (buddy_pfn - pfn);
|
|
|
+
|
|
|
+ prefetch(buddy);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Frees a number of pages from the PCP lists
|
|
|
* Assumes all pages on list are in same zone, and of same order.
|
|
@@ -1079,6 +1088,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
|
|
|
{
|
|
|
int migratetype = 0;
|
|
|
int batch_free = 0;
|
|
|
+ int prefetch_nr = 0;
|
|
|
bool isolated_pageblocks;
|
|
|
struct page *page, *tmp;
|
|
|
LIST_HEAD(head);
|
|
@@ -1114,6 +1124,18 @@ static void free_pcppages_bulk(struct zone *zone, int count,
|
|
|
continue;
|
|
|
|
|
|
list_add_tail(&page->lru, &head);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We are going to put the page back to the global
|
|
|
+ * pool, prefetch its buddy to speed up later access
|
|
|
+ * under zone->lock. It is believed the overhead of
|
|
|
+ * an additional test and calculating buddy_pfn here
|
|
|
+ * can be offset by reduced memory latency later. To
|
|
|
+ * avoid excessive prefetching due to large count, only
|
|
|
+ * prefetch buddy for the first pcp->batch nr of pages.
|
|
|
+ */
|
|
|
+ if (prefetch_nr++ < pcp->batch)
|
|
|
+ prefetch_buddy(page);
|
|
|
} while (--count && --batch_free && !list_empty(list));
|
|
|
}
|
|
|
|