diff options
author | David Rientjes <rientjes@google.com> | 2007-05-06 17:49:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-07 15:12:52 -0400 |
commit | 10a8d6ae4b3182d6588a5809a8366343bc295c20 (patch) | |
tree | 37a1d626c350df5f4a4234a0fcaf524f5755fe4a | |
parent | 9490991482a2091a828d997adbc088e24c310a4d (diff) |
i386: add ptep_test_and_clear_{dirty,young}
Add ptep_test_and_clear_{dirty,young} to i386. They advertise that they
have it and there is at least one place where it needs to be called without
the page table lock: to clear the accessed bit on write to
/proc/pid/clear_refs.
ptep_clear_flush_{dirty,young} are updated to use the new functions. The
overall net effect to current users of ptep_clear_flush_{dirty,young} is
that we introduce an additional branch.
Cc: Hugh Dickins <hugh@veritas.com>
Cc: Ingo Molnar <mingo@redhat.com>
Signed-off-by: David Rientjes <rientjes@google.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/asm-i386/pgtable.h | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index c6b8b944120c..995e8b34efd0 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h | |||
@@ -296,12 +296,23 @@ do { \ | |||
296 | } \ | 296 | } \ |
297 | } while (0) | 297 | } while (0) |
298 | 298 | ||
299 | /* | ||
300 | * We don't actually have these, but we want to advertise them so that | ||
301 | * we can encompass the flush here. | ||
302 | */ | ||
303 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY | 299 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY |
300 | static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, | ||
301 | unsigned long addr, pte_t *ptep) | ||
302 | { | ||
303 | if (!pte_dirty(*ptep)) | ||
304 | return 0; | ||
305 | return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); | ||
306 | } | ||
307 | |||
304 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | 308 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG |
309 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, | ||
310 | unsigned long addr, pte_t *ptep) | ||
311 | { | ||
312 | if (!pte_young(*ptep)) | ||
313 | return 0; | ||
314 | return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low); | ||
315 | } | ||
305 | 316 | ||
306 | /* | 317 | /* |
307 | * Rules for using ptep_establish: the pte MUST be a user pte, and | 318 | * Rules for using ptep_establish: the pte MUST be a user pte, and |
@@ -318,9 +329,8 @@ do { \ | |||
318 | #define ptep_clear_flush_dirty(vma, address, ptep) \ | 329 | #define ptep_clear_flush_dirty(vma, address, ptep) \ |
319 | ({ \ | 330 | ({ \ |
320 | int __dirty; \ | 331 | int __dirty; \ |
321 | __dirty = pte_dirty(*(ptep)); \ | 332 | __dirty = ptep_test_and_clear_dirty((vma), (address), (ptep)); \ |
322 | if (__dirty) { \ | 333 | if (__dirty) { \ |
323 | clear_bit(_PAGE_BIT_DIRTY, &(ptep)->pte_low); \ | ||
324 | pte_update_defer((vma)->vm_mm, (address), (ptep)); \ | 334 | pte_update_defer((vma)->vm_mm, (address), (ptep)); \ |
325 | flush_tlb_page(vma, address); \ | 335 | flush_tlb_page(vma, address); \ |
326 | } \ | 336 | } \ |
@@ -331,9 +341,8 @@ do { \ | |||
331 | #define ptep_clear_flush_young(vma, address, ptep) \ | 341 | #define ptep_clear_flush_young(vma, address, ptep) \ |
332 | ({ \ | 342 | ({ \ |
333 | int __young; \ | 343 | int __young; \ |
334 | __young = pte_young(*(ptep)); \ | 344 | __young = ptep_test_and_clear_young((vma), (address), (ptep)); \ |
335 | if (__young) { \ | 345 | if (__young) { \ |
336 | clear_bit(_PAGE_BIT_ACCESSED, &(ptep)->pte_low); \ | ||
337 | pte_update_defer((vma)->vm_mm, (address), (ptep)); \ | 346 | pte_update_defer((vma)->vm_mm, (address), (ptep)); \ |
338 | flush_tlb_page(vma, address); \ | 347 | flush_tlb_page(vma, address); \ |
339 | } \ | 348 | } \ |