summaryrefslogtreecommitdiff
path: root/proc.c
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2011-07-27 20:49:45 -0400
committerFrans Kaashoek <[email protected]>2011-07-27 20:49:45 -0400
commitdccb915282854476ce47752df6631dcce3b8f661 (patch)
treea84aa8ed35618f99c3d7e8cdd466d22ae7bad597 /proc.c
parent9acdfe0d04f3fcf95c6e392e08afb45bdfe16c20 (diff)
parent13a96baefc0ff5d8262c4bc8c797bee4b157443c (diff)
downloadxv6-labs-dccb915282854476ce47752df6631dcce3b8f661.tar.gz
xv6-labs-dccb915282854476ce47752df6631dcce3b8f661.tar.bz2
xv6-labs-dccb915282854476ce47752df6631dcce3b8f661.zip
Merge commit 'origin/master' into page
Diffstat (limited to 'proc.c')
-rw-r--r--proc.c257
1 files changed, 131 insertions, 126 deletions
diff --git a/proc.c b/proc.c
index 5ac2780..eb334d0 100644
--- a/proc.c
+++ b/proc.c
@@ -17,53 +17,18 @@ int nextpid = 1;
extern void forkret(void);
extern void trapret(void);
+static void wakeup1(void *chan);
+
void
pinit(void)
{
initlock(&ptable.lock, "ptable");
}
-//PAGEBREAK: 36
-// Print a process listing to console. For debugging.
-// Runs when user types ^P on console.
-// No lock to avoid wedging a stuck machine further.
-void
-procdump(void)
-{
- static char *states[] = {
- [UNUSED] "unused",
- [EMBRYO] "embryo",
- [SLEEPING] "sleep ",
- [RUNNABLE] "runble",
- [RUNNING] "run ",
- [ZOMBIE] "zombie"
- };
- int i;
- struct proc *p;
- char *state;
- uint pc[10];
-
- for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
- if(p->state == UNUSED)
- continue;
- if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
- state = states[p->state];
- else
- state = "???";
- cprintf("%d %s %s", p->pid, state, p->name);
- if(p->state == SLEEPING){
- getcallerpcs((uint*)p->context->ebp+2, pc);
- for(i=0; i<10 && pc[i] != 0; i++)
- cprintf(" %p", pc[i]);
- }
- cprintf("\n");
- }
-}
-
-
//PAGEBREAK: 32
// Look in the process table for an UNUSED proc.
-// If found, change state to EMBRYO and return it.
+// If found, change state to EMBRYO and initialize
+// state required to run in the kernel.
// Otherwise return 0.
static struct proc*
allocproc(void)
@@ -95,7 +60,7 @@ found:
p->tf = (struct trapframe*)sp;
// Set up new context to start executing at forkret,
- // which returns to trapret (see below).
+ // which returns to trapret.
sp -= 4;
*(uint*)sp = (uint)trapret;
@@ -103,6 +68,7 @@ found:
p->context = (struct context*)sp;
memset(p->context, 0, sizeof *p->context);
p->context->eip = (uint)forkret;
+
return p;
}
@@ -116,12 +82,10 @@ userinit(void)
p = allocproc();
initproc = p;
- if (!(p->pgdir = setupkvm()))
+ if((p->pgdir = setupkvm()) == 0)
panic("userinit: out of memory?");
- if (!allocuvm(p->pgdir, 0x0, (int)_binary_initcode_size))
- panic("userinit: out of memory?");
- inituvm(p->pgdir, 0x0, _binary_initcode_start, (int)_binary_initcode_size);
- p->sz = PGROUNDUP((int)_binary_initcode_size);
+ inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
+ p->sz = PGSIZE;
memset(p->tf, 0, sizeof(*p->tf));
p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
@@ -142,14 +106,17 @@ userinit(void)
int
growproc(int n)
{
+ uint sz;
+
+ sz = proc->sz;
if(n > 0){
- if (!allocuvm(proc->pgdir, (char *)proc->sz, n))
+ if((sz = allocuvm(proc->pgdir, sz, sz + n)) == 0)
return -1;
} else if(n < 0){
- if (!deallocuvm(proc->pgdir, (char *)(proc->sz + n), 0 - n))
+ if((sz = deallocuvm(proc->pgdir, sz, sz + n)) == 0)
return -1;
}
- proc->sz += n;
+ proc->sz = sz;
switchuvm(proc);
return 0;
}
@@ -168,7 +135,7 @@ fork(void)
return -1;
// Copy process state from p.
- if (!(np->pgdir = copyuvm(proc->pgdir, proc->sz))) {
+ if((np->pgdir = copyuvm(proc->pgdir, proc->sz)) == 0){
kfree(np->kstack);
np->kstack = 0;
np->state = UNUSED;
@@ -192,6 +159,92 @@ fork(void)
return pid;
}
+// Exit the current process. Does not return.
+// An exited process remains in the zombie state
+// until its parent calls wait() to find out it exited.
+void
+exit(void)
+{
+ struct proc *p;
+ int fd;
+
+ if(proc == initproc)
+ panic("init exiting");
+
+ // Close all open files.
+ for(fd = 0; fd < NOFILE; fd++){
+ if(proc->ofile[fd]){
+ fileclose(proc->ofile[fd]);
+ proc->ofile[fd] = 0;
+ }
+ }
+
+ iput(proc->cwd);
+ proc->cwd = 0;
+
+ acquire(&ptable.lock);
+
+ // Parent might be sleeping in wait().
+ wakeup1(proc->parent);
+
+ // Pass abandoned children to init.
+ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
+ if(p->parent == proc){
+ p->parent = initproc;
+ if(p->state == ZOMBIE)
+ wakeup1(initproc);
+ }
+ }
+
+ // Jump into the scheduler, never to return.
+ proc->state = ZOMBIE;
+ sched();
+ panic("zombie exit");
+}
+
+// Wait for a child process to exit and return its pid.
+// Return -1 if this process has no children.
+int
+wait(void)
+{
+ struct proc *p;
+ int havekids, pid;
+
+ acquire(&ptable.lock);
+ for(;;){
+ // Scan through table looking for zombie children.
+ havekids = 0;
+ for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
+ if(p->parent != proc)
+ continue;
+ havekids = 1;
+ if(p->state == ZOMBIE){
+ // Found one.
+ pid = p->pid;
+ kfree(p->kstack);
+ p->kstack = 0;
+ freevm(p->pgdir);
+ p->state = UNUSED;
+ p->pid = 0;
+ p->parent = 0;
+ p->name[0] = 0;
+ p->killed = 0;
+ release(&ptable.lock);
+ return pid;
+ }
+ }
+
+ // No point waiting if we don't have any children.
+ if(!havekids || proc->killed){
+ release(&ptable.lock);
+ return -1;
+ }
+
+ // Wait for children to exit. (See wakeup1 call in proc_exit.)
+ sleep(proc, &ptable.lock); //DOC: wait-sleep
+ }
+}
+
//PAGEBREAK: 42
// Per-CPU process scheduler.
// Each CPU calls scheduler() after setting itself up.
@@ -356,89 +409,41 @@ kill(int pid)
return -1;
}
-// Exit the current process. Does not return.
-// An exited process remains in the zombie state
-// until its parent calls wait() to find out it exited.
+//PAGEBREAK: 36
+// Print a process listing to console. For debugging.
+// Runs when user types ^P on console.
+// No lock to avoid wedging a stuck machine further.
void
-exit(void)
+procdump(void)
{
+ static char *states[] = {
+ [UNUSED] "unused",
+ [EMBRYO] "embryo",
+ [SLEEPING] "sleep ",
+ [RUNNABLE] "runble",
+ [RUNNING] "run ",
+ [ZOMBIE] "zombie"
+ };
+ int i;
struct proc *p;
- int fd;
-
- if(proc == initproc)
- panic("init exiting");
-
- // Close all open files.
- for(fd = 0; fd < NOFILE; fd++){
- if(proc->ofile[fd]){
- fileclose(proc->ofile[fd]);
- proc->ofile[fd] = 0;
- }
- }
-
- iput(proc->cwd);
- proc->cwd = 0;
-
- acquire(&ptable.lock);
-
- // Parent might be sleeping in wait().
- wakeup1(proc->parent);
-
- // Pass abandoned children to init.
+ char *state;
+ uint pc[10];
+
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
- if(p->parent == proc){
- p->parent = initproc;
- if(p->state == ZOMBIE)
- wakeup1(initproc);
+ if(p->state == UNUSED)
+ continue;
+ if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
+ state = states[p->state];
+ else
+ state = "???";
+ cprintf("%d %s %s", p->pid, state, p->name);
+ if(p->state == SLEEPING){
+ getcallerpcs((uint*)p->context->ebp+2, pc);
+ for(i=0; i<10 && pc[i] != 0; i++)
+ cprintf(" %p", pc[i]);
}
+ cprintf("\n");
}
-
- // Jump into the scheduler, never to return.
- proc->state = ZOMBIE;
- sched();
- panic("zombie exit");
}
-// Wait for a child process to exit and return its pid.
-// Return -1 if this process has no children.
-int
-wait(void)
-{
- struct proc *p;
- int havekids, pid;
-
- acquire(&ptable.lock);
- for(;;){
- // Scan through table looking for zombie children.
- havekids = 0;
- for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
- if(p->parent != proc)
- continue;
- havekids = 1;
- if(p->state == ZOMBIE){
- // Found one.
- pid = p->pid;
- kfree(p->kstack);
- p->kstack = 0;
- freevm(p->pgdir);
- p->state = UNUSED;
- p->pid = 0;
- p->parent = 0;
- p->name[0] = 0;
- p->killed = 0;
- release(&ptable.lock);
- return pid;
- }
- }
-
- // No point waiting if we don't have any children.
- if(!havekids || proc->killed){
- release(&ptable.lock);
- return -1;
- }
-
- // Wait for children to exit. (See wakeup1 call in proc_exit.)
- sleep(proc, &ptable.lock); //DOC: wait-sleep
- }
-}