diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-07-03 08:30:39 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2009-07-29 23:30:44 +0200 |
commit | b38cb5ad333d0f84adf1825cf24929707ffce57d (patch) | |
tree | 966732156695818fdf17e13b0bf22b95a7d33405 /include/linux/mm.h | |
parent | 751675d74ac83053714021896601a3cde294a6ff (diff) | |
download | lwn-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.h | 32 |
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 |