提交 ba45ab30 创建 作者: Robert Morris's avatar Robert Morris

sbrk() (growproc()) can now allocate vmas

try to be careful not to tread on existing vmas (e.g. stack)
上级 01c040d3
...@@ -173,22 +173,71 @@ userinit(void) ...@@ -173,22 +173,71 @@ userinit(void)
int int
growproc(int n) growproc(int n)
{ {
uint brk = proc->brk; struct vmap *m = proc->vmap;
uint nbrk = brk + n;
struct vma *vma = vmap_lookup(proc->vmap, brk-1); if(n < 0 || n > USERTOP || proc->brk + n > USERTOP)
if(vma == 0)
return -1; return -1;
if(nbrk > vma->va_end){ acquire(&m->lock);
/* XXX */
release(&vma->lock); // find first unallocated address in brk..brk+n
cprintf("cannot resize heap: %d -> %d\n", brk, nbrk); uint newstart = proc->brk;
uint newn = n;
while(newn > 0){
int ind = vmap_overlap(m, newstart, 1);
if(ind == -1)
break;
if(m->e[ind].va_end >= newstart + newn){
newstart += newn;
newn = 0;
break;
}
newn -= m->e[ind].va_end - newstart;
newstart = m->e[ind].va_end;
}
if(newn <= 0){
// no need to allocate
proc->brk += n;
release(&m->lock);
switchuvm(proc);
return 0;
}
// is there space for newstart..newstart+newn?
if(vmap_overlap(m, newstart, newn) != -1){
release(&m->lock);
cprintf("growproc: not enough room in address space; brk %d n %d\n",
proc->brk, n);
return -1;
}
// would the newly allocated region abut the next-higher
// vma? we can't allow that, since then a future sbrk()
// would start to use the next region (e.g. the stack).
if(vmap_overlap(m, PGROUNDUP(newstart+newn), 1) != -1){
release(&m->lock);
cprintf("growproc: would abut next vma; brk %d n %d\n",
proc->brk, n);
return -1;
}
struct vmnode *vmn = vmn_allocpg(PGROUNDUP(newn) / PGSIZE);
if(vmn == 0){
release(&m->lock);
cprintf("growproc: vmn_allocpg failed\n");
return -1;
}
release(&m->lock); // XXX
if(vmap_insert(m, vmn, newstart) < 0){
vmn_free(vmn);
cprintf("growproc: vmap_insert failed\n");
return -1; return -1;
} }
proc->brk = brk + n; proc->brk += n;
release(&vma->lock);
switchuvm(proc); switchuvm(proc);
return 0; return 0;
} }
......
...@@ -35,7 +35,7 @@ enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE }; ...@@ -35,7 +35,7 @@ enum procstate { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
enum vmntype { EAGER, ONDEMAND}; enum vmntype { EAGER, ONDEMAND};
struct vmnode { struct vmnode {
uint npages; uint npages;
char *page[32]; char *page[128];
uint ref; uint ref;
uint alloc; // in use? uint alloc; // in use?
enum vmntype type; enum vmntype type;
......
...@@ -1272,23 +1272,25 @@ sbrktest(void) ...@@ -1272,23 +1272,25 @@ sbrktest(void)
wait(); wait();
// can one allocate the full 640K? // can one allocate the full 640K?
// less a stack page and an empty page at the top.
a = sbrk(0); a = sbrk(0);
amt = (640 * 1024) - (uint)a; amt = (632 * 1024) - (uint)a;
p = sbrk(amt); p = sbrk(amt);
if(p != a){ if(p != a){
printf(stdout, "sbrk test failed 640K test, p %x a %x\n", p, a); printf(stdout, "sbrk test failed 632K test, p %x a %x\n", p, a);
exit(); exit();
} }
lastaddr = (char*)(640 * 1024 - 1); lastaddr = (char*)(632 * 1024 - 1);
*lastaddr = 99; *lastaddr = 99;
// is one forbidden from allocating more than 640K? // is one forbidden from allocating more than 632K?
c = sbrk(4096); c = sbrk(4096);
if(c != (char*)0xffffffff){ if(c != (char*)0xffffffff){
printf(stdout, "sbrk allocated more than 640K, c %x\n", c); printf(stdout, "sbrk allocated more than 632K, c %x\n", c);
exit(); exit();
} }
#if 0
// can one de-allocate? // can one de-allocate?
a = sbrk(0); a = sbrk(0);
c = sbrk(-4096); c = sbrk(-4096);
...@@ -1314,10 +1316,11 @@ sbrktest(void) ...@@ -1314,10 +1316,11 @@ sbrktest(void)
printf(stdout, "sbrk de-allocation didn't really deallocate\n"); printf(stdout, "sbrk de-allocation didn't really deallocate\n");
exit(); exit();
} }
#endif
c = sbrk(4096); c = sbrk(4096);
if(c != (char*)0xffffffff){ if(c != (char*)0xffffffff){
printf(stdout, "sbrk was able to re-allocate beyond 640K, c %x\n", c); printf(stdout, "sbrk was able to re-allocate beyond 632K, c %x\n", c);
exit(); exit();
} }
...@@ -1346,8 +1349,8 @@ sbrktest(void) ...@@ -1346,8 +1349,8 @@ sbrktest(void)
} }
for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){ for(i = 0; i < sizeof(pids)/sizeof(pids[0]); i++){
if((pids[i] = fork(0)) == 0){ if((pids[i] = fork(0)) == 0){
// allocate the full 640K // allocate the full 632K
sbrk((640 * 1024) - (uint)sbrk(0)); sbrk((632 * 1024) - (uint)sbrk(0));
write(fds[1], "x", 1); write(fds[1], "x", 1);
// sit around until killed // sit around until killed
for(;;) sleep(1000); for(;;) sleep(1000);
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论