diff options
author | Johannes Weiner <hannes@cmpxchg.org> | 2009-09-21 20:01:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-22 10:17:30 -0400 |
commit | 451ea25da71590361c71bf3044c55b870a887d53 (patch) | |
tree | e2e9de6e7c1fb4f79c0413a3c4d401ec9263b722 | |
parent | bf88c8c83e4425d17e29daa5354ffb1f8ba7b225 (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.h | 12 | ||||
-rw-r--r-- | mm/page_alloc.c | 4 |
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) \ | |||
158 | static inline int TestClearPage##uname(struct page *page) \ | 158 | static 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) \ | ||
162 | static 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) \ |
185 | static inline int TestClearPage##uname(struct page *page) { return 0; } | 188 | static inline int TestClearPage##uname(struct page *page) { return 0; } |
186 | 189 | ||
190 | #define __TESTCLEARFLAG_FALSE(uname) \ | ||
191 | static inline int __TestClearPage##uname(struct page *page) { return 0; } | ||
192 | |||
187 | struct page; /* forward declaration */ | 193 | struct page; /* forward declaration */ |
188 | 194 | ||
189 | TESTPAGEFLAG(Locked, locked) TESTSETFLAG(Locked, locked) | 195 | TESTPAGEFLAG(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 |
252 | PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked) | 258 | PAGEFLAG(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 |
256 | PAGEFLAG_FALSE(Mlocked) | 262 | PAGEFLAG_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 | ||