Messages in this thread Patch in this message | | | Date | Mon, 20 Mar 2006 08:38:36 -0500 | From | "Stone Wang" <> | Subject | [PATCH][8/8] mm: lru interface change |
| |
Add Wired list to LRU. Add PG_Wired bit to page.
Signed-off-by: Shaoping Wang <pwstone@gmail.com>
-- include/linux/mm_inline.h | 25 +++++++++++++ include/linux/mmzone.h | 2 + include/linux/page-flags.h | 9 +++++ include/linux/swap.h | 2 + mm/page_alloc.c | 4 +- mm/swap.c | 81 +++++++++++++++++++++++++++++++++++++-------- 6 files changed, 107 insertions(+), 16 deletions(-)
diff -urN linux-2.6.15.orig/include/linux/mm_inline.h linux-2.6.15/include/linux/mm_inline.h --- linux-2.6.15.orig/include/linux/mm_inline.h 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/include/linux/mm_inline.h 2006-03-07 01:56:10.000000000 -0500 @@ -1,3 +1,9 @@ +/* + * There are 3 per-zone lists in LRU: + * Active: pages which were accessed more frequently. + * Inactive: pages accessed less frequently. + * Wired: pages mlocked by some tasks. + */
static inline void add_page_to_active_list(struct zone *zone, struct page *page) @@ -14,6 +20,13 @@ }
static inline void +add_page_to_wired_list(struct zone *zone, struct page *page) +{ + list_add(&page->lru, &zone->wired_list); + zone->nr_wired++; +} + +static inline void del_page_from_active_list(struct zone *zone, struct page *page) { list_del(&page->lru); @@ -28,10 +41,20 @@ }
static inline void +del_page_from_wired_list(struct zone *zone, struct page *page) +{ + list_del(&page->lru); + zone->nr_wired--; +} + +static inline void del_page_from_lru(struct zone *zone, struct page *page) { list_del(&page->lru); - if (PageActive(page)) { + if(PageWired(page)){ + ClearPageWired(page); + zone->nr_wired--; + } else if (PageActive(page)) { ClearPageActive(page); zone->nr_active--; } else { diff -urN linux-2.6.15.orig/include/linux/mmzone.h linux-2.6.15/include/linux/mmzone.h --- linux-2.6.15.orig/include/linux/mmzone.h 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/include/linux/mmzone.h 2006-03-07 01:58:26.000000000 -0500 @@ -143,10 +143,12 @@ spinlock_t lru_lock; struct list_head active_list; struct list_head inactive_list; + struct list_head wired_list; /* Pages wired. */ unsigned long nr_scan_active; unsigned long nr_scan_inactive; unsigned long nr_active; unsigned long nr_inactive; + unsigned long nr_wired; unsigned long pages_scanned; /* since last reclaim */ int all_unreclaimable; /* All pages pinned */
diff -urN linux-2.6.15.orig/include/linux/page-flags.h linux-2.6.15/include/linux/page-flags.h --- linux-2.6.15.orig/include/linux/page-flags.h 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/include/linux/page-flags.h 2006-03-06 06:30:07.000000000 -0500 @@ -76,6 +76,8 @@ #define PG_nosave_free 18 /* Free, should not be written */ #define PG_uncached 19 /* Page has been mapped as uncached */
+#define PG_wired 20 /* Page is on Wired list */ + /* * Global page accounting. One instance per CPU. Only unsigned longs are * allowed. @@ -198,7 +200,14 @@ #define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags) #define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)
+#define SetPageWired(page) set_bit(PG_wired, &(page)->flags) +#define ClearPageWired(page) clear_bit(PG_wired,&(page)->flags) +#define PageWired(page) test_bit(PG_wired, &(page)->flags) +#define TestSetPageWired(page) test_and_set_bit(PG_wired, &(page)->flags) +#define TestClearPageWired(page) test_and_clear_bit(PG_wired, &(page)->flags) + #define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) +#define ClearPageLRU(page) clear_bit(PG_lru, &(page)->flags) #define PageLRU(page) test_bit(PG_lru, &(page)->flags) #define TestSetPageLRU(page) test_and_set_bit(PG_lru, &(page)->flags) #define TestClearPageLRU(page) test_and_clear_bit(PG_lru, &(page)->flags) diff -urN linux-2.6.15.orig/include/linux/swap.h linux-2.6.15/include/linux/swap.h --- linux-2.6.15.orig/include/linux/swap.h 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/include/linux/swap.h 2006-03-06 06:30:07.000000000 -0500 @@ -165,6 +165,8 @@ extern void FASTCALL(lru_cache_add(struct page *)); extern void FASTCALL(lru_cache_add_active(struct page *)); extern void FASTCALL(activate_page(struct page *)); +extern void FASTCALL(wire_page(struct page *)); +extern void FASTCALL(unwire_page(struct page *)); extern void FASTCALL(mark_page_accessed(struct page *)); extern void lru_add_drain(void); extern int rotate_reclaimable_page(struct page *page); diff -urN linux-2.6.15.orig/mm/swap.c linux-2.6.15/mm/swap.c --- linux-2.6.15.orig/mm/swap.c 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/mm/swap.c 2006-03-07 11:45:37.000000000 -0500 @@ -110,6 +110,44 @@ spin_unlock_irq(&zone->lru_lock); }
+/* Wire the page; if the page is in LRU, + * try move it to Wired list. + */ +void fastcall wire_page(struct page *page) +{ + struct zone *zone = page_zone(page); + + spin_lock_irq(&zone->lru_lock); + page->wired_count ++; + if(!PageWired(page)){ + if(PageLRU(page)){ + del_page_from_lru(zone, page); + add_page_to_wired_list(zone,page); + SetPageWired(page); + } + } + spin_unlock_irq(&zone->lru_lock); +} + +/* Unwire the page. + * If it isnt wired by any process, try move it to active list. + */ +void fastcall unwire_page(struct page *page) +{ + struct zone *zone = page_zone(page); + + spin_lock_irq(&zone->lru_lock); + page->wired_count --; + if(!page->wired_count){ + if(PageLRU(page) && TestClearPageWired(page)){ + del_page_from_wired_list(zone,page); + add_page_to_active_list(zone,page); + SetPageActive(page); + } + } + spin_unlock_irq(&zone->lru_lock); +} + /* * Mark a page as having seen activity. * @@ -119,11 +157,13 @@ */ void fastcall mark_page_accessed(struct page *page) { - if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) { - activate_page(page); - ClearPageReferenced(page); - } else if (!PageReferenced(page)) { - SetPageReferenced(page); + if(!PageWired(page)) { + if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) { + activate_page(page); + ClearPageReferenced(page); + } else if (!PageReferenced(page)) { + SetPageReferenced(page); + } } }
@@ -178,13 +218,15 @@ struct zone *zone = page_zone(page);
spin_lock_irqsave(&zone->lru_lock, flags); - if (TestClearPageLRU(page)) - del_page_from_lru(zone, page); - if (page_count(page) != 0) - page = NULL; + if(!PageWired(page)) { + if (TestClearPageLRU(page)) + del_page_from_lru(zone, page); + if (page_count(page) != 0) + page = NULL; + if (page) + free_hot_page(page); + } spin_unlock_irqrestore(&zone->lru_lock, flags); - if (page) - free_hot_page(page); }
EXPORT_SYMBOL(__page_cache_release); @@ -214,7 +256,8 @@
if (!put_page_testzero(page)) continue; - + if(PageWired(page)) + continue; pagezone = page_zone(page); if (pagezone != zone) { if (zone) @@ -301,7 +344,12 @@ } if (TestSetPageLRU(page)) BUG(); - add_page_to_inactive_list(zone, page); + if(!page->wired_count) + add_page_to_inactive_list(zone, page); + else { + SetPageWired(page); + add_page_to_wired_list(zone,page); + } } if (zone) spin_unlock_irq(&zone->lru_lock); @@ -330,7 +378,12 @@ BUG(); if (TestSetPageActive(page)) BUG(); - add_page_to_active_list(zone, page); + if(!page->wired_count) + add_page_to_active_list(zone, page); + else{ + SetPageWired(page); + add_page_to_wired_list(zone,page); + } } if (zone) spin_unlock_irq(&zone->lru_lock); diff -urN linux-2.6.15.orig/mm/page_alloc.c linux-2.6.15/mm/page_alloc.c --- linux-2.6.15.orig/mm/page_alloc.c 2006-01-02 22:21:10.000000000 -0500 +++ linux-2.6.15/mm/page_alloc.c 2006-03-06 06:30:08.000000000 -0500 @@ -348,7 +348,8 @@ 1 << PG_slab | 1 << PG_swapcache | 1 << PG_writeback | - 1 << PG_reserved ))) + 1 << PG_reserved | + 1 << PG_wired ))) bad_page(function, page); if (PageDirty(page)) __ClearPageDirty(page); @@ -481,6 +482,7 @@ 1 << PG_private | 1 << PG_locked | 1 << PG_active | + 1 << PG_wired | 1 << PG_dirty | 1 << PG_reclaim | 1 << PG_slab | - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |