From: Hugh Dickins Test for pte_young before going to the costlier atomic test_and_clear, as asm-generic does. Test for pte_dirty before going to the costlier atomic test_and_clear, as asm-generic does (I said before that I would not do so for pte_dirty, but was missing the point: there is nothing atomic about deciding to do nothing). But I've not touched the rather different ppc and ppc64. Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton --- 25-akpm/include/asm-i386/pgtable.h | 16 ++++++++++++++-- 25-akpm/include/asm-ia64/pgtable.h | 4 ++++ 25-akpm/include/asm-parisc/pgtable.h | 4 ++++ 25-akpm/include/asm-x86_64/pgtable.h | 17 +++++++++++++++-- 4 files changed, 37 insertions(+), 4 deletions(-) diff -puN include/asm-i386/pgtable.h~mm-pretest-pte_young-and-pte_dirty include/asm-i386/pgtable.h --- 25/include/asm-i386/pgtable.h~mm-pretest-pte_young-and-pte_dirty Wed Jun 2 15:12:32 2004 +++ 25-akpm/include/asm-i386/pgtable.h Wed Jun 2 15:12:32 2004 @@ -220,8 +220,20 @@ static inline pte_t pte_mkdirty(pte_t pt static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; } static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; } -static inline int ptep_test_and_clear_dirty(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); } -static inline int ptep_test_and_clear_young(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); } +static inline int ptep_test_and_clear_dirty(pte_t *ptep) +{ + if (!pte_dirty(*ptep)) + return 0; + return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); +} + +static inline int ptep_test_and_clear_young(pte_t *ptep) +{ + if (!pte_young(*ptep)) + return 0; + return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); +} + static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, &ptep->pte_low); } static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); } diff -puN include/asm-ia64/pgtable.h~mm-pretest-pte_young-and-pte_dirty include/asm-ia64/pgtable.h --- 25/include/asm-ia64/pgtable.h~mm-pretest-pte_young-and-pte_dirty Wed Jun 2 15:12:32 2004 +++ 25-akpm/include/asm-ia64/pgtable.h Wed Jun 2 15:12:32 2004 @@ -346,6 +346,8 @@ static inline int ptep_test_and_clear_young (pte_t *ptep) { #ifdef CONFIG_SMP + if (!pte_young(*ptep)) + return 0; return test_and_clear_bit(_PAGE_A_BIT, ptep); #else pte_t pte = *ptep; @@ -360,6 +362,8 @@ static inline int ptep_test_and_clear_dirty (pte_t *ptep) { #ifdef CONFIG_SMP + if (!pte_dirty(*ptep)) + return 0; return test_and_clear_bit(_PAGE_D_BIT, ptep); #else pte_t pte = *ptep; diff -puN include/asm-parisc/pgtable.h~mm-pretest-pte_young-and-pte_dirty include/asm-parisc/pgtable.h --- 25/include/asm-parisc/pgtable.h~mm-pretest-pte_young-and-pte_dirty Wed Jun 2 15:12:32 2004 +++ 25-akpm/include/asm-parisc/pgtable.h Wed Jun 2 15:12:32 2004 @@ -417,6 +417,8 @@ extern void update_mmu_cache(struct vm_a static inline int ptep_test_and_clear_young(pte_t *ptep) { #ifdef CONFIG_SMP + if (!pte_young(*ptep)) + return 0; return test_and_clear_bit(xlate_pabit(_PAGE_ACCESSED_BIT), ptep); #else pte_t pte = *ptep; @@ -430,6 +432,8 @@ static inline int ptep_test_and_clear_yo static inline int ptep_test_and_clear_dirty(pte_t *ptep) { #ifdef CONFIG_SMP + if (!pte_dirty(*ptep)) + return 0; return test_and_clear_bit(xlate_pabit(_PAGE_DIRTY_BIT), ptep); #else pte_t pte = *ptep; diff -puN include/asm-x86_64/pgtable.h~mm-pretest-pte_young-and-pte_dirty include/asm-x86_64/pgtable.h --- 25/include/asm-x86_64/pgtable.h~mm-pretest-pte_young-and-pte_dirty Wed Jun 2 15:12:32 2004 +++ 25-akpm/include/asm-x86_64/pgtable.h Wed Jun 2 15:12:32 2004 @@ -262,8 +262,21 @@ extern inline pte_t pte_mkexec(pte_t pte extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; } -static inline int ptep_test_and_clear_dirty(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); } -static inline int ptep_test_and_clear_young(pte_t *ptep) { return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); } + +static inline int ptep_test_and_clear_dirty(pte_t *ptep) +{ + if (!pte_dirty(*ptep)) + return 0; + return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep); +} + +static inline int ptep_test_and_clear_young(pte_t *ptep) +{ + if (!pte_young(*ptep)) + return 0; + return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep); +} + static inline void ptep_set_wrprotect(pte_t *ptep) { clear_bit(_PAGE_BIT_RW, ptep); } static inline void ptep_mkdirty(pte_t *ptep) { set_bit(_PAGE_BIT_DIRTY, ptep); } _