xref: /xv6-public/proc.c (revision 4638cabf)
155e95b16Srtm #include "types.h"
2558ab49fSrsc #include "defs.h"
3558ab49fSrsc #include "param.h"
49aa0337dSFrans Kaashoek #include "memlayout.h"
555e95b16Srtm #include "mmu.h"
655e95b16Srtm #include "x86.h"
7df5cc916Srtm #include "proc.h"
84e8f237bSrtm #include "spinlock.h"
94e8f237bSrtm 
1034295f46Srsc struct {
1134295f46Srsc   struct spinlock lock;
1255e95b16Srtm   struct proc proc[NPROC];
1334295f46Srsc } ptable;
1434295f46Srsc 
153a057d12Srsc static struct proc *initproc;
163a057d12Srsc 
17eaea18cbSrsc int nextpid = 1;
1865bd8e13Srsc extern void forkret(void);
192c5f7abaSRuss Cox extern void trapret(void);
2055e95b16Srtm 
21c7c21467SAustin Clements static void wakeup1(void *chan);
22c7c21467SAustin Clements 
235be0039cSrtm void
pinit(void)245be0039cSrtm pinit(void)
255be0039cSrtm {
2634295f46Srsc   initlock(&ptable.lock, "ptable");
275be0039cSrtm }
285be0039cSrtm 
29ed396c06SFrans Kaashoek // Must be called with interrupts disabled
30abf847a0SFrans Kaashoek int
cpuid()31abf847a0SFrans Kaashoek cpuid() {
32abf847a0SFrans Kaashoek   return mycpu()-cpus;
33abf847a0SFrans Kaashoek }
34abf847a0SFrans Kaashoek 
35*4638cabfSRobert Morris // Must be called with interrupts disabled to avoid the caller being
36*4638cabfSRobert Morris // rescheduled between reading lapicid and running through the loop.
37ed396c06SFrans Kaashoek struct cpu*
mycpu(void)38ed396c06SFrans Kaashoek mycpu(void)
39ed396c06SFrans Kaashoek {
40c9fa90f7SFrans Kaashoek   int apicid, i;
41c9fa90f7SFrans Kaashoek 
422e2d14c2SFrans Kaashoek   if(readeflags()&FL_IF)
432e2d14c2SFrans Kaashoek     panic("mycpu called with interrupts enabled\n");
44c9fa90f7SFrans Kaashoek 
45c9fa90f7SFrans Kaashoek   apicid = lapicid();
46c9fa90f7SFrans Kaashoek   // APIC IDs are not guaranteed to be contiguous. Maybe we should have
47c9fa90f7SFrans Kaashoek   // a reverse map, or reserve a register to store &cpus[i].
48c9fa90f7SFrans Kaashoek   for (i = 0; i < ncpu; ++i) {
49c9fa90f7SFrans Kaashoek     if (cpus[i].apicid == apicid)
50c9fa90f7SFrans Kaashoek       return &cpus[i];
51c9fa90f7SFrans Kaashoek   }
52c9fa90f7SFrans Kaashoek   panic("unknown apicid\n");
53ed396c06SFrans Kaashoek }
54ed396c06SFrans Kaashoek 
55fbb4c094SFrans Kaashoek // Disable interrupts so that we are not rescheduled
56fbb4c094SFrans Kaashoek // while reading proc from the cpu structure
57fbb4c094SFrans Kaashoek struct proc*
myproc(void)58fbb4c094SFrans Kaashoek myproc(void) {
59fbb4c094SFrans Kaashoek   struct cpu *c;
60fbb4c094SFrans Kaashoek   struct proc *p;
61fbb4c094SFrans Kaashoek   pushcli();
62fbb4c094SFrans Kaashoek   c = mycpu();
63fbb4c094SFrans Kaashoek   p = c->proc;
64fbb4c094SFrans Kaashoek   popcli();
65fbb4c094SFrans Kaashoek   return p;
66abf847a0SFrans Kaashoek }
67abf847a0SFrans Kaashoek 
68c9ee77b8SRuss Cox //PAGEBREAK: 32
69eaea18cbSrsc // Look in the process table for an UNUSED proc.
70faad047aSRobert Morris // If found, change state to EMBRYO and initialize
71faad047aSRobert Morris // state required to run in the kernel.
72eaea18cbSrsc // Otherwise return 0.
73eaea18cbSrsc static struct proc*
allocproc(void)74eaea18cbSrsc allocproc(void)
7555e95b16Srtm {
76eaea18cbSrsc   struct proc *p;
772c5f7abaSRuss Cox   char *sp;
78350e63f7Srtm 
79aeaa3089SRobert Morris   acquire(&ptable.lock);
80aeaa3089SRobert Morris 
812c5f7abaSRuss Cox   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
822c5f7abaSRuss Cox     if(p->state == UNUSED)
8319333efbSrsc       goto found;
84aeaa3089SRobert Morris 
85aeaa3089SRobert Morris   release(&ptable.lock);
86eaea18cbSrsc   return 0;
8719333efbSrsc 
8819333efbSrsc found:
892c5f7abaSRuss Cox   p->state = EMBRYO;
902c5f7abaSRuss Cox   p->pid = nextpid++;
9119333efbSrsc 
92aeaa3089SRobert Morris   release(&ptable.lock);
93aeaa3089SRobert Morris 
945a236924SRobert Morris   // Allocate kernel stack.
957d7dc933SRobert Morris   if((p->kstack = kalloc()) == 0){
9619333efbSrsc     p->state = UNUSED;
9719333efbSrsc     return 0;
9819333efbSrsc   }
992c5f7abaSRuss Cox   sp = p->kstack + KSTACKSIZE;
10019333efbSrsc 
1012c5f7abaSRuss Cox   // Leave room for trap frame.
1022c5f7abaSRuss Cox   sp -= sizeof *p->tf;
1032c5f7abaSRuss Cox   p->tf = (struct trapframe*)sp;
1042c5f7abaSRuss Cox 
1052c5f7abaSRuss Cox   // Set up new context to start executing at forkret,
106faad047aSRobert Morris   // which returns to trapret.
1072c5f7abaSRuss Cox   sp -= 4;
1082c5f7abaSRuss Cox   *(uint*)sp = (uint)trapret;
1092c5f7abaSRuss Cox 
1102c5f7abaSRuss Cox   sp -= sizeof *p->context;
1112c5f7abaSRuss Cox   p->context = (struct context*)sp;
1122c5f7abaSRuss Cox   memset(p->context, 0, sizeof *p->context);
11319333efbSrsc   p->context->eip = (uint)forkret;
114faad047aSRobert Morris 
11519333efbSrsc   return p;
11655e95b16Srtm }
11755e95b16Srtm 
118c9ee77b8SRuss Cox //PAGEBREAK: 32
1190aef8914SRuss Cox // Set up first user process.
1200aef8914SRuss Cox void
userinit(void)1210aef8914SRuss Cox userinit(void)
1220aef8914SRuss Cox {
1230aef8914SRuss Cox   struct proc *p;
1240aef8914SRuss Cox   extern char _binary_initcode_start[], _binary_initcode_size[];
1250aef8914SRuss Cox 
1260aef8914SRuss Cox   p = allocproc();
127d63ac118SRobert Morris 
1280aef8914SRuss Cox   initproc = p;
1294ce832ddSFrans Kaashoek   if((p->pgdir = setupkvm()) == 0)
13040889627SFrans Kaashoek     panic("userinit: out of memory?");
131f53e6110SAustin Clements   inituvm(p->pgdir, _binary_initcode_start, (int)_binary_initcode_size);
132f53e6110SAustin Clements   p->sz = PGSIZE;
1330aef8914SRuss Cox   memset(p->tf, 0, sizeof(*p->tf));
1340aef8914SRuss Cox   p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
1350aef8914SRuss Cox   p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
1360aef8914SRuss Cox   p->tf->es = p->tf->ds;
1370aef8914SRuss Cox   p->tf->ss = p->tf->ds;
1380aef8914SRuss Cox   p->tf->eflags = FL_IF;
13940889627SFrans Kaashoek   p->tf->esp = PGSIZE;
1400aef8914SRuss Cox   p->tf->eip = 0;  // beginning of initcode.S
1410aef8914SRuss Cox 
1420aef8914SRuss Cox   safestrcpy(p->name, "initcode", sizeof(p->name));
1430aef8914SRuss Cox   p->cwd = namei("/");
1440aef8914SRuss Cox 
145d63ac118SRobert Morris   // this assignment to p->state lets other cores
146d63ac118SRobert Morris   // run this process. the acquire forces the above
147d63ac118SRobert Morris   // writes to be visible, and the lock is also needed
148d63ac118SRobert Morris   // because the assignment might not be atomic.
149d63ac118SRobert Morris   acquire(&ptable.lock);
150d63ac118SRobert Morris 
1510aef8914SRuss Cox   p->state = RUNNABLE;
15219f65413SRobert Morris 
15319f65413SRobert Morris   release(&ptable.lock);
1540aef8914SRuss Cox }
1550aef8914SRuss Cox 
1561656b1b2Srsc // Grow current process's memory by n bytes.
15719333efbSrsc // Return 0 on success, -1 on failure.
1581656b1b2Srsc int
growproc(int n)1591656b1b2Srsc growproc(int n)
1601656b1b2Srsc {
1611a81e38bSRuss Cox   uint sz;
162fbb4c094SFrans Kaashoek   struct proc *curproc = myproc();
1631a81e38bSRuss Cox 
164fbb4c094SFrans Kaashoek   sz = curproc->sz;
16583d2db91SRobert Morris   if(n > 0){
166fbb4c094SFrans Kaashoek     if((sz = allocuvm(curproc->pgdir, sz, sz + n)) == 0)
167dd868974Srsc       return -1;
16883d2db91SRobert Morris   } else if(n < 0){
169fbb4c094SFrans Kaashoek     if((sz = deallocuvm(curproc->pgdir, sz, sz + n)) == 0)
17083d2db91SRobert Morris       return -1;
17183d2db91SRobert Morris   }
172fbb4c094SFrans Kaashoek   curproc->sz = sz;
173fbb4c094SFrans Kaashoek   switchuvm(curproc);
17419333efbSrsc   return 0;
1751656b1b2Srsc }
1761656b1b2Srsc 
177856e1fc1Srsc // Create a new process copying p as the parent.
178eaea18cbSrsc // Sets up stack to return as if from system call.
179eaea18cbSrsc // Caller must set state of returned proc to RUNNABLE.
18021573833Srsc int
fork(void)18121573833Srsc fork(void)
182856e1fc1Srsc {
18321573833Srsc   int i, pid;
18455e95b16Srtm   struct proc *np;
185fbb4c094SFrans Kaashoek   struct proc *curproc = myproc();
18655e95b16Srtm 
187856e1fc1Srsc   // Allocate process.
18819f65413SRobert Morris   if((np = allocproc()) == 0){
18921573833Srsc     return -1;
19019f65413SRobert Morris   }
1914e8f237bSrtm 
192abf847a0SFrans Kaashoek   // Copy process state from proc.
193fbb4c094SFrans Kaashoek   if((np->pgdir = copyuvm(curproc->pgdir, curproc->sz)) == 0){
1947d7dc933SRobert Morris     kfree(np->kstack);
195f32f3638Srsc     np->kstack = 0;
1964e8f237bSrtm     np->state = UNUSED;
19721573833Srsc     return -1;
19855e95b16Srtm   }
199fbb4c094SFrans Kaashoek   np->sz = curproc->sz;
200fbb4c094SFrans Kaashoek   np->parent = curproc;
201fbb4c094SFrans Kaashoek   *np->tf = *curproc->tf;
20221573833Srsc 
20321573833Srsc   // Clear %eax so that fork returns 0 in the child.
20421573833Srsc   np->tf->eax = 0;
205856e1fc1Srsc 
2061ccff18bSrsc   for(i = 0; i < NOFILE; i++)
207fbb4c094SFrans Kaashoek     if(curproc->ofile[i])
208fbb4c094SFrans Kaashoek       np->ofile[i] = filedup(curproc->ofile[i]);
209fbb4c094SFrans Kaashoek   np->cwd = idup(curproc->cwd);
210856e1fc1Srsc 
211fbb4c094SFrans Kaashoek   safestrcpy(np->name, curproc->name, sizeof(curproc->name));
212020c8e23SRobert Morris 
213020c8e23SRobert Morris   pid = np->pid;
214020c8e23SRobert Morris 
215d63ac118SRobert Morris   acquire(&ptable.lock);
216d63ac118SRobert Morris 
217020c8e23SRobert Morris   np->state = RUNNABLE;
21819f65413SRobert Morris 
219020c8e23SRobert Morris   release(&ptable.lock);
220020c8e23SRobert Morris 
22121573833Srsc   return pid;
22255e95b16Srtm }
22355e95b16Srtm 
224d8828817SAustin Clements // Exit the current process.  Does not return.
225d8828817SAustin Clements // An exited process remains in the zombie state
226d8828817SAustin Clements // until its parent calls wait() to find out it exited.
227d8828817SAustin Clements void
exit(void)228d8828817SAustin Clements exit(void)
229d8828817SAustin Clements {
230fbb4c094SFrans Kaashoek   struct proc *curproc = myproc();
231d8828817SAustin Clements   struct proc *p;
232d8828817SAustin Clements   int fd;
233d8828817SAustin Clements 
234fbb4c094SFrans Kaashoek   if(curproc == initproc)
235d8828817SAustin Clements     panic("init exiting");
236d8828817SAustin Clements 
237d8828817SAustin Clements   // Close all open files.
238d8828817SAustin Clements   for(fd = 0; fd < NOFILE; fd++){
239fbb4c094SFrans Kaashoek     if(curproc->ofile[fd]){
240fbb4c094SFrans Kaashoek       fileclose(curproc->ofile[fd]);
241fbb4c094SFrans Kaashoek       curproc->ofile[fd] = 0;
242d8828817SAustin Clements     }
243d8828817SAustin Clements   }
244d8828817SAustin Clements 
24571453f72SRobert Morris   begin_op();
246fbb4c094SFrans Kaashoek   iput(curproc->cwd);
24771453f72SRobert Morris   end_op();
248fbb4c094SFrans Kaashoek   curproc->cwd = 0;
249d8828817SAustin Clements 
250d8828817SAustin Clements   acquire(&ptable.lock);
251d8828817SAustin Clements 
252d8828817SAustin Clements   // Parent might be sleeping in wait().
253fbb4c094SFrans Kaashoek   wakeup1(curproc->parent);
254d8828817SAustin Clements 
255d8828817SAustin Clements   // Pass abandoned children to init.
256d8828817SAustin Clements   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
257fbb4c094SFrans Kaashoek     if(p->parent == curproc){
258d8828817SAustin Clements       p->parent = initproc;
259d8828817SAustin Clements       if(p->state == ZOMBIE)
260d8828817SAustin Clements         wakeup1(initproc);
261d8828817SAustin Clements     }
262d8828817SAustin Clements   }
263d8828817SAustin Clements 
264d8828817SAustin Clements   // Jump into the scheduler, never to return.
265fbb4c094SFrans Kaashoek   curproc->state = ZOMBIE;
266d8828817SAustin Clements   sched();
267d8828817SAustin Clements   panic("zombie exit");
268d8828817SAustin Clements }
269d8828817SAustin Clements 
270d8828817SAustin Clements // Wait for a child process to exit and return its pid.
271d8828817SAustin Clements // Return -1 if this process has no children.
272d8828817SAustin Clements int
wait(void)273d8828817SAustin Clements wait(void)
274d8828817SAustin Clements {
275d8828817SAustin Clements   struct proc *p;
276d8828817SAustin Clements   int havekids, pid;
277fbb4c094SFrans Kaashoek   struct proc *curproc = myproc();
278d8828817SAustin Clements 
279d8828817SAustin Clements   acquire(&ptable.lock);
280d8828817SAustin Clements   for(;;){
281d63ac118SRobert Morris     // Scan through table looking for exited children.
282d8828817SAustin Clements     havekids = 0;
283d8828817SAustin Clements     for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
284fbb4c094SFrans Kaashoek       if(p->parent != curproc)
285d8828817SAustin Clements         continue;
286d8828817SAustin Clements       havekids = 1;
287d8828817SAustin Clements       if(p->state == ZOMBIE){
288d8828817SAustin Clements         // Found one.
289d8828817SAustin Clements         pid = p->pid;
290d8828817SAustin Clements         kfree(p->kstack);
291d8828817SAustin Clements         p->kstack = 0;
292d8828817SAustin Clements         freevm(p->pgdir);
293d8828817SAustin Clements         p->pid = 0;
294d8828817SAustin Clements         p->parent = 0;
295d8828817SAustin Clements         p->name[0] = 0;
296d8828817SAustin Clements         p->killed = 0;
29719f65413SRobert Morris         p->state = UNUSED;
298d8828817SAustin Clements         release(&ptable.lock);
299d8828817SAustin Clements         return pid;
300d8828817SAustin Clements       }
301d8828817SAustin Clements     }
302d8828817SAustin Clements 
303d8828817SAustin Clements     // No point waiting if we don't have any children.
304fbb4c094SFrans Kaashoek     if(!havekids || curproc->killed){
305d8828817SAustin Clements       release(&ptable.lock);
306d8828817SAustin Clements       return -1;
307d8828817SAustin Clements     }
308d8828817SAustin Clements 
309d8828817SAustin Clements     // Wait for children to exit.  (See wakeup1 call in proc_exit.)
310fbb4c094SFrans Kaashoek     sleep(curproc, &ptable.lock);  //DOC: wait-sleep
311d8828817SAustin Clements   }
312d8828817SAustin Clements }
313d8828817SAustin Clements 
31431085bb4Srsc //PAGEBREAK: 42
31565bd8e13Srsc // Per-CPU process scheduler.
31665bd8e13Srsc // Each CPU calls scheduler() after setting itself up.
31765bd8e13Srsc // Scheduler never returns.  It loops, doing:
31865bd8e13Srsc //  - choose a process to run
319de1329ddSrtm //  - swtch to start running that process
320de1329ddSrtm //  - eventually that process transfers control
321de1329ddSrtm //      via swtch back to the scheduler.
32265bd8e13Srsc void
scheduler(void)3235ce9751cSrsc scheduler(void)
32455e95b16Srtm {
32565bd8e13Srsc   struct proc *p;
326fbb4c094SFrans Kaashoek   struct cpu *c = mycpu();
327ed396c06SFrans Kaashoek   c->proc = 0;
32855e95b16Srtm 
32965bd8e13Srsc   for(;;){
3302c5f7abaSRuss Cox     // Enable interrupts on this processor.
331ab08960fSrsc     sti();
332ab08960fSrsc 
33365bd8e13Srsc     // Loop over process table looking for process to run.
33434295f46Srsc     acquire(&ptable.lock);
33534295f46Srsc     for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
33665bd8e13Srsc       if(p->state != RUNNABLE)
33765bd8e13Srsc         continue;
3388b4e2a08Srtm 
33965bd8e13Srsc       // Switch to chosen process.  It is the process's job
34034295f46Srsc       // to release ptable.lock and then reacquire it
34165bd8e13Srsc       // before jumping back to us.
342fbb4c094SFrans Kaashoek       c->proc = p;
343c4cc10daSRobert Morris       switchuvm(p);
34465bd8e13Srsc       p->state = RUNNING;
345ed396c06SFrans Kaashoek 
346ed396c06SFrans Kaashoek       swtch(&(c->scheduler), p->context);
347c4cc10daSRobert Morris       switchkvm();
34865bd8e13Srsc 
34965bd8e13Srsc       // Process is done running for now.
35065bd8e13Srsc       // It should have changed its p->state before coming back.
351fbb4c094SFrans Kaashoek       c->proc = 0;
35265bd8e13Srsc     }
35334295f46Srsc     release(&ptable.lock);
354ab08960fSrsc 
35565bd8e13Srsc   }
3565ce9751cSrsc }
3575ce9751cSrsc 
3582c5f7abaSRuss Cox // Enter scheduler.  Must hold only ptable.lock
359bc8221a5SRobert Morris // and have changed proc->state. Saves and restores
360bc8221a5SRobert Morris // intena because intena is a property of this
361bc8221a5SRobert Morris // kernel thread, not this CPU. It should
362bc8221a5SRobert Morris // be proc->intena and proc->ncli, but that would
363bc8221a5SRobert Morris // break in the few places where a lock is held but
364bc8221a5SRobert Morris // there's no process.
3655ce9751cSrsc void
sched(void)36665bd8e13Srsc sched(void)
3675ce9751cSrsc {
368228e500aSkolya   int intena;
369fbb4c094SFrans Kaashoek   struct proc *p = myproc();
370228e500aSkolya 
37134295f46Srsc   if(!holding(&ptable.lock))
37234295f46Srsc     panic("sched ptable.lock");
373abf847a0SFrans Kaashoek   if(mycpu()->ncli != 1)
374b6cac0a5Srsc     panic("sched locks");
375fbb4c094SFrans Kaashoek   if(p->state == RUNNING)
3762c5f7abaSRuss Cox     panic("sched running");
3772c5f7abaSRuss Cox   if(readeflags()&FL_IF)
3782c5f7abaSRuss Cox     panic("sched interruptible");
379abf847a0SFrans Kaashoek   intena = mycpu()->intena;
380ed396c06SFrans Kaashoek   swtch(&p->context, mycpu()->scheduler);
381abf847a0SFrans Kaashoek   mycpu()->intena = intena;
38255e95b16Srtm }
383be0a7eacSrtm 
38465bd8e13Srsc // Give up the CPU for one scheduling round.
385be0a7eacSrtm void
yield(void)386856e1fc1Srsc yield(void)
38765bd8e13Srsc {
3882c5f7abaSRuss Cox   acquire(&ptable.lock);  //DOC: yieldlock
389abf847a0SFrans Kaashoek   myproc()->state = RUNNABLE;
39065bd8e13Srsc   sched();
39134295f46Srsc   release(&ptable.lock);
39265bd8e13Srsc }
39365bd8e13Srsc 
39418432ed5Srtm // A fork child's very first scheduling by scheduler()
395de1329ddSrtm // will swtch here.  "Return" to user space.
396856e1fc1Srsc void
forkret(void)397856e1fc1Srsc forkret(void)
398856e1fc1Srsc {
399d10d324eSFrans Kaashoek   static int first = 1;
40034295f46Srsc   // Still holding ptable.lock from scheduler.
40134295f46Srsc   release(&ptable.lock);
402856e1fc1Srsc 
403d10d324eSFrans Kaashoek   if (first) {
404194f8bf7SFrans Kaashoek     // Some initialization functions must be run in the context
405194f8bf7SFrans Kaashoek     // of a regular process (e.g., they call sleep), and thus cannot
406194f8bf7SFrans Kaashoek     // be run from main().
407d10d324eSFrans Kaashoek     first = 0;
4088320d61bSFrans Kaashoek     iinit(ROOTDEV);
4098320d61bSFrans Kaashoek     initlog(ROOTDEV);
410d10d324eSFrans Kaashoek   }
411d10d324eSFrans Kaashoek 
4122c5f7abaSRuss Cox   // Return to "caller", actually trapret (see allocproc).
413856e1fc1Srsc }
414856e1fc1Srsc 
41565bd8e13Srsc // Atomically release lock and sleep on chan.
41648755214SRuss Cox // Reacquires lock when awakened.
41765bd8e13Srsc void
sleep(void * chan,struct spinlock * lk)41865bd8e13Srsc sleep(void *chan, struct spinlock *lk)
419be0a7eacSrtm {
420fbb4c094SFrans Kaashoek   struct proc *p = myproc();
421fbb4c094SFrans Kaashoek 
422fbb4c094SFrans Kaashoek   if(p == 0)
4235ce9751cSrsc     panic("sleep");
42446bbd72fSrtm 
4250dd42537Srsc   if(lk == 0)
4260dd42537Srsc     panic("sleep without lk");
4270dd42537Srsc 
42834295f46Srsc   // Must acquire ptable.lock in order to
42965bd8e13Srsc   // change p->state and then call sched.
43034295f46Srsc   // Once we hold ptable.lock, we can be
43165bd8e13Srsc   // guaranteed that we won't miss any wakeup
43234295f46Srsc   // (wakeup runs with ptable.lock locked),
43365bd8e13Srsc   // so it's okay to release lk.
43400e57115SRuss Cox   if(lk != &ptable.lock){  //DOC: sleeplock0
43500e57115SRuss Cox     acquire(&ptable.lock);  //DOC: sleeplock1
43665bd8e13Srsc     release(lk);
43746bbd72fSrtm   }
43865bd8e13Srsc   // Go to sleep.
439fbb4c094SFrans Kaashoek   p->chan = chan;
440fbb4c094SFrans Kaashoek   p->state = SLEEPING;
441fbb4c094SFrans Kaashoek 
44265bd8e13Srsc   sched();
44365bd8e13Srsc 
44465bd8e13Srsc   // Tidy up.
445fbb4c094SFrans Kaashoek   p->chan = 0;
44665bd8e13Srsc 
44765bd8e13Srsc   // Reacquire original lock.
44800e57115SRuss Cox   if(lk != &ptable.lock){  //DOC: sleeplock2
44934295f46Srsc     release(&ptable.lock);
45065bd8e13Srsc     acquire(lk);
45165bd8e13Srsc   }
45265bd8e13Srsc }
45365bd8e13Srsc 
454eaea18cbSrsc //PAGEBREAK!
45565bd8e13Srsc // Wake up all processes sleeping on chan.
45634295f46Srsc // The ptable lock must be held.
457dd868974Srsc static void
wakeup1(void * chan)45846bbd72fSrtm wakeup1(void *chan)
45946bbd72fSrtm {
46046bbd72fSrtm   struct proc *p;
46146bbd72fSrtm 
46227ff8f0eSrsc   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
46365bd8e13Srsc     if(p->state == SLEEPING && p->chan == chan)
46446bbd72fSrtm       p->state = RUNNABLE;
465be0a7eacSrtm }
466be0a7eacSrtm 
46765bd8e13Srsc // Wake up all processes sleeping on chan.
468be0a7eacSrtm void
wakeup(void * chan)469be0a7eacSrtm wakeup(void *chan)
470be0a7eacSrtm {
47134295f46Srsc   acquire(&ptable.lock);
47246bbd72fSrtm   wakeup1(chan);
47334295f46Srsc   release(&ptable.lock);
474be0a7eacSrtm }
475b548df15Srtm 
47665bd8e13Srsc // Kill the process with the given pid.
47748755214SRuss Cox // Process won't exit until it returns
47865bd8e13Srsc // to user space (see trap in trap.c).
479643b122bSrsc int
kill(int pid)4805573c8f2Srsc kill(int pid)
481643b122bSrsc {
482643b122bSrsc   struct proc *p;
483643b122bSrsc 
48434295f46Srsc   acquire(&ptable.lock);
48534295f46Srsc   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
48665bd8e13Srsc     if(p->pid == pid){
487643b122bSrsc       p->killed = 1;
48865bd8e13Srsc       // Wake process from sleep if necessary.
48965bd8e13Srsc       if(p->state == SLEEPING)
490643b122bSrsc         p->state = RUNNABLE;
49134295f46Srsc       release(&ptable.lock);
492643b122bSrsc       return 0;
493643b122bSrsc     }
494643b122bSrsc   }
49534295f46Srsc   release(&ptable.lock);
496643b122bSrsc   return -1;
497643b122bSrsc }
498643b122bSrsc 
499cf4b1ad9SRuss Cox //PAGEBREAK: 36
500cf4b1ad9SRuss Cox // Print a process listing to console.  For debugging.
501cf4b1ad9SRuss Cox // Runs when user types ^P on console.
502cf4b1ad9SRuss Cox // No lock to avoid wedging a stuck machine further.
503cf4b1ad9SRuss Cox void
procdump(void)504cf4b1ad9SRuss Cox procdump(void)
505cf4b1ad9SRuss Cox {
506cf4b1ad9SRuss Cox   static char *states[] = {
507cf4b1ad9SRuss Cox   [UNUSED]    "unused",
508cf4b1ad9SRuss Cox   [EMBRYO]    "embryo",
509cf4b1ad9SRuss Cox   [SLEEPING]  "sleep ",
510cf4b1ad9SRuss Cox   [RUNNABLE]  "runble",
511cf4b1ad9SRuss Cox   [RUNNING]   "run   ",
512cf4b1ad9SRuss Cox   [ZOMBIE]    "zombie"
513cf4b1ad9SRuss Cox   };
514cf4b1ad9SRuss Cox   int i;
515cf4b1ad9SRuss Cox   struct proc *p;
516cf4b1ad9SRuss Cox   char *state;
517cf4b1ad9SRuss Cox   uint pc[10];
518cf4b1ad9SRuss Cox 
519cf4b1ad9SRuss Cox   for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
520cf4b1ad9SRuss Cox     if(p->state == UNUSED)
521cf4b1ad9SRuss Cox       continue;
522cf4b1ad9SRuss Cox     if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
523cf4b1ad9SRuss Cox       state = states[p->state];
524cf4b1ad9SRuss Cox     else
525cf4b1ad9SRuss Cox       state = "???";
526cf4b1ad9SRuss Cox     cprintf("%d %s %s", p->pid, state, p->name);
527cf4b1ad9SRuss Cox     if(p->state == SLEEPING){
528cf4b1ad9SRuss Cox       getcallerpcs((uint*)p->context->ebp+2, pc);
529cf4b1ad9SRuss Cox       for(i=0; i<10 && pc[i] != 0; i++)
530cf4b1ad9SRuss Cox         cprintf(" %p", pc[i]);
531cf4b1ad9SRuss Cox     }
532cf4b1ad9SRuss Cox     cprintf("\n");
533cf4b1ad9SRuss Cox   }
534cf4b1ad9SRuss Cox }
535