Scalar page state: generalize to N lru lists

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Here's a slightly out of date patch against Rik's vm to allow an increased
number of lru lists, which opens up a variety of new design possibilities.
In addition, the code is very slightly faster than the bit-per-state version,
consumes fewer bits in the page state, and scales without extra overhead as
number of lists increases.

To apply:

  cd /your/2.4.6-source/tree
  patch <this/patch -p0

--- ../uml.2.4.6.clean/include/linux/mm.h	Wed Jul  4 00:42:55 2001
+++ ./include/linux/mm.h	Fri Jul  6 18:31:14 2001
@@ -274,15 +274,14 @@
 #define PG_uptodate		 3
 #define PG_dirty		 4
 #define PG_decr_after		 5
-#define PG_active		 6
-#define PG_inactive_dirty	 7
 #define PG_slab			 8
 #define PG_swap_cache		 9
 #define PG_skip			10
-#define PG_inactive_clean	11
 #define PG_highmem		12
 #define PG_checked		13	/* kill me in 2.5.<early>. */
-				/* bits 21-29 unused */
+				/* bits 6, 7, 11 and 21-29 unused */
+#define PG_state_shift		14
+#define PG_state_mask		(3 << PG_state_shift)
 #define PG_arch_1		30
 #define PG_reserved		31
 
@@ -344,17 +343,24 @@
 
 #define PageTestandClearSwapCache(page)	test_and_clear_bit(PG_swap_cache, &(page)->flags)
 
-#define PageActive(page)	test_bit(PG_active, &(page)->flags)
-#define SetPageActive(page)	set_bit(PG_active, &(page)->flags)
-#define ClearPageActive(page)	clear_bit(PG_active, &(page)->flags)
-
-#define PageInactiveDirty(page)	test_bit(PG_inactive_dirty, &(page)->flags)
-#define SetPageInactiveDirty(page)	set_bit(PG_inactive_dirty, &(page)->flags)
-#define ClearPageInactiveDirty(page)	clear_bit(PG_inactive_dirty, &(page)->flags)
-
-#define PageInactiveClean(page)	test_bit(PG_inactive_clean, &(page)->flags)
-#define SetPageInactiveClean(page)	set_bit(PG_inactive_clean, &(page)->flags)
-#define ClearPageInactiveClean(page)	clear_bit(PG_inactive_clean, &(page)->flags)
+#define PG_Nolist 0
+#define PG_Active 1
+#define PG_InactiveClean 2
+#define PG_InactiveDirty 3
+
+#define PageNolist(page)	(((page)->flags & PG_state_mask) == PG_Nolist << PG_state_shift)
+#define PageActive(page)	(((page)->flags & PG_state_mask) == PG_Active << PG_state_shift)
+#define PageInactiveClean(page)	(((page)->flags & PG_state_mask) == PG_InactiveClean << PG_state_shift)
+#define PageInactiveDirty(page)	(((page)->flags & PG_state_mask) == PG_InactiveDirty << PG_state_shift)
+
+#define SetPageNolist(page)	   ((page)->flags &= ~PG_state_mask)
+#define SetPageActive(page)	   ((page)->flags |= PG_Active << PG_state_shift)
+#define SetPageInactiveClean(page) ((page)->flags |= PG_InactiveClean << PG_state_shift)
+#define SetPageInactiveDirty(page) ((page)->flags |= PG_InactiveDirty << PG_state_shift)
+
+#define ClearPageActive SetPageNolist
+#define ClearPageInactiveClean SetPageNolist
+#define ClearPageInactiveDirty SetPageNolist
 
 #ifdef CONFIG_HIGHMEM
 #define PageHighMem(page)		test_bit(PG_highmem, &(page)->flags)
--- ../uml.2.4.6.clean/include/linux/swap.h	Wed Jul  4 00:42:55 2001
+++ ./include/linux/swap.h	Fri Jul  6 17:26:39 2001
@@ -182,8 +182,7 @@
  * with the pagemap_lru_lock held!
  */
 #define DEBUG_ADD_PAGE \
-	if (PageActive(page) || PageInactiveDirty(page) || \
-					PageInactiveClean(page)) BUG();
+	if (!PageNolist(page)) BUG();
 
 #define ZERO_PAGE_BUG \
 	if (page_count(page) == 0) BUG();
--- ../uml.2.4.6.clean/mm/page_alloc.c	Sat Jun 30 00:39:41 2001
+++ ./mm/page_alloc.c	Fri Jul  6 17:25:41 2001
@@ -81,11 +81,7 @@
 		BUG();
 	if (PageDecrAfter(page))
 		BUG();
-	if (PageActive(page))
-		BUG();
-	if (PageInactiveDirty(page))
-		BUG();
-	if (PageInactiveClean(page))
+	if (!PageNolist(page))
 		BUG();
 
 	page->flags &= ~((1<<PG_referenced) | (1<<PG_dirty));
--- ../uml.2.4.6.clean/mm/swap.c	Mon Jan 22 22:30:21 2001
+++ ./mm/swap.c	Fri Jul  6 16:36:27 2001
@@ -197,13 +197,17 @@
  */
 void activate_page_nolock(struct page * page)
 {
-	if (PageInactiveDirty(page)) {
+	switch ((page->flags & PG_state_mask) >> PG_state_shift)
+	{
+	case PG_InactiveDirty:
 		del_page_from_inactive_dirty_list(page);
 		add_page_to_active_list(page);
-	} else if (PageInactiveClean(page)) {
+		break;
+	case PG_InactiveClean:
 		del_page_from_inactive_clean_list(page);
 		add_page_to_active_list(page);
-	} else {
+		break;
+	default:
 		/*
 		 * The page was not on any list, so we take care
 		 * not to do anything.
@@ -248,16 +252,21 @@
  */
 void __lru_cache_del(struct page * page)
 {
-	if (PageActive(page)) {
+	switch ((page->flags & PG_state_mask) >> PG_state_shift)
+	{
+	case PG_Active:
 		del_page_from_active_list(page);
-	} else if (PageInactiveDirty(page)) {
-		del_page_from_inactive_dirty_list(page);
-	} else if (PageInactiveClean(page)) {
+		break;
+	case PG_InactiveClean:
 		del_page_from_inactive_clean_list(page);
-	} else {
+		break;
+	case PG_InactiveDirty:
+		del_page_from_inactive_dirty_list(page);
+		break;
+	default:
 		printk("VM: __lru_cache_del, found unknown page ?!\n");
+		DEBUG_ADD_PAGE
 	}
-	DEBUG_ADD_PAGE
 }
 
 /**
--
Kernelnewbies: Help each other learn about the Linux kernel.
Archive:       http://mail.nl.linux.org/kernelnewbies/
IRC Channel:   irc.openprojects.net / #kernelnewbies
Web Page:      http://www.kernelnewbies.org/



[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux