From: "Stone Wang" <pwstone@gmail.com>
To: akpm@osdl.org
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: [PATCH][8/8] mm: lru interface change
Date: Mon, 20 Mar 2006 08:38:36 -0500 [thread overview]
Message-ID: <bc56f2f0603200538g3d6aa712i@mail.gmail.com> (raw)
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 |
WARNING: multiple messages have this Message-ID (diff)
From: "Stone Wang" <pwstone@gmail.com>
To: akpm@osdl.org
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: [PATCH][8/8] mm: lru interface change
Date: Mon, 20 Mar 2006 08:38:36 -0500 [thread overview]
Message-ID: <bc56f2f0603200538g3d6aa712i@mail.gmail.com> (raw)
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, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next reply other threads:[~2006-03-20 13:38 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-03-20 13:38 Stone Wang [this message]
2006-03-20 13:38 ` [PATCH][8/8] mm: lru interface change Stone Wang
2006-03-21 12:22 ` Nick Piggin
2006-03-21 12:22 ` Nick Piggin
2006-03-21 13:13 ` Arjan van de Ven
2006-03-21 13:13 ` Arjan van de Ven
2006-03-21 15:53 ` Stone Wang
2006-03-21 15:53 ` Stone Wang
2006-03-22 0:18 ` Nick Piggin
2006-03-22 0:18 ` Nick Piggin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bc56f2f0603200538g3d6aa712i@mail.gmail.com \
--to=pwstone@gmail.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.