aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-11-18 21:14:24 -0500
committerMel Gorman <mgorman@suse.de>2012-12-11 09:28:34 -0500
commit1233d588210737ed3696b44c26e71dfa44a6995a (patch)
treec2f29980355ef6983c06c2d01ac6bf0445bd16f6
parent7da4d641c58d201c3cc1835c05ca1a7fa26f0856 (diff)
mm: Optimize the TLB flush of sys_mprotect() and change_protection() users
Reuse the NUMA code's 'modified page protections' count that change_protection() computes and skip the TLB flush if there's no changes to a range that sys_mprotect() modifies. Given that mprotect() already optimizes the same-flags case I expected this optimization to dominantly trigger on CONFIG_NUMA_BALANCING=y kernels - but even with that feature disabled it triggers rather often. There's two reasons for that: 1) While sys_mprotect() already optimizes the same-flag case: if (newflags == oldflags) { *pprev = vma; return 0; } and this test works in many cases, but it is too sharp in some others, where it differentiates between protection values that the underlying PTE format makes no distinction about, such as PROT_EXEC == PROT_READ on x86. 2) Even where the pte format over vma flag changes necessiates a modification of the pagetables, there might be no pagetables yet to modify: they might not be instantiated yet. During a regular desktop bootup this optimization hits a couple of hundred times. During a Java test I measured thousands of hits. So this optimization improves sys_mprotect() in general, not just CONFIG_NUMA_BALANCING=y kernels. [ We could further increase the efficiency of this optimization if change_pte_range() and change_huge_pmd() was a bit smarter about recognizing exact-same-value protection masks - when the hardware can do that safely. This would probably further speed up mprotect(). ] Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Hugh Dickins <hughd@google.com> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--mm/mprotect.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 1e265be25f85..7c3628a8b486 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -153,7 +153,9 @@ static unsigned long change_protection_range(struct vm_area_struct *vma,
153 dirty_accountable); 153 dirty_accountable);
154 } while (pgd++, addr = next, addr != end); 154 } while (pgd++, addr = next, addr != end);
155 155
156 flush_tlb_range(vma, start, end); 156 /* Only flush the TLB if we actually modified any entries: */
157 if (pages)
158 flush_tlb_range(vma, start, end);
157 159
158 return pages; 160 return pages;
159} 161}