]> Zhao Yanbai Git Server - minix.git/commitdiff
vm optimisation - maintain hint for new virtual region position.
authorBen Gras <ben@minix3.org>
Thu, 7 Oct 2010 10:04:05 +0000 (10:04 +0000)
committerBen Gras <ben@minix3.org>
Thu, 7 Oct 2010 10:04:05 +0000 (10:04 +0000)
servers/vm/exec.c
servers/vm/exit.c
servers/vm/region.c
servers/vm/vmproc.h

index 3cc58e23a04bd7b7af0110ae2be6fe020948d7cb..049280e769975fc4f0e023998bd8f4ea3c18f041 100644 (file)
@@ -187,6 +187,7 @@ SANITYCHECK(SCL_DETAIL);
 #endif
 
   region_init(&rmp->vm_regions_avl); /* exec()ing process regions thrown out. */
+  rmp->vm_region_top = 0;
 SANITYCHECK(SCL_DETAIL);
 
   /* Build new process in current slot, without freeing old
index 84f0ac1e9b38c110be71cf56e64fe7b39ace76e5..1c876ed9c94dc459191b835c200c56e1d9b14494 100644 (file)
@@ -32,6 +32,7 @@ PUBLIC void free_proc(struct vmproc *vmp)
                pt_free(&vmp->vm_pt);
        }
        region_init(&vmp->vm_regions_avl);
+       vmp->vm_region_top = 0;
 #if VMSTATS
        vmp->vm_bytecopies = 0;
 #endif
@@ -40,6 +41,7 @@ PUBLIC void free_proc(struct vmproc *vmp)
 PUBLIC void clear_proc(struct vmproc *vmp)
 {
        region_init(&vmp->vm_regions_avl);
+       vmp->vm_region_top = 0;
        vmp->vm_callback = NULL;        /* No pending vfs callback. */
        vmp->vm_flags = 0;              /* Clear INUSE, so slot is free. */
        vmp->vm_heap = NULL;
index b764e51c99b12f457e31aa8962d8b031bba115da..51054c282eebe893448462059db53cf4bfd40ead 100644 (file)
@@ -365,19 +365,18 @@ PRIVATE int map_ph_writept(struct vmproc *vmp, struct vir_region *vr,
        return OK;
 }
 
+#define SLOT_FAIL ((vir_bytes) -1)
+
 /*===========================================================================*
- *                             region_find_slot                             *
+ *                             region_find_slot_range                       *
  *===========================================================================*/
-PRIVATE vir_bytes region_find_slot(struct vmproc *vmp,
-               vir_bytes minv, vir_bytes maxv, vir_bytes length,
-               struct vir_region **prev)
+PRIVATE vir_bytes region_find_slot_range(struct vmproc *vmp,
+               vir_bytes minv, vir_bytes maxv, vir_bytes length)
 {
-       struct vir_region *firstregion, *prevregion = NULL;
+       struct vir_region *firstregion;
        vir_bytes startv;
        int foundflag = 0;
-
-       /* XXX start search closer to minv to optimise. */
-       firstregion = region_search_least(&vmp->vm_regions_avl);
+       region_iter iter;
 
        SANITYCHECK(SCL_FUNCTIONS);
 
@@ -395,7 +394,7 @@ PRIVATE vir_bytes region_find_slot(struct vmproc *vmp,
                         printf("region_find_slot: minv 0x%lx and bytes 0x%lx\n",
                                 minv, length);
                        map_printmap(vmp);
-                        return (vir_bytes) -1;
+                        return SLOT_FAIL;
                 }
         }
 
@@ -408,30 +407,37 @@ PRIVATE vir_bytes region_find_slot(struct vmproc *vmp,
        assert(minv < maxv);
        assert(minv + length <= maxv);
 
-#define FREEVRANGE(rangestart, rangeend, foundcode) {          \
+#define FREEVRANGE(rangestart, rangeend) {             \
        vir_bytes frstart = (rangestart), frend = (rangeend);   \
        frstart = MAX(frstart, minv);                           \
        frend   = MIN(frend, maxv);                             \
        if(frend > frstart && (frend - frstart) >= length) {    \
                startv = frstart;                               \
                foundflag = 1;                                  \
-               foundcode;                                      \
        } }
 
-       /* This is the free virtual address space before the first region. */
-       FREEVRANGE(0, firstregion ? firstregion->vaddr : VM_DATATOP, ;);
+       /* find region before minv. */
+       region_start_iter(&vmp->vm_regions_avl, &iter, minv, AVL_LESS_EQUAL);
+       firstregion = region_get_iter(&iter);
+
+       if(!firstregion) {
+               /* This is the free virtual address space before the first region. */
+               region_start_iter(&vmp->vm_regions_avl, &iter, minv, AVL_GREATER_EQUAL);
+               firstregion = region_get_iter(&iter);
+               FREEVRANGE(0, firstregion ? firstregion->vaddr : VM_DATATOP);
+       }
 
        if(!foundflag) {
                struct vir_region *vr;
-               region_iter iter;
-               region_start_iter_least(&vmp->vm_regions_avl, &iter);
                while((vr = region_get_iter(&iter)) && !foundflag) {
                        struct vir_region *nextvr;
                        region_incr_iter(&iter);
                        nextvr = region_get_iter(&iter);
                        FREEVRANGE(vr->vaddr + vr->length,
-                         nextvr ? nextvr->vaddr : VM_DATATOP,
-                               prevregion = vr;);
+                         nextvr ? nextvr->vaddr : VM_DATATOP);
+                       if(!foundflag) {
+                               printf("incr from 0x%lx to 0x%lx; v range 0x%lx-0x%lx\n", vr->vaddr, nextvr->vaddr);
+                       }
                }
        }
 
@@ -439,23 +445,42 @@ PRIVATE vir_bytes region_find_slot(struct vmproc *vmp,
                printf("VM: region_find_slot: no 0x%lx bytes found for %d between 0x%lx and 0x%lx\n",
                        length, vmp->vm_endpoint, minv, maxv);
                map_printmap(vmp);
-               return (vir_bytes) -1;
+               return SLOT_FAIL;
        }
 
-#if SANITYCHECKS
-       if(prevregion) assert(prevregion->vaddr < startv);
-#endif
-
        /* However we got it, startv must be in the requested range. */
        assert(startv >= minv);
        assert(startv < maxv);
        assert(startv + length <= maxv);
 
-       if (prev)
-               *prev = prevregion;
+       /* remember this position as a hint for next time. */
+       vmp->vm_region_top = startv + length;
+
        return startv;
 }
 
+/*===========================================================================*
+ *                             region_find_slot                             *
+ *===========================================================================*/
+PRIVATE vir_bytes region_find_slot(struct vmproc *vmp,
+               vir_bytes minv, vir_bytes maxv, vir_bytes length)
+{
+       vir_bytes v, hint = vmp->vm_region_top;
+
+       /* use the top of the last inserted region as a minv hint if
+        * possible. remember that a zero maxv is a special case.
+        */
+
+       if(maxv && hint < maxv) {
+               v = region_find_slot_range(vmp, hint, maxv, length);
+
+               if(v != SLOT_FAIL)
+                       return v;
+       }
+
+       return region_find_slot_range(vmp, minv, maxv, length);
+}
+
 /*===========================================================================*
  *                             map_page_region                              *
  *===========================================================================*/
@@ -469,7 +494,7 @@ vir_bytes what;
 u32_t flags;
 int mapflags;
 {
-       struct vir_region *prevregion = NULL, *newregion;
+       struct vir_region *newregion;
        vir_bytes startv;
        struct phys_region *ph;
        physr_avl *phavl;
@@ -478,8 +503,8 @@ int mapflags;
 
        SANITYCHECK(SCL_FUNCTIONS);
 
-       startv = region_find_slot(vmp, minv, maxv, length, &prevregion);
-       if (startv == (vir_bytes) -1)
+       startv = region_find_slot(vmp, minv, maxv, length);
+       if (startv == SLOT_FAIL)
                return NULL;
 
        /* Now we want a new region. */
@@ -1305,7 +1330,7 @@ int write;
 }
 
 #if SANITYCHECKS
-static int countregions(struct vir_region *vr)
+static int count_phys_regions(struct vir_region *vr)
 {
        int n = 0;
        struct phys_region *ph;
@@ -1338,7 +1363,7 @@ PRIVATE struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
        physr_avl *phavl;
 #if SANITYCHECKS
        int cr;
-       cr = countregions(vr);
+       cr = count_phys_regions(vr);
 #endif
 
        if(!SLABALLOC(newvr))
@@ -1372,13 +1397,13 @@ PRIVATE struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
 #endif
                physr_insert(newvr->phys, newph);
 #if SANITYCHECKS
-               assert(countregions(vr) == cr);
+               assert(count_phys_regions(vr) == cr);
 #endif
                physr_incr_iter(&iter);
        }
 
 #if SANITYCHECKS
-       assert(countregions(vr) == countregions(newvr));
+       assert(count_phys_regions(vr) == count_phys_regions(newvr));
 #endif
 
        return newvr;
@@ -1738,7 +1763,7 @@ PUBLIC int map_unmap_region(struct vmproc *vmp, struct vir_region *r,
 PUBLIC int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size,
                struct vir_region *region, vir_bytes *r)
 {
-       struct vir_region *vr, *prev;
+       struct vir_region *vr;
        struct phys_region *ph;
        vir_bytes startv, dst_addr;
        physr_iter iter;
@@ -1754,11 +1779,10 @@ PUBLIC int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size,
                dst_addr = da;
        dst_addr = arch_vir2map(dvmp, dst_addr);
 
-       prev = NULL;
        /* round up to page size */
        assert(!(size % VM_PAGE_SIZE));
-       startv = region_find_slot(dvmp, dst_addr, VM_DATATOP, size, &prev);
-       if (startv == (vir_bytes) -1) {
+       startv = region_find_slot(dvmp, dst_addr, VM_DATATOP, size);
+       if (startv == SLOT_FAIL) {
                printf("map_remap: search 0x%lx...\n", dst_addr);
                map_printmap(dvmp);
                return ENOMEM;
index bd5d2dedec8cd73eaa4d5edf793ce650e4403041..2f67db371a3362376438b9117d255a072fbbea82 100644 (file)
@@ -31,6 +31,7 @@ struct vmproc {
 
        /* Regions in virtual address space. */
        region_avl vm_regions_avl;
+       vir_bytes  vm_region_top;       /* highest vaddr last inserted */
        yielded_avl     vm_yielded_blocks;       /* avl of yielded physblocks */
 
        /* Heap for brk() to extend. */