summaryrefslogtreecommitdiff
path: root/kernel/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/proc.c')
-rw-r--r--kernel/proc.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/kernel/proc.c b/kernel/proc.c
index c12d97e..8ea09b5 100644
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -111,6 +111,30 @@ 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->sz = 0;
+ p->pid = 0;
+ p->parent = 0;
+ p->name[0] = 0;
+ p->chan = 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
@@ -147,7 +171,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")
@@ -226,7 +251,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;
@@ -342,17 +370,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(&np->lock);
release(&p->lock);
return pid;