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
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

View 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;

View 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;

View 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. */