00001 #include "types.h"
00002 #include "defs.h"
00003 #include "param.h"
00004 #include "mmu.h"
00005 #include "x86.h"
00006 #include "proc.h"
00007 #include "spinlock.h"
00008
00009 struct {
00010 struct spinlock lock;
00011 struct proc proc[NPROC];
00012 } ptable;
00013
00014 static struct proc *initproc;
00015
00016 int nextpid = 1;
00017 extern void forkret(void);
00018 extern void trapret(void);
00019
00020 void
00021 pinit(void)
00022 {
00023 initlock(&ptable.lock, "ptable");
00024 }
00025
00026
00027
00028
00029 void
00030 procdump(void)
00031 {
00032 static char *states[] = {
00033 [UNUSED] "unused",
00034 [EMBRYO] "embryo",
00035 [SLEEPING] "sleep ",
00036 [RUNNABLE] "runble",
00037 [RUNNING] "run ",
00038 [ZOMBIE] "zombie"
00039 };
00040 int i;
00041 struct proc *p;
00042 char *state;
00043 uint pc[10];
00044
00045 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
00046 if(p->state == UNUSED)
00047 continue;
00048 if(p->state >= 0 && p->state < NELEM(states) && states[p->state])
00049 state = states[p->state];
00050 else
00051 state = "???";
00052 cprintf("%d %s %s", p->pid, state, p->name);
00053 if(p->state == SLEEPING){
00054 getcallerpcs((uint*)p->context->ebp+2, pc);
00055 for(i=0; i<10 && pc[i] != 0; i++)
00056 cprintf(" %p", pc[i]);
00057 }
00058 cprintf("\n");
00059 }
00060 }
00061
00062
00063
00064 void
00065 ksegment(void)
00066 {
00067 struct cpu *c;
00068
00069 c = &cpus[cpunum()];
00070 c->gdt[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0x100000 + 64*1024-1, 0);
00071 c->gdt[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
00072 c->gdt[SEG_KCPU] = SEG(STA_W, &c->cpu, 8, 0);
00073 lgdt(c->gdt, sizeof(c->gdt));
00074 loadgs(SEG_KCPU << 3);
00075
00076
00077 cpu = c;
00078 proc = 0;
00079 }
00080
00081
00082 void
00083 usegment(void)
00084 {
00085 pushcli();
00086 cpu->gdt[SEG_UCODE] = SEG(STA_X|STA_R, proc->mem, proc->sz-1, DPL_USER);
00087 cpu->gdt[SEG_UDATA] = SEG(STA_W, proc->mem, proc->sz-1, DPL_USER);
00088 cpu->gdt[SEG_TSS] = SEG16(STS_T32A, &cpu->ts, sizeof(cpu->ts)-1, 0);
00089 cpu->gdt[SEG_TSS].s = 0;
00090 cpu->ts.ss0 = SEG_KDATA << 3;
00091 cpu->ts.esp0 = (uint)proc->kstack + KSTACKSIZE;
00092 ltr(SEG_TSS << 3);
00093 popcli();
00094 }
00095
00096
00097
00098
00099 static struct proc*
00100 allocproc(void)
00101 {
00102 struct proc *p;
00103 char *sp;
00104
00105 acquire(&ptable.lock);
00106 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
00107 if(p->state == UNUSED)
00108 goto found;
00109 release(&ptable.lock);
00110 return 0;
00111
00112 found:
00113 p->state = EMBRYO;
00114 p->pid = nextpid++;
00115 release(&ptable.lock);
00116
00117
00118 if((p->kstack = kalloc(KSTACKSIZE)) == 0){
00119 p->state = UNUSED;
00120 return 0;
00121 }
00122 sp = p->kstack + KSTACKSIZE;
00123
00124
00125 sp -= sizeof *p->tf;
00126 p->tf = (struct trapframe*)sp;
00127
00128
00129
00130 sp -= 4;
00131 *(uint*)sp = (uint)trapret;
00132
00133 sp -= sizeof *p->context;
00134 p->context = (struct context*)sp;
00135 memset(p->context, 0, sizeof *p->context);
00136 p->context->eip = (uint)forkret;
00137 return p;
00138 }
00139
00140
00141 void
00142 userinit(void)
00143 {
00144 struct proc *p;
00145 extern char _binary_initcode_start[], _binary_initcode_size[];
00146
00147 p = allocproc();
00148 initproc = p;
00149
00150
00151 p->sz = PAGE;
00152 p->mem = kalloc(p->sz);
00153 memset(p->mem, 0, p->sz);
00154 memmove(p->mem, _binary_initcode_start, (int)_binary_initcode_size);
00155
00156 memset(p->tf, 0, sizeof(*p->tf));
00157 p->tf->cs = (SEG_UCODE << 3) | DPL_USER;
00158 p->tf->ds = (SEG_UDATA << 3) | DPL_USER;
00159 p->tf->es = p->tf->ds;
00160 p->tf->ss = p->tf->ds;
00161 p->tf->eflags = FL_IF;
00162 p->tf->esp = p->sz;
00163 p->tf->eip = 0;
00164
00165 safestrcpy(p->name, "initcode", sizeof(p->name));
00166 p->cwd = namei("/");
00167
00168 p->state = RUNNABLE;
00169 }
00170
00171
00172
00173 int
00174 growproc(int n)
00175 {
00176 char *newmem;
00177
00178 newmem = kalloc(proc->sz + n);
00179 if(newmem == 0)
00180 return -1;
00181 memmove(newmem, proc->mem, proc->sz);
00182 memset(newmem + proc->sz, 0, n);
00183 kfree(proc->mem, proc->sz);
00184 proc->mem = newmem;
00185 proc->sz += n;
00186 usegment();
00187 return 0;
00188 }
00189
00190
00191
00192
00193 int
00194 fork(void)
00195 {
00196 int i, pid;
00197 struct proc *np;
00198
00199
00200 if((np = allocproc()) == 0)
00201 return -1;
00202
00203
00204 np->sz = proc->sz;
00205 if((np->mem = kalloc(np->sz)) == 0){
00206 kfree(np->kstack, KSTACKSIZE);
00207 np->kstack = 0;
00208 np->state = UNUSED;
00209 return -1;
00210 }
00211 memmove(np->mem, proc->mem, np->sz);
00212 np->parent = proc;
00213 *np->tf = *proc->tf;
00214
00215
00216 np->tf->eax = 0;
00217
00218 for(i = 0; i < NOFILE; i++)
00219 if(proc->ofile[i])
00220 np->ofile[i] = filedup(proc->ofile[i]);
00221 np->cwd = idup(proc->cwd);
00222
00223 pid = np->pid;
00224 np->state = RUNNABLE;
00225
00226 return pid;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 void
00237 scheduler(void)
00238 {
00239 struct proc *p;
00240
00241 for(;;){
00242
00243 sti();
00244
00245
00246 acquire(&ptable.lock);
00247 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
00248 if(p->state != RUNNABLE)
00249 continue;
00250
00251
00252
00253
00254 proc = p;
00255 usegment();
00256 p->state = RUNNING;
00257 swtch(&cpu->scheduler, proc->context);
00258
00259
00260
00261 proc = 0;
00262 }
00263 release(&ptable.lock);
00264
00265 }
00266 }
00267
00268
00269
00270 void
00271 sched(void)
00272 {
00273 int intena;
00274
00275 if(!holding(&ptable.lock))
00276 panic("sched ptable.lock");
00277 if(cpu->ncli != 1)
00278 panic("sched locks");
00279 if(proc->state == RUNNING)
00280 panic("sched running");
00281 if(readeflags()&FL_IF)
00282 panic("sched interruptible");
00283
00284 intena = cpu->intena;
00285 swtch(&proc->context, cpu->scheduler);
00286 cpu->intena = intena;
00287 }
00288
00289
00290 void
00291 yield(void)
00292 {
00293 acquire(&ptable.lock);
00294 proc->state = RUNNABLE;
00295 sched();
00296 release(&ptable.lock);
00297 }
00298
00299
00300
00301 void
00302 forkret(void)
00303 {
00304
00305 release(&ptable.lock);
00306
00307
00308 }
00309
00310
00311
00312 void
00313 sleep(void *chan, struct spinlock *lk)
00314 {
00315 if(proc == 0)
00316 panic("sleep");
00317
00318 if(lk == 0)
00319 panic("sleep without lk");
00320
00321
00322
00323
00324
00325
00326
00327 if(lk != &ptable.lock){
00328 acquire(&ptable.lock);
00329 release(lk);
00330 }
00331
00332
00333 proc->chan = chan;
00334 proc->state = SLEEPING;
00335 sched();
00336
00337
00338 proc->chan = 0;
00339
00340
00341 if(lk != &ptable.lock){
00342 release(&ptable.lock);
00343 acquire(lk);
00344 }
00345 }
00346
00347
00348
00349 static void
00350 wakeup1(void *chan)
00351 {
00352 struct proc *p;
00353
00354 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
00355 if(p->state == SLEEPING && p->chan == chan)
00356 p->state = RUNNABLE;
00357 }
00358
00359
00360 void
00361 wakeup(void *chan)
00362 {
00363 acquire(&ptable.lock);
00364 wakeup1(chan);
00365 release(&ptable.lock);
00366 }
00367
00368
00369
00370
00371 int
00372 kill(int pid)
00373 {
00374 struct proc *p;
00375
00376 acquire(&ptable.lock);
00377 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
00378 if(p->pid == pid){
00379 p->killed = 1;
00380
00381 if(p->state == SLEEPING)
00382 p->state = RUNNABLE;
00383 release(&ptable.lock);
00384 return 0;
00385 }
00386 }
00387 release(&ptable.lock);
00388 return -1;
00389 }
00390
00391
00392
00393
00394 void
00395 exit(void)
00396 {
00397 struct proc *p;
00398 int fd;
00399
00400 if(proc == initproc)
00401 panic("init exiting");
00402
00403
00404 for(fd = 0; fd < NOFILE; fd++){
00405 if(proc->ofile[fd]){
00406 fileclose(proc->ofile[fd]);
00407 proc->ofile[fd] = 0;
00408 }
00409 }
00410
00411 iput(proc->cwd);
00412 proc->cwd = 0;
00413
00414 acquire(&ptable.lock);
00415
00416
00417 wakeup1(proc->parent);
00418
00419
00420 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
00421 if(p->parent == proc){
00422 p->parent = initproc;
00423 if(p->state == ZOMBIE)
00424 wakeup1(initproc);
00425 }
00426 }
00427
00428
00429 proc->state = ZOMBIE;
00430 sched();
00431 panic("zombie exit");
00432 }
00433
00434
00435
00436 int
00437 wait(void)
00438 {
00439 struct proc *p;
00440 int havekids, pid;
00441
00442 acquire(&ptable.lock);
00443 for(;;){
00444
00445 havekids = 0;
00446 for(p = ptable.proc; p < &ptable.proc[NPROC]; p++){
00447 if(p->parent != proc)
00448 continue;
00449 havekids = 1;
00450 if(p->state == ZOMBIE){
00451
00452 pid = p->pid;
00453 kfree(p->mem, p->sz);
00454 kfree(p->kstack, KSTACKSIZE);
00455 p->state = UNUSED;
00456 p->pid = 0;
00457 p->parent = 0;
00458 p->name[0] = 0;
00459 p->killed = 0;
00460 release(&ptable.lock);
00461 return pid;
00462 }
00463 }
00464
00465
00466 if(!havekids || proc->killed){
00467 release(&ptable.lock);
00468 return -1;
00469 }
00470
00471
00472 sleep(proc, &ptable.lock);
00473 }
00474 }
00475