vm: break: allow brk() on any region

use the user-supplied point to lookup which region to perform brk() on,
and if it's a reasonable one, do it, no matter what vm's notion of the
heap region is.
This commit is contained in:
Ben Gras 2012-04-07 01:19:28 +02:00
parent 1c7885f932
commit 660e15b2d1
3 changed files with 43 additions and 14 deletions

View file

@ -167,19 +167,11 @@ int real_brk(vmp, v)
struct vmproc *vmp;
vir_bytes v;
{
vir_bytes new_sp;
vir_clicks new_clicks;
int r;
if(!(vmp->vm_flags & VMF_HASPT))
return OK;
new_clicks = (vir_clicks) (CLICK_CEIL(v) >> CLICK_SHIFT);
if (new_clicks < vmp->vm_arch.vm_seg[D].mem_vir) {
printf("VM: real_brk failed because new_clicks too high: %d\n",
new_clicks);
return(ENOMEM);
}
new_clicks -= vmp->vm_arch.vm_seg[D].mem_vir;
if ((r=get_stack_ptr(vmp->vm_endpoint, &new_sp)) != OK)
panic("couldn't get stack pointer: %d", r);
r = adjust(vmp, new_clicks, new_sp);
return r;
if(map_region_extend_upto_v(vmp, v) == OK)
return OK;
return(ENOMEM);
}

View file

@ -144,6 +144,7 @@ struct vir_region * map_page_region(struct vmproc *vmp, vir_bytes min,
struct vir_region * map_proc_kernel(struct vmproc *dst);
int map_region_extend(struct vmproc *vmp, struct vir_region *vr,
vir_bytes delta);
int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes vir);
int map_region_shrink(struct vir_region *vr, vir_bytes delta);
int map_unmap_region(struct vmproc *vmp, struct vir_region *vr,
vir_bytes len);

View file

@ -1665,6 +1665,42 @@ struct vir_region *map_proc_kernel(struct vmproc *vmp)
return vr; /* Return pointer not useful, just non-NULL. */
}
int map_region_extend_upto_v(struct vmproc *vmp, vir_bytes v)
{
vir_bytes offset, o, end;
struct vir_region *vr, *nextvr;
offset = arch_vir2map(vmp, v);
if((o=(offset % VM_PAGE_SIZE))) {
offset+= VM_PAGE_SIZE - o;
}
if(!(vr = region_search(&vmp->vm_regions_avl, offset, AVL_LESS_EQUAL))) {
printf("VM: nothing to extend\n");
return ENOMEM;
}
if(!(vr->flags & VR_ANON)) {
printf("VM: memory range to extend not anonymous\n");
return ENOMEM;
}
assert(vr->vaddr <= offset);
if((nextvr = getnextvr(vr))) {
assert(offset < nextvr->vaddr);
}
end = vr->vaddr + vr->length;
if(offset < end)
return map_region_shrink(vr, end - offset);
return map_region_extend(vmp, vr, offset - end);
return ENOMEM;
}
/*========================================================================*
* map_region_extend *
*========================================================================*/