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);
printf("region_find_slot: minv 0x%lx and bytes 0x%lx\n",
minv, length);
map_printmap(vmp);
- return (vir_bytes) -1;
+ return SLOT_FAIL;
}
}
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);
+ }
}
}
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 *
*===========================================================================*/
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;
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. */
}
#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;
physr_avl *phavl;
#if SANITYCHECKS
int cr;
- cr = countregions(vr);
+ cr = count_phys_regions(vr);
#endif
if(!SLABALLOC(newvr))
#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;
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;
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;