]> git.neil.brown.name Git - history.git/commitdiff
Fix up some more TLB shootdown issues.
authorLinus Torvalds <torvalds@home.transmeta.com>
Wed, 15 May 2002 19:09:13 +0000 (12:09 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Wed, 15 May 2002 19:09:13 +0000 (12:09 -0700)
include/asm-generic/tlb.h
mm/mmap.c

index 0e5c08cec926e717af83c2242d0eb931f37edfd5..0b7dc666fecf9606d2f8a0629f54241d9ca5b796 100644 (file)
@@ -44,11 +44,18 @@ extern mmu_gather_t mmu_gathers[NR_CPUS];
 static inline mmu_gather_t *tlb_gather_mmu(struct mm_struct *mm)
 {
        mmu_gather_t *tlb = &mmu_gathers[smp_processor_id()];
+       unsigned long nr;
 
        tlb->mm = mm;
        tlb->freed = 0;
-       /* Use fast mode if there is only one user of this mm (this process) */
-       tlb->nr = (atomic_read(&(mm)->mm_users) == 1) ? ~0UL : 0UL;
+
+       /* Use fast mode if this MM only exists on this CPU */
+       nr = ~0UL;
+#ifdef CONFIG_SMP
+       if (mm->cpu_vm_mask != (1<<smp_processor_id()))
+               nr = 0UL;
+#endif
+       tlb->nr = nr;
        return tlb;
 }
 
index fb7186aeadae414a27f647aa3871ce12b79c0a9a..d67191b52b579eb00764aafe1f72c2ec659f3d18 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1100,32 +1100,19 @@ void exit_mmap(struct mm_struct * mm)
 
        release_segments(mm);
        spin_lock(&mm->page_table_lock);
-       mpnt = mm->mmap;
-       mm->mmap = mm->mmap_cache = NULL;
-       mm->mm_rb = RB_ROOT;
-       mm->rss = 0;
-       mm->total_vm = 0;
-       mm->locked_vm = 0;
 
        tlb = tlb_gather_mmu(mm);
 
        flush_cache_mm(mm);
+       mpnt = mm->mmap;
        while (mpnt) {
-               struct vm_area_struct * next = mpnt->vm_next;
                unsigned long start = mpnt->vm_start;
                unsigned long end = mpnt->vm_end;
 
-               if (mpnt->vm_ops) {
-                       if (mpnt->vm_ops->close)
-                               mpnt->vm_ops->close(mpnt);
-               }
                mm->map_count--;
                remove_shared_vm_struct(mpnt);
                unmap_page_range(tlb, mpnt, start, end);
-               if (mpnt->vm_file)
-                       fput(mpnt->vm_file);
-               kmem_cache_free(vm_area_cachep, mpnt);
-               mpnt = next;
+               mpnt = mpnt->vm_next;
        }
 
        /* This is just debugging */
@@ -1134,7 +1121,32 @@ void exit_mmap(struct mm_struct * mm)
 
        clear_page_tables(tlb, FIRST_USER_PGD_NR, USER_PTRS_PER_PGD);
        tlb_finish_mmu(tlb, FIRST_USER_PGD_NR*PGDIR_SIZE, USER_PTRS_PER_PGD*PGDIR_SIZE);
+
+       mpnt = mm->mmap;
+       mm->mmap = mm->mmap_cache = NULL;
+       mm->mm_rb = RB_ROOT;
+       mm->rss = 0;
+       mm->total_vm = 0;
+       mm->locked_vm = 0;
+
        spin_unlock(&mm->page_table_lock);
+
+       /*
+        * Walk the list again, actually closing and freeing it
+        * without holding any MM locks.
+        */
+       while (mpnt) {
+               struct vm_area_struct * next = mpnt->vm_next;
+               if (mpnt->vm_ops) {
+                       if (mpnt->vm_ops->close)
+                               mpnt->vm_ops->close(mpnt);
+               }
+               if (mpnt->vm_file)
+                       fput(mpnt->vm_file);
+               kmem_cache_free(vm_area_cachep, mpnt);
+               mpnt = next;
+       }
+               
 }
 
 /* Insert vm structure into process list sorted by address