Hi,

The reaper is not very nice: it blocks any access to the kernel (i.e.
syscalls) until it is done with its work.  For big processes, this may
result in stalls in userspace.  This diff attempts to relieve it by
yielding the reaper during this operation.

Please test this diff (vmmap_reaperyield.diff.0).
-- 
Ariane


Index: uvm/uvm_extern.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_extern.h,v
retrieving revision 1.104
diff -u -d -p -r1.104 uvm_extern.h
--- uvm/uvm_extern.h    9 Mar 2012 13:01:29 -0000       1.104
+++ uvm/uvm_extern.h    12 Apr 2012 12:13:36 -0000
@@ -236,6 +236,11 @@ typedef int                vm_prot_t;
 #define        PHYSLOAD_DEVICE 0x01    /* don't add to the page queue */
 
 /*
+ * Flags to uvm_unmap_detach.
+ */
+#define UVM_UNMAP_DETACH_YIELD 0x0001  /* Yield during detach. */
+
+/*
  * structures
  */
 
Index: uvm/uvm_io.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_io.c,v
retrieving revision 1.20
diff -u -d -p -r1.20 uvm_io.c
--- uvm/uvm_io.c        9 Mar 2012 13:01:29 -0000       1.20
+++ uvm/uvm_io.c        12 Apr 2012 12:16:56 -0000
@@ -143,7 +143,7 @@ uvm_io(vm_map_t map, struct uio *uio, in
                uvm_unmap_remove(kernel_map, kva, kva+chunksz,
                    &dead_entries, FALSE, TRUE);
                vm_map_unlock(kernel_map);
-               uvm_unmap_detach(&dead_entries, AMAP_REFALL);
+               uvm_unmap_detach(&dead_entries, AMAP_REFALL, 0);
 
                /*
                 * We defer checking the error return from uiomove until
Index: uvm/uvm_km.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_km.c,v
retrieving revision 1.107
diff -u -d -p -r1.107 uvm_km.c
--- uvm/uvm_km.c        9 Mar 2012 13:01:29 -0000       1.107
+++ uvm/uvm_km.c        12 Apr 2012 12:17:00 -0000
@@ -478,7 +478,7 @@ uvm_km_free_wakeup(struct vm_map *map, v
        wakeup(map);
        vm_map_unlock(map);
 
-       uvm_unmap_detach(&dead_entries, 0);
+       uvm_unmap_detach(&dead_entries, 0, 0);
 }
 
 /*
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.151
diff -u -d -p -r1.151 uvm_map.c
--- uvm/uvm_map.c       11 Apr 2012 11:23:22 -0000      1.151
+++ uvm/uvm_map.c       12 Apr 2012 12:15:28 -0000
@@ -1208,7 +1208,7 @@ unlock:
         * uvm_map_mkentry may also create dead entries, when it attempts to
         * destroy free-space entries.
         */
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
        return error;
 }
 
@@ -1364,7 +1364,7 @@ uvm_mapent_tryjoin(struct vm_map *map, s
  * Kill entries that are no longer in a map.
  */
 void
-uvm_unmap_detach(struct uvm_map_deadq *deadq, int flags)
+uvm_unmap_detach(struct uvm_map_deadq *deadq, int amapflags, int flags)
 {
        struct vm_map_entry *entry;
 
@@ -1376,7 +1376,7 @@ uvm_unmap_detach(struct uvm_map_deadq *d
                        amap_unref(entry->aref.ar_amap,
                            entry->aref.ar_pageoff,
                            atop(entry->end - entry->start),
-                           flags);
+                           amapflags);
 
                /*
                 * Drop reference to our backing object, if we've got one.
@@ -1395,6 +1395,13 @@ uvm_unmap_detach(struct uvm_map_deadq *d
                 */
                TAILQ_REMOVE(deadq, entry, dfree.deadq);
                uvm_mapent_free(entry);
+
+               /*
+                * Yield between steps in the map.
+                * Only do this if instructed to do so.
+                */
+               if ((flags & UVM_UNMAP_DETACH_YIELD) && !curcpu_is_idle())
+                       yield();
        }
 }
 
@@ -1645,7 +1652,7 @@ uvm_unmap(struct vm_map *map, vaddr_t st
        uvm_unmap_remove(map, start, end, &dead, FALSE, TRUE);
        vm_map_unlock(map);
 
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
 }
 
 /*
@@ -2352,6 +2359,10 @@ uvm_map_teardown(struct vm_map *map)
                        DEAD_ENTRY_PUSH(&dead_entries, tmp);
                /* Update wave-front. */
                entry = TAILQ_NEXT(entry, dfree.deadq);
+
+               /* Don't starve other processes. */
+               if (!curcpu_is_idle())
+                       yield();
        }
 
        if ((map->flags & VM_MAP_INTRSAFE) == 0)
@@ -2365,7 +2376,7 @@ uvm_map_teardown(struct vm_map *map)
                numq++;
        KASSERT(numt == numq);
 #endif
-       uvm_unmap_detach(&dead_entries, 0);
+       uvm_unmap_detach(&dead_entries, 0, UVM_UNMAP_DETACH_YIELD);
        pmap_destroy(map->pmap);
        map->pmap = NULL;
 }
@@ -3219,7 +3230,7 @@ uvmspace_exec(struct proc *p, vaddr_t st
        /*
         * Release dead entries
         */
-       uvm_unmap_detach(&dead_entries, 0);
+       uvm_unmap_detach(&dead_entries, 0, 0);
 }
 
 /*
@@ -3591,7 +3602,7 @@ uvmspace_fork(struct vmspace *vm1)
         * This can actually happen, if multiple entries described a
         * space in which an entry was inherited.
         */
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
 
 #ifdef SYSVSHM
        if (vm1->vm_shm)
@@ -3771,7 +3782,7 @@ uvm_map_deallocate(vm_map_t map)
        KASSERT(RB_EMPTY(&map->addr));
        free(map, M_VMMAP);
 
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
 }
 
 /* 
@@ -4039,7 +4050,7 @@ fail2:
 fail:
        vm_map_unlock(srcmap);
 
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
 
        return error;
 }
@@ -4618,7 +4629,7 @@ uvm_map_set_uaddr(struct vm_map *map, st
 
        uvm_map_freelist_update_refill(map, 0);
        vm_map_unlock(map);
-       uvm_unmap_detach(&dead, 0);
+       uvm_unmap_detach(&dead, 0, 0);
 }
 
 /*
Index: uvm/uvm_map.h
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.h,v
retrieving revision 1.48
diff -u -d -p -r1.48 uvm_map.h
--- uvm/uvm_map.h       11 Apr 2012 11:23:22 -0000      1.48
+++ uvm/uvm_map.h       12 Apr 2012 12:15:59 -0000
@@ -402,7 +402,7 @@ void                uvm_map_set_uaddr(struct vm_map*, 
                    struct uvm_addr_state*);
 int            uvm_map_mquery(struct vm_map*, vaddr_t*, vsize_t, voff_t, int);
 
-void           uvm_unmap_detach(struct uvm_map_deadq*, int);
+void           uvm_unmap_detach(struct uvm_map_deadq*, int, int);
 void           uvm_unmap_remove(struct vm_map*, vaddr_t, vaddr_t,
                    struct uvm_map_deadq*, boolean_t, boolean_t);
 
Index: uvm/uvm_mmap.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_mmap.c,v
retrieving revision 1.89
diff -u -d -p -r1.89 uvm_mmap.c
--- uvm/uvm_mmap.c      10 Apr 2012 10:30:44 -0000      1.89
+++ uvm/uvm_mmap.c      12 Apr 2012 12:17:05 -0000
@@ -664,7 +664,7 @@ sys_munmap(struct proc *p, void *v, regi
 
        vm_map_unlock(map);     /* and unlock */
 
-       uvm_unmap_detach(&dead_entries, 0);
+       uvm_unmap_detach(&dead_entries, 0, 0);
 
        return (0);
 }

Reply via email to