From 660e15b2d125d7c54c2e2ba7da692c47e3fe88bf Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Sat, 7 Apr 2012 01:19:28 +0200 Subject: [PATCH] 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. --- servers/vm/break.c | 20 ++++++-------------- servers/vm/proto.h | 1 + servers/vm/region.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/servers/vm/break.c b/servers/vm/break.c index 6882bc1ac..bc4a0687a 100644 --- a/servers/vm/break.c +++ b/servers/vm/break.c @@ -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); } diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 0d3ea3f8a..14dd12feb 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -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); diff --git a/servers/vm/region.c b/servers/vm/region.c index 2a3cabeba..744ad3ee6 100644 --- a/servers/vm/region.c +++ b/servers/vm/region.c @@ -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 * *========================================================================*/