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