[PATCH] i386: pte xchg optimization
authorZachary Amsden <zach@vmware.com>
Wed, 2 May 2007 17:27:19 +0000 (19:27 +0200)
committerAndi Kleen <andi@basil.nowhere.org>
Wed, 2 May 2007 17:27:19 +0000 (19:27 +0200)
In situations where page table updates need only be made locally, and there is
no cross-processor A/D bit races involved, we need not use the heavyweight
xchg instruction to atomically fetch and clear page table entries.  Instead,
we can just read and clear them directly.

This introduces a neat optimization for non-SMP kernels; drop the atomic xchg
operations from page table updates.

Thanks to Michel Lespinasse for noting this potential optimization.

Signed-off-by: Zachary Amsden <zach@vmware.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Andi Kleen <ak@suse.de>
include/asm-i386/pgtable-2level.h
include/asm-i386/pgtable-3level.h

index 85d9005c0cdf9c42d1949fdb176b1a8e6208af15..3daab67cd3666e3465d6fbb46ad7c43b250c7a54 100644 (file)
@@ -41,10 +41,24 @@ static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr, pt
        *xp = __pte(0);
 }
 
+/* local pte updates need not use xchg for locking */
+static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
+{
+       pte_t res;
+
+       res = *ptep;
+       native_pte_clear(NULL, 0, ptep);
+       return res;
+}
+
+#ifdef CONFIG_SMP
 static inline pte_t native_ptep_get_and_clear(pte_t *xp)
 {
        return __pte(xchg(&xp->pte_low, 0));
 }
+#else
+#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
+#endif
 
 #define pte_page(x)            pfn_to_page(pte_pfn(x))
 #define pte_none(x)            (!(x).pte_low)
index 664bfee5a2f20f2f1b63a31413c273cbf26b5e35..45b0241815070c3c84605b5f70855bdd461a23d2 100644 (file)
@@ -139,6 +139,17 @@ static inline void pud_clear (pud_t * pud) { }
 #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
                        pmd_index(address))
 
+/* local pte updates need not use xchg for locking */
+static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep)
+{
+       pte_t res;
+
+       res = *ptep;
+       native_pte_clear(NULL, 0, ptep);
+       return res;
+}
+
+#ifdef CONFIG_SMP
 static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
 {
        pte_t res;
@@ -150,6 +161,9 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
 
        return res;
 }
+#else
+#define native_ptep_get_and_clear(xp) native_local_ptep_get_and_clear(xp)
+#endif
 
 #define __HAVE_ARCH_PTE_SAME
 static inline int pte_same(pte_t a, pte_t b)