summaryrefslogtreecommitdiff
path: root/mm/memory.c
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2005-10-29 18:15:53 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-29 21:40:36 -0700
commite040f218bb49a6965a5b77edce05fe47a62dda39 (patch)
treee5547e04fa312f1b87db66e4ac2b6eed885ca276 /mm/memory.c
parent09ad4bbc3a5c93316d7f4ffc0c310d9cbb28c2f0 (diff)
downloadlwn-e040f218bb49a6965a5b77edce05fe47a62dda39.tar.gz
lwn-e040f218bb49a6965a5b77edce05fe47a62dda39.zip
[PATCH] mm: copy_pte_range progress fix
My latency breaking in copy_pte_range didn't work as intended: instead of checking at regularish intervals, after the first interval it checked every time around the loop, too impatient to be preempted. Fix that. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/memory.c')
-rw-r--r--mm/memory.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 1db40e935e55..222c13e46130 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -410,7 +410,7 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
{
pte_t *src_pte, *dst_pte;
unsigned long vm_flags = vma->vm_flags;
- int progress;
+ int progress = 0;
again:
dst_pte = pte_alloc_map(dst_mm, dst_pmd, addr);
@@ -418,17 +418,19 @@ again:
return -ENOMEM;
src_pte = pte_offset_map_nested(src_pmd, addr);
- progress = 0;
spin_lock(&src_mm->page_table_lock);
do {
/*
* We are holding two locks at this point - either of them
* could generate latencies in another task on another CPU.
*/
- if (progress >= 32 && (need_resched() ||
- need_lockbreak(&src_mm->page_table_lock) ||
- need_lockbreak(&dst_mm->page_table_lock)))
- break;
+ if (progress >= 32) {
+ progress = 0;
+ if (need_resched() ||
+ need_lockbreak(&src_mm->page_table_lock) ||
+ need_lockbreak(&dst_mm->page_table_lock))
+ break;
+ }
if (pte_none(*src_pte)) {
progress++;
continue;