vm optimisation - maintain hint for new virtual region position.

This commit is contained in:
Ben Gras 2010-10-07 10:04:05 +00:00
parent e0ac271e5a
commit a3f2df124c
4 changed files with 63 additions and 35 deletions

View file

@ -187,6 +187,7 @@ SANITYCHECK(SCL_DETAIL);
#endif #endif
region_init(&rmp->vm_regions_avl); /* exec()ing process regions thrown out. */ region_init(&rmp->vm_regions_avl); /* exec()ing process regions thrown out. */
rmp->vm_region_top = 0;
SANITYCHECK(SCL_DETAIL); SANITYCHECK(SCL_DETAIL);
/* Build new process in current slot, without freeing old /* Build new process in current slot, without freeing old

View file

@ -32,6 +32,7 @@ PUBLIC void free_proc(struct vmproc *vmp)
pt_free(&vmp->vm_pt); pt_free(&vmp->vm_pt);
} }
region_init(&vmp->vm_regions_avl); region_init(&vmp->vm_regions_avl);
vmp->vm_region_top = 0;
#if VMSTATS #if VMSTATS
vmp->vm_bytecopies = 0; vmp->vm_bytecopies = 0;
#endif #endif
@ -40,6 +41,7 @@ PUBLIC void free_proc(struct vmproc *vmp)
PUBLIC void clear_proc(struct vmproc *vmp) PUBLIC void clear_proc(struct vmproc *vmp)
{ {
region_init(&vmp->vm_regions_avl); region_init(&vmp->vm_regions_avl);
vmp->vm_region_top = 0;
vmp->vm_callback = NULL; /* No pending vfs callback. */ vmp->vm_callback = NULL; /* No pending vfs callback. */
vmp->vm_flags = 0; /* Clear INUSE, so slot is free. */ vmp->vm_flags = 0; /* Clear INUSE, so slot is free. */
vmp->vm_heap = NULL; vmp->vm_heap = NULL;

View file

@ -365,19 +365,18 @@ PRIVATE int map_ph_writept(struct vmproc *vmp, struct vir_region *vr,
return OK; return OK;
} }
#define SLOT_FAIL ((vir_bytes) -1)
/*===========================================================================* /*===========================================================================*
* region_find_slot * * region_find_slot_range *
*===========================================================================*/ *===========================================================================*/
PRIVATE vir_bytes region_find_slot(struct vmproc *vmp, PRIVATE vir_bytes region_find_slot_range(struct vmproc *vmp,
vir_bytes minv, vir_bytes maxv, vir_bytes length, vir_bytes minv, vir_bytes maxv, vir_bytes length)
struct vir_region **prev)
{ {
struct vir_region *firstregion, *prevregion = NULL; struct vir_region *firstregion;
vir_bytes startv; vir_bytes startv;
int foundflag = 0; int foundflag = 0;
region_iter iter;
/* XXX start search closer to minv to optimise. */
firstregion = region_search_least(&vmp->vm_regions_avl);
SANITYCHECK(SCL_FUNCTIONS); 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", printf("region_find_slot: minv 0x%lx and bytes 0x%lx\n",
minv, length); minv, length);
map_printmap(vmp); 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 < maxv);
assert(minv + length <= maxv); assert(minv + length <= maxv);
#define FREEVRANGE(rangestart, rangeend, foundcode) { \ #define FREEVRANGE(rangestart, rangeend) { \
vir_bytes frstart = (rangestart), frend = (rangeend); \ vir_bytes frstart = (rangestart), frend = (rangeend); \
frstart = MAX(frstart, minv); \ frstart = MAX(frstart, minv); \
frend = MIN(frend, maxv); \ frend = MIN(frend, maxv); \
if(frend > frstart && (frend - frstart) >= length) { \ if(frend > frstart && (frend - frstart) >= length) { \
startv = frstart; \ startv = frstart; \
foundflag = 1; \ foundflag = 1; \
foundcode; \
} } } }
/* 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. */ /* This is the free virtual address space before the first region. */
FREEVRANGE(0, firstregion ? firstregion->vaddr : VM_DATATOP, ;); 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) { if(!foundflag) {
struct vir_region *vr; struct vir_region *vr;
region_iter iter;
region_start_iter_least(&vmp->vm_regions_avl, &iter);
while((vr = region_get_iter(&iter)) && !foundflag) { while((vr = region_get_iter(&iter)) && !foundflag) {
struct vir_region *nextvr; struct vir_region *nextvr;
region_incr_iter(&iter); region_incr_iter(&iter);
nextvr = region_get_iter(&iter); nextvr = region_get_iter(&iter);
FREEVRANGE(vr->vaddr + vr->length, FREEVRANGE(vr->vaddr + vr->length,
nextvr ? nextvr->vaddr : VM_DATATOP, nextvr ? nextvr->vaddr : VM_DATATOP);
prevregion = vr;); 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", 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); length, vmp->vm_endpoint, minv, maxv);
map_printmap(vmp); 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. */ /* However we got it, startv must be in the requested range. */
assert(startv >= minv); assert(startv >= minv);
assert(startv < maxv); assert(startv < maxv);
assert(startv + length <= maxv); assert(startv + length <= maxv);
if (prev) /* remember this position as a hint for next time. */
*prev = prevregion; vmp->vm_region_top = startv + length;
return startv; 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 * * map_page_region *
*===========================================================================*/ *===========================================================================*/
@ -469,7 +494,7 @@ vir_bytes what;
u32_t flags; u32_t flags;
int mapflags; int mapflags;
{ {
struct vir_region *prevregion = NULL, *newregion; struct vir_region *newregion;
vir_bytes startv; vir_bytes startv;
struct phys_region *ph; struct phys_region *ph;
physr_avl *phavl; physr_avl *phavl;
@ -478,8 +503,8 @@ int mapflags;
SANITYCHECK(SCL_FUNCTIONS); SANITYCHECK(SCL_FUNCTIONS);
startv = region_find_slot(vmp, minv, maxv, length, &prevregion); startv = region_find_slot(vmp, minv, maxv, length);
if (startv == (vir_bytes) -1) if (startv == SLOT_FAIL)
return NULL; return NULL;
/* Now we want a new region. */ /* Now we want a new region. */
@ -1305,7 +1330,7 @@ int write;
} }
#if SANITYCHECKS #if SANITYCHECKS
static int countregions(struct vir_region *vr) static int count_phys_regions(struct vir_region *vr)
{ {
int n = 0; int n = 0;
struct phys_region *ph; struct phys_region *ph;
@ -1338,7 +1363,7 @@ PRIVATE struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
physr_avl *phavl; physr_avl *phavl;
#if SANITYCHECKS #if SANITYCHECKS
int cr; int cr;
cr = countregions(vr); cr = count_phys_regions(vr);
#endif #endif
if(!SLABALLOC(newvr)) if(!SLABALLOC(newvr))
@ -1372,13 +1397,13 @@ PRIVATE struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region
#endif #endif
physr_insert(newvr->phys, newph); physr_insert(newvr->phys, newph);
#if SANITYCHECKS #if SANITYCHECKS
assert(countregions(vr) == cr); assert(count_phys_regions(vr) == cr);
#endif #endif
physr_incr_iter(&iter); physr_incr_iter(&iter);
} }
#if SANITYCHECKS #if SANITYCHECKS
assert(countregions(vr) == countregions(newvr)); assert(count_phys_regions(vr) == count_phys_regions(newvr));
#endif #endif
return newvr; 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, PUBLIC int map_remap(struct vmproc *dvmp, vir_bytes da, size_t size,
struct vir_region *region, vir_bytes *r) struct vir_region *region, vir_bytes *r)
{ {
struct vir_region *vr, *prev; struct vir_region *vr;
struct phys_region *ph; struct phys_region *ph;
vir_bytes startv, dst_addr; vir_bytes startv, dst_addr;
physr_iter iter; 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 = da;
dst_addr = arch_vir2map(dvmp, dst_addr); dst_addr = arch_vir2map(dvmp, dst_addr);
prev = NULL;
/* round up to page size */ /* round up to page size */
assert(!(size % VM_PAGE_SIZE)); assert(!(size % VM_PAGE_SIZE));
startv = region_find_slot(dvmp, dst_addr, VM_DATATOP, size, &prev); startv = region_find_slot(dvmp, dst_addr, VM_DATATOP, size);
if (startv == (vir_bytes) -1) { if (startv == SLOT_FAIL) {
printf("map_remap: search 0x%lx...\n", dst_addr); printf("map_remap: search 0x%lx...\n", dst_addr);
map_printmap(dvmp); map_printmap(dvmp);
return ENOMEM; return ENOMEM;

View file

@ -31,6 +31,7 @@ struct vmproc {
/* Regions in virtual address space. */ /* Regions in virtual address space. */
region_avl vm_regions_avl; region_avl vm_regions_avl;
vir_bytes vm_region_top; /* highest vaddr last inserted */
yielded_avl vm_yielded_blocks; /* avl of yielded physblocks */ yielded_avl vm_yielded_blocks; /* avl of yielded physblocks */
/* Heap for brk() to extend. */ /* Heap for brk() to extend. */