summaryrefslogtreecommitdiff
path: root/include/linux/mm.h
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2009-07-03 08:30:39 -0500
committerThomas Gleixner <tglx@linutronix.de>2009-07-29 23:30:44 +0200
commitb38cb5ad333d0f84adf1825cf24929707ffce57d (patch)
tree966732156695818fdf17e13b0bf22b95a7d33405 /include/linux/mm.h
parent751675d74ac83053714021896601a3cde294a6ff (diff)
downloadlwn-b38cb5ad333d0f84adf1825cf24929707ffce57d.tar.gz
lwn-b38cb5ad333d0f84adf1825cf24929707ffce57d.zip
mm: remove kmap_lock
Eradicate global locks. - kmap_lock is removed by extensive use of atomic_t and a new flush scheme. - pool_lock is removed by using the pkmap index for the page_address_maps and modifying set_page_address to only allow NULL<->virt transitions. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r--include/linux/mm.h32
1 files changed, 24 insertions, 8 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index fb2a7e90eaaf..1f631fce9ea8 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -602,23 +602,39 @@ static __always_inline void *lowmem_page_address(struct page *page)
#endif
#if defined(WANT_PAGE_VIRTUAL)
-#define page_address(page) ((page)->virtual)
-#define set_page_address(page, address) \
- do { \
- (page)->virtual = (address); \
- } while(0)
-#define page_address_init() do { } while(0)
+/*
+ * wrap page->virtual so it is safe to set/read locklessly
+ */
+#define page_address(page) \
+ ({ typeof((page)->virtual) v = (page)->virtual; \
+ smp_read_barrier_depends(); \
+ v; })
+
+static inline int set_page_address(struct page *page, void *address)
+{
+ if (address)
+ return cmpxchg(&page->virtual, NULL, address) == NULL;
+ else {
+ /*
+ * cmpxchg is a bit abused because it is not guaranteed
+ * safe wrt direct assignment on all platforms.
+ */
+ void *virt = page->virtual;
+ return cmpxchg(&page->vitrual, virt, NULL) == virt;
+ }
+}
+void page_address_init(void);
#endif
#if defined(HASHED_PAGE_VIRTUAL)
void *page_address(struct page *page);
-void set_page_address(struct page *page, void *virtual);
+int set_page_address(struct page *page, void *virtual);
void page_address_init(void);
#endif
#if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL)
#define page_address(page) lowmem_page_address(page)
-#define set_page_address(page, address) do { } while(0)
+#define set_page_address(page, address) (0)
#define page_address_init() do { } while(0)
#endif