aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Weiner <hannes@cmpxchg.org>2009-09-21 20:01:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:30 -0400
commit451ea25da71590361c71bf3044c55b870a887d53 (patch)
treee2e9de6e7c1fb4f79c0413a3c4d401ec9263b722
parentbf88c8c83e4425d17e29daa5354ffb1f8ba7b225 (diff)
mm: perform non-atomic test-clear of PG_mlocked on free
By the time PG_mlocked is cleared in the page freeing path, nobody else is looking at our page->flags anymore. It is thus safe to make the test-and-clear non-atomic and thereby removing an unnecessary and expensive operation from a hotpath. Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Reviewed-by: Christoph Lameter <cl@linux-foundation.org> Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Christoph Lameter <cl@linux-foundation.org> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Nick Piggin <nickpiggin@yahoo.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/page-flags.h12
-rw-r--r--mm/page_alloc.c4
2 files changed, 11 insertions, 5 deletions
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 2b87acfc5f87..d07c0bb2203a 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -158,6 +158,9 @@ static inline int TestSetPage##uname(struct page *page) \
158static inline int TestClearPage##uname(struct page *page) \ 158static inline int TestClearPage##uname(struct page *page) \
159 { return test_and_clear_bit(PG_##lname, &page->flags); } 159 { return test_and_clear_bit(PG_##lname, &page->flags); }
160 160
161#define __TESTCLEARFLAG(uname, lname) \
162static inline int __TestClearPage##uname(struct page *page) \
163 { return __test_and_clear_bit(PG_##lname, &page->flags); }
161 164
162#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \ 165#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
163 SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) 166 SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
@@ -184,6 +187,9 @@ static inline void __ClearPage##uname(struct page *page) { }
184#define TESTCLEARFLAG_FALSE(uname) \ 187#define TESTCLEARFLAG_FALSE(uname) \
185static inline int TestClearPage##uname(struct page *page) { return 0; } 188static inline int TestClearPage##uname(struct page *page) { return 0; }
186 189
190#define __TESTCLEARFLAG_FALSE(uname) \
191static inline int __TestClearPage##uname(struct page *page) { return 0; }
192
187struct page; /* forward declaration */ 193struct page; /* forward declaration */
188 194
189TESTPAGEFLAG(Locked, locked) TESTSETFLAG(Locked, locked) 195TESTPAGEFLAG(Locked, locked) TESTSETFLAG(Locked, locked)
@@ -250,11 +256,11 @@ PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable)
250#ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT 256#ifdef CONFIG_HAVE_MLOCKED_PAGE_BIT
251#define MLOCK_PAGES 1 257#define MLOCK_PAGES 1
252PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) 258PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked)
253 TESTSCFLAG(Mlocked, mlocked) 259 TESTSCFLAG(Mlocked, mlocked) __TESTCLEARFLAG(Mlocked, mlocked)
254#else 260#else
255#define MLOCK_PAGES 0 261#define MLOCK_PAGES 0
256PAGEFLAG_FALSE(Mlocked) 262PAGEFLAG_FALSE(Mlocked) SETPAGEFLAG_NOOP(Mlocked)
257 SETPAGEFLAG_NOOP(Mlocked) TESTCLEARFLAG_FALSE(Mlocked) 263 TESTCLEARFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked)
258#endif 264#endif
259 265
260#ifdef CONFIG_ARCH_USES_PG_UNCACHED 266#ifdef CONFIG_ARCH_USES_PG_UNCACHED
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 81926c7ef6f0..9242d13f4ff3 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -557,7 +557,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
557 unsigned long flags; 557 unsigned long flags;
558 int i; 558 int i;
559 int bad = 0; 559 int bad = 0;
560 int wasMlocked = TestClearPageMlocked(page); 560 int wasMlocked = __TestClearPageMlocked(page);
561 561
562 kmemcheck_free_shadow(page, order); 562 kmemcheck_free_shadow(page, order);
563 563
@@ -1026,7 +1026,7 @@ static void free_hot_cold_page(struct page *page, int cold)
1026 struct zone *zone = page_zone(page); 1026 struct zone *zone = page_zone(page);
1027 struct per_cpu_pages *pcp; 1027 struct per_cpu_pages *pcp;
1028 unsigned long flags; 1028 unsigned long flags;
1029 int wasMlocked = TestClearPageMlocked(page); 1029 int wasMlocked = __TestClearPageMlocked(page);
1030 1030
1031 kmemcheck_free_shadow(page, 0); 1031 kmemcheck_free_shadow(page, 0);
1032 1032