diff options
author | Robert Morris <[email protected]> | 2019-07-01 17:46:06 -0400 |
---|---|---|
committer | Robert Morris <[email protected]> | 2019-07-01 17:46:06 -0400 |
commit | abfe9999f447c15d904b3c11f32d4a22a45470a0 (patch) | |
tree | bdcf8264c9da666661b107157a6c634b86608ee2 /kernel | |
parent | 18e76a6c47b0f62b2458430d4357f3eb68bfd759 (diff) | |
download | xv6-labs-abfe9999f447c15d904b3c11f32d4a22a45470a0.tar.gz xv6-labs-abfe9999f447c15d904b3c11f32d4a22a45470a0.tar.bz2 xv6-labs-abfe9999f447c15d904b3c11f32d4a22a45470a0.zip |
have fork() fail, not panic, if not enough phys mem
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/defs.h | 2 | ||||
-rw-r--r-- | kernel/proc.c | 42 | ||||
-rw-r--r-- | kernel/vm.c | 11 |
3 files changed, 39 insertions, 16 deletions
diff --git a/kernel/defs.h b/kernel/defs.h index 1b397fe..1c0b39a 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -185,7 +185,7 @@ pagetable_t uvmcreate(void); void uvminit(pagetable_t, uchar *, uint); uint64 uvmalloc(pagetable_t, uint64, uint64); uint64 uvmdealloc(pagetable_t, uint64, uint64); -void uvmcopy(pagetable_t, pagetable_t, uint64); +int uvmcopy(pagetable_t, pagetable_t, uint64); void uvmfree(pagetable_t, uint64); void mappages(pagetable_t, uint64, uint64, uint64, int); void unmappages(pagetable_t, uint64, uint64, int); diff --git a/kernel/proc.c b/kernel/proc.c index 4ae34c8..e0ee965 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -109,6 +109,28 @@ found: return p; } +// free a proc structure and the data hanging from it, +// including user pages. +// the proc lock must be held. +static void +freeproc(struct proc *p) +{ + if(p->kstack) + kfree(p->kstack); + p->kstack = 0; + if(p->tf) + kfree((void*)p->tf); + p->tf = 0; + if(p->pagetable) + proc_freepagetable(p->pagetable, p->sz); + p->pagetable = 0; + p->pid = 0; + p->parent = 0; + p->name[0] = 0; + p->killed = 0; + p->state = UNUSED; +} + // Create a page table for a given process, // with no users pages, but with trampoline pages. // Called both when creating a process, and @@ -145,7 +167,8 @@ proc_freepagetable(pagetable_t pagetable, uint64 sz) { unmappages(pagetable, TRAMPOLINE, PGSIZE, 0); unmappages(pagetable, TRAMPOLINE-PGSIZE, PGSIZE, 0); - uvmfree(pagetable, sz); + if(sz > 0) + uvmfree(pagetable, sz); } // a user program that calls exec("/init") @@ -223,7 +246,10 @@ fork(void) } // Copy user memory from parent to child. - uvmcopy(p->pagetable, np->pagetable, p->sz); + if(uvmcopy(p->pagetable, np->pagetable, p->sz) < 0){ + freeproc(np); + return -1; + } np->sz = p->sz; np->parent = p; @@ -319,17 +345,7 @@ wait(void) if(np->state == ZOMBIE){ // Found one. pid = np->pid; - kfree(np->kstack); - np->kstack = 0; - kfree((void*)np->tf); - np->tf = 0; - proc_freepagetable(np->pagetable, np->sz); - np->pagetable = 0; - np->pid = 0; - np->parent = 0; - np->name[0] = 0; - np->killed = 0; - np->state = UNUSED; + freeproc(np); release(&ptable.lock); return pid; } diff --git a/kernel/vm.c b/kernel/vm.c index 580669f..7d67464 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -273,7 +273,9 @@ uvmfree(pagetable_t pagetable, uint64 sz) // its memory into a child's page table. // Copies both the page table and the // physical memory. -void +// returns 0 on success, -1 on failure. +// frees any allocated pages on failure. +int uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) { pte_t *pte; @@ -289,10 +291,15 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz) pa = PTE2PA(*pte); flags = PTE_FLAGS(*pte); if((mem = kalloc()) == 0) - panic("uvmcopy: kalloc failed"); + goto err; memmove(mem, (char*)pa, PGSIZE); mappages(new, i, PGSIZE, (uint64)mem, flags); } + return 0; + + err: + unmappages(new, 0, i, 1); + return -1; } // Copy from kernel to user. |