| plan 9 kernel history: overview | file list | diff list |
1991/0513/port/proc.c (diff list | history)
| 1991/0513/sys/src/9/port/proc.c:1,645 – 1991/0517/sys/src/9/port/proc.c:1,648 (short | long | prev | next) | ||
|
Close file descriptors before freeing memory (why? XXX)
rsc Mon Mar 20 17:14:11 2006 | ||
| 1990/0227 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" struct { Lock; ulong pid; }pidalloc; struct { Lock; Proc *arena; Proc *free; }procalloc; | |
| 1991/0420 | typedef struct | |
| 1990/0227 | { Lock; Proc *head; Proc *tail; | |
| 1991/0420 | }Schedq; | |
| 1990/0227 | ||
| 1991/0420 | Schedq runhiq, runloq; | |
| 1990/0227 | char *statename[]={ /* BUG: generate automatically */ "Dead", "Moribund", "Zombie", "Ready", "Scheding", "Running", "Queueing", "MMUing", "Exiting", "Inwait", "Wakeme", "Broken", }; /* * Always splhi()'ed. */ void schedinit(void) /* never returns */ { Proc *p; setlabel(&m->sched); if(u){ m->proc = 0; p = u->p; | |
| 1990/1211 | invalidateu(); /* safety first */ | |
| 1990/0227 | u = 0; if(p->state == Running) ready(p); else if(p->state == Moribund){ p->pid = 0; | |
| 1991/0507 | mmurelease(p); | |
| 1990/0227 | /* procalloc already locked */ p->qnext = procalloc.free; procalloc.free = p; | |
| 1991/0430 | p->upage->ref--; | |
| 1990/0227 | p->upage = 0; | |
| 1991/0430 | unlock(&p->debug); | |
| 1990/0227 | unlock(&procalloc); p->state = Dead; } p->mach = 0; } sched(); } void sched(void) { | |
| 1991/0420 | uchar procstate[64]; /* sleaze for portability */ | |
| 1990/0227 | Proc *p; ulong tlbvirt, tlbphys; | |
| 1990/0731 | void (*f)(ulong, ulong); | |
| 1990/0227 | if(u){ splhi(); | |
| 1991/0425 | m->cs++; | |
| 1990/1212 | procsave(procstate, sizeof(procstate)); | |
| 1990/0227 | if(setlabel(&u->p->sched)){ /* woke up */ p = u->p; p->state = Running; p->mach = m; m->proc = p; | |
| 1990/1212 | procrestore(p, procstate); | |
| 1990/0227 | spllo(); return; } gotolabel(&m->sched); } spllo(); p = runproc(); splhi(); mapstack(p); gotolabel(&p->sched); } | |
| 1990/1227 | int anyready(void) { | |
| 1991/0420 | return runloq.head != 0 || runhiq.head != 0; | |
| 1990/1227 | } | |
| 1990/0227 | void ready(Proc *p) { | |
| 1991/0420 | Schedq *rq; | |
| 1990/0227 | int s; s = splhi(); | |
| 1991/0501 | ||
| 1991/0420 | if(p->state == Running) rq = &runloq; else rq = &runhiq; lock(&runhiq); | |
| 1990/0227 | p->rnext = 0; | |
| 1991/0420 | if(rq->tail) rq->tail->rnext = p; | |
| 1990/0227 | else | |
| 1991/0420 | rq->head = p; rq->tail = p; | |
| 1990/0227 | p->state = Ready; | |
| 1991/0420 | unlock(&runhiq); | |
| 1990/0227 | splx(s); } /* * Always called spllo */ Proc* runproc(void) { | |
| 1991/0420 | Schedq *rq; | |
| 1990/0227 | Proc *p; int i; loop: | |
| 1991/0420 | while(runhiq.head==0 && runloq.head==0) | |
| 1990/1211 | for(i=0; i<10; i++) /* keep out of shared memory for a while */ | |
| 1990/0227 | ; splhi(); | |
| 1991/0420 | lock(&runhiq); if(runhiq.head) rq = &runhiq; else rq = &runloq; p = rq->head; | |
| 1990/0227 | if(p==0 || p->mach){ /* p->mach==0 only when process state is saved */ | |
| 1991/0420 | unlock(&runhiq); | |
| 1990/0227 | spllo(); goto loop; } if(p->rnext == 0) | |
| 1991/0420 | rq->tail = 0; rq->head = p->rnext; | |
| 1990/0227 | if(p->state != Ready) print("runproc %s %d %s\n", p->text, p->pid, statename[p->state]); | |
| 1991/0420 | unlock(&runhiq); | |
| 1990/0227 | p->state = Scheding; spllo(); return p; } Proc* newproc(void) { Proc *p; loop: lock(&procalloc); if(p = procalloc.free){ /* assign = */ procalloc.free = p->qnext; p->state = Zombie; unlock(&procalloc); p->mach = 0; p->qnext = 0; p->nchild = 0; p->child = 0; p->exiting = 0; | |
| 1991/0317 | p->pgrp = 0; | |
| 1990/0722 | p->fpstate = FPinit; | |
| 1991/0425 | p->kp = 0; | |
| 1990/0227 | memset(p->seg, 0, sizeof p->seg); lock(&pidalloc); p->pid = ++pidalloc.pid; unlock(&pidalloc); if(p->pid == 0) panic("pidalloc"); return p; } unlock(&procalloc); print("no procs\n"); if(u == 0) panic("newproc"); | |
| 1990/0619 | u->p->state = Wakeme; | |
| 1990/0227 | alarm(1000, wakeme, u->p); sched(); goto loop; } void procinit0(void) /* bad planning - clashes with devproc.c */ { Proc *p; int i; procalloc.free = ialloc(conf.nproc*sizeof(Proc), 0); procalloc.arena = procalloc.free; p = procalloc.free; | |
| 1990/0310 | for(i=0; i<conf.nproc-1; i++,p++) | |
| 1990/0227 | p->qnext = p+1; p->qnext = 0; } void sleep1(Rendez *r, int (*f)(void*), void *arg) { Proc *p; int s; /* * spl is to allow lock to be called * at interrupt time. lock is mutual exclusion */ s = splhi(); lock(r); /* * if condition happened, never mind */ if((*f)(arg)){ unlock(r); splx(s); return; } /* * now we are committed to * change state and call scheduler */ p = u->p; if(r->p) | |
| 1990/03013 | print("double sleep %d %d\n", r->p->pid, p->pid); | |
| 1990/0227 | p->r = r; p->wokeup = 0; p->state = Wakeme; r->p = p; unlock(r); } void sleep(Rendez *r, int (*f)(void*), void *arg) { sleep1(r, f, arg); sched(); if(u->p->wokeup){ u->p->wokeup = 0; | |
| 1990/11211 | error(Eintr); | |
| 1990/0227 | } } void tsleep(Rendez *r, int (*f)(void*), void *arg, int ms) { Alarm *a; sleep1(r, f, arg); a = alarm(ms, twakeme, r); sched(); cancel(a); if(u->p->wokeup){ u->p->wokeup = 0; | |
| 1990/11211 | error(Eintr); | |
| 1990/0227 | } } void wakeup(Rendez *r) { Proc *p; int s; s = splhi(); lock(r); p = r->p; if(p){ r->p = 0; if(p->state != Wakeme) panic("wakeup: not Wakeme"); p->r = 0; ready(p); } unlock(r); splx(s); } | |
| 1990/03091 | void wakeme(Alarm *a) { ready((Proc*)(a->arg)); cancel(a); } void twakeme(Alarm *a) { wakeup((Rendez*)(a->arg)); } | |
| 1990/0227 | int postnote(Proc *p, int dolock, char *n, int flag) { User *up; | |
| 1990/0617 | KMap *k; | |
| 1990/0227 | int s; Rendez *r; | |
| 1991/0425 | SET(k); USED(k); | |
| 1990/0227 | if(dolock) lock(&p->debug); | |
| 1991/0430 | if(p->upage == 0) errors("noted process disappeared"); | |
| 1991/0425 | ||
| 1991/0109 | if(p != u->p){ k = kmap(p->upage); up = (User*)VA(k); | |
| 1991/0425 | }else | |
| 1991/0109 | up = u; | |
| 1991/0425 | ||
| 1990/0227 | if(flag!=NUser && (up->notify==0 || up->notified)) up->nnote = 0; /* force user's hand */ | |
| 1990/0617 | else if(up->nnote == NNOTE-1){ | |
| 1991/0109 | if(up != u) kunmap(k); | |
| 1990/0227 | return 0; | |
| 1990/0617 | } | |
| 1990/0227 | strcpy(up->note[up->nnote].msg, n); up->note[up->nnote++].flag = flag; | |
| 1991/0109 | if(up != u) kunmap(k); | |
| 1990/0227 | if(dolock) unlock(&p->debug); if(r = p->r){ /* assign = */ /* wake up */ s = splhi(); lock(r); if(p->r==r && r->p==p){ r->p = 0; if(p->state != Wakeme) panic("postnote wakeup: not Wakeme"); p->wokeup = 1; p->r = 0; ready(p); } unlock(r); splx(s); } return 1; } | |
| 1990/1101 | /* * weird thing: keep at most NBROKEN around */ #define NBROKEN 4 struct{ Lock; int n; Proc *p[NBROKEN]; }broken; | |
| 1990/0227 | void | |
| 1990/1101 | addbroken(Proc *c) { int b; lock(&broken); if(broken.n == NBROKEN){ ready(broken.p[0]); | |
| 1991/0318 | memmove(&broken.p[0], &broken.p[1], sizeof(Proc*)*(NBROKEN-1)); | |
| 1990/1101 | --broken.n; } broken.p[broken.n++] = c; unlock(&broken); c->state = Broken; sched(); /* until someone lets us go */ lock(&broken); for(b=0; b<NBROKEN; b++) if(broken.p[b] == c){ broken.n--; | |
| 1991/0318 | memmove(&broken.p[b], &broken.p[b+1], sizeof(Proc*)*(NBROKEN-(b+1))); | |
| 1990/1101 | break; } unlock(&broken); } int freebroken(void) { | |
| 1991/0109 | int i, n; | |
| 1990/1101 | lock(&broken); n = broken.n; | |
| 1991/0109 | for(i=0; i<n; i++) ready(broken.p[i]); broken.n = 0; | |
| 1990/1101 | unlock(&broken); return n; } void | |
| 1990/0227 | pexit(char *s, int freemem) { ulong mypid; | |
| 1990/03081 | Proc *p, *c, *k, *l; | |
| 1990/0227 | int n; | |
| 1990/03081 | Chan *ch; | |
| 1991/0110 | char msg[ERRLEN]; | |
| 1990/0227 | ulong *up, *ucp, *wp; | |
| 1991/0110 | if(s) /* squirrel away; we'll lose our address space */ strcpy(msg, s); else msg[0] = 0; | |
| 1990/03081 | c = u->p; | |
| 1991/0513 | c->alarm = 0; | |
| 1990/03081 | mypid = c->pid; | |
| 1991/0517 | for(n=0; n<=u->maxfd; n++) if(ch = u->fd[n]) /* assign = */ close(ch); | |
| 1990/0227 | if(freemem){ freesegs(-1); | |
| 1990/03081 | closepgrp(c->pgrp); | |
| 1990/0227 | close(u->dot); } | |
| 1990/03081 |
| |
| 1990/0227 | /* * Any of my children exiting? */ | |
| 1990/03081 | while(c->nchild){ | |
| 1990/0324 | lock(&c->wait.queue); if(canlock(&c->wait.use)){ /* no child is exiting */ | |
| 1990/03081 | c->exiting = 1; | |
| 1990/0324 | unlock(&c->wait.use); unlock(&c->wait.queue); | |
| 1990/0227 | break; }else{ /* must wait for child */ | |
| 1990/0324 | unlock(&c->wait.queue); | |
| 1990/0227 | pwait(0); } } | |
| 1990/03081 | c->time[TReal] = MACHP(0)->ticks - c->time[TReal]; | |
| 1990/0227 | /* * Tell my parent */ | |
| 1990/03081 | p = c->parent; | |
| 1990/0227 | if(p == 0) goto out; qlock(&p->wait); | |
| 1990/0324 | lock(&p->wait.queue); | |
| 1990/03081 | if(p->pid==c->parentpid && !p->exiting){ | |
| 1991/0318 | memmove(p->waitmsg.msg, msg, ERRLEN); | |
| 1991/0109 | p->waitmsg.pid = mypid; wp = &p->waitmsg.time[TUser]; | |
| 1990/03081 | up = &c->time[TUser]; ucp = &c->time[TCUser]; | |
| 1990/0614 | *wp++ = TK2MS(*up++ + *ucp++); *wp++ = TK2MS(*up++ + *ucp ); *wp = TK2MS(*up ); | |
| 1990/03081 | p->child = c; c->state = Exiting; | |
| 1990/0227 | if(p->state == Inwait) ready(p); | |
| 1990/0324 | unlock(&p->wait.queue); | |
| 1990/0227 | sched(); }else{ | |
| 1990/0324 | unlock(&p->wait.queue); | |
| 1990/0227 | qunlock(&p->wait); } out: if(!freemem){ | |
| 1990/1101 | addbroken(c); | |
| 1990/0227 | freesegs(-1); | |
| 1990/03081 | closepgrp(c->pgrp); | |
| 1990/0227 | close(u->dot); } | |
| 1990/03081 | done: | |
| 1990/0227 | lock(&procalloc); /* sched() can't do this */ | |
| 1990/03081 | lock(&c->debug); /* sched() can't do this */ | |
| 1990/1212 | unusepage(c->upage, 1); /* sched() can't do this (it locks) */ | |
| 1990/03081 | c->state = Moribund; | |
| 1990/0227 | sched(); /* never returns */ } ulong pwait(Waitmsg *w) { Proc *c, *p; ulong cpid; p = u->p; again: | |
| 1990/0324 | while(canlock(&p->wait.use)){ | |
| 1990/0227 | if(p->nchild == 0){ qunlock(&p->wait); | |
| 1990/11211 | error(Enochild); | |
| 1990/0227 | } p->state = Inwait; qunlock(&p->wait); sched(); } | |
| 1990/0324 | lock(&p->wait.queue); /* wait until child is finished */ | |
| 1990/0227 | c = p->child; if(c == 0){ p->state = Inwait; | |
| 1990/0324 | unlock(&p->wait.queue); | |
| 1990/0227 | sched(); goto again; } p->child = 0; if(w) | |
| 1991/0109 | *w = p->waitmsg; cpid = p->waitmsg.pid; | |
| 1990/0227 | p->time[TCUser] += c->time[TUser] + c->time[TCUser]; p->time[TCSys] += c->time[TSys] + c->time[TCSys]; p->time[TCReal] += c->time[TReal]; p->nchild--; | |
| 1990/0324 | unlock(&p->wait.queue); | |
| 1990/0227 | qunlock(&p->wait); ready(c); return cpid; } Proc* proctab(int i) { return &procalloc.arena[i]; } #include <ureg.h> | |
| 1990/1220 | void DEBUG(void) | |
| 1990/0227 | { | |
| 1990/0330 | int i; | |
| 1990/0227 | Proc *p; | |
| 1990/0312 | Orig *o; | |
| 1990/0227 | print("DEBUG\n"); for(i=0; i<conf.nproc; i++){ p = procalloc.arena+i; | |
| 1990/0312 | if(p->state != Dead){ | |
| 1990/0704 | print("%d:%s %s upc %lux %s ut %ld st %ld r %lux\n", p->pid, p->text, p->pgrp->user, p->pc, statename[p->state], | |
| 1990/0629 | p->time[0], p->time[1], p->r); | |
| 1990/0312 | } | |
| 1990/0227 | } } void kproc(char *name, void (*func)(void *), void *arg) { Proc *p; int n; ulong upa; | |
| 1990/0424 | int lastvar; /* used to compute stack address */ | |
| 1990/0617 | User *up; KMap *k; | |
| 1990/0722 | static Pgrp *kpgrp; | |
| 1990/0227 | /* * Kernel stack */ p = newproc(); | |
| 1990/1212 | p->kp = 1; | |
| 1990/0227 | p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF)); | |
| 1990/0617 | k = kmap(p->upage); upa = VA(k); up = (User*)upa; up->p = p; | |
| 1990/0227 | /* * Save time: only copy u-> data and useful stack */ | |
| 1990/1211 | clearmmucache(); | |
| 1991/0318 | memmove(up, u, sizeof(User)); | |
| 1990/0227 | n = USERADDR+BY2PG - (ulong)&lastvar; n = (n+32) & ~(BY2WD-1); /* be safe & word align */ | |
| 1991/0318 | memmove((void*)(upa+BY2PG-n), (void*)(USERADDR+BY2PG-n), n); | |
| 1990/0227 | /* * Refs */ incref(up->dot); for(n=0; n<=up->maxfd; n++) up->fd[n] = 0; up->maxfd = 0; | |
| 1990/0617 | kunmap(k); | |
| 1990/0227 | /* * Sched */ if(setlabel(&p->sched)){ u->p = p; p->state = Running; p->mach = m; m->proc = p; spllo(); (*func)(arg); pexit(0, 1); } | |
| 1990/0722 | if(kpgrp == 0){ kpgrp = newpgrp(); strcpy(kpgrp->user, "bootes"); } p->pgrp = kpgrp; incref(kpgrp); sprint(p->text, "%s.%.6s", name, u->p->pgrp->user); | |
| 1990/0227 | p->nchild = 0; p->parent = 0; memset(p->time, 0, sizeof(p->time)); p->time[TReal] = MACHP(0)->ticks; ready(p); flushmmu(); } | |