diff options
| -rw-r--r-- | sys/src/9/port/auth.c | 12 | ||||
| -rw-r--r-- | sys/src/9/port/devcap.c | 4 | ||||
| -rw-r--r-- | sys/src/9/port/devproc.c | 422 | ||||
| -rw-r--r-- | sys/src/9/port/pgrp.c | 18 | ||||
| -rw-r--r-- | sys/src/9/port/portdat.h | 16 | ||||
| -rw-r--r-- | sys/src/9/port/portfns.h | 7 | ||||
| -rw-r--r-- | sys/src/9/port/proc.c | 392 | ||||
| -rw-r--r-- | sys/src/9/port/sysproc.c | 17 | ||||
| -rw-r--r-- | sys/src/9/port/userinit.c | 1 |
9 files changed, 479 insertions, 410 deletions
diff --git a/sys/src/9/port/auth.c b/sys/src/9/port/auth.c index ff3c9a8cd..2cc54c657 100644 --- a/sys/src/9/port/auth.c +++ b/sys/src/9/port/auth.c @@ -117,8 +117,7 @@ userwrite(char *a, int n) { if(n!=4 || strncmp(a, "none", 4)!=0) error(Eperm); - kstrdup(&up->user, "none"); - up->basepri = PriNormal; + procsetuser(up, "none"); return n; } @@ -130,12 +129,14 @@ userwrite(char *a, int n) long hostownerwrite(char *a, int n) { - char buf[128]; + char buf[KNAMELEN]; if(!iseve()) error(Eperm); - if(n <= 0 || n >= sizeof buf) + if(n <= 0) error(Ebadarg); + if(n >= sizeof buf) + error(Etoolong); memmove(buf, a, n); buf[n] = 0; @@ -143,8 +144,7 @@ hostownerwrite(char *a, int n) srvrenameuser(eve, buf); shrrenameuser(eve, buf); kstrdup(&eve, buf); - kstrdup(&up->user, buf); - up->basepri = PriNormal; + procsetuser(up, buf); return n; } diff --git a/sys/src/9/port/devcap.c b/sys/src/9/port/devcap.c index 574e53959..05c69f413 100644 --- a/sys/src/9/port/devcap.c +++ b/sys/src/9/port/devcap.c @@ -246,9 +246,7 @@ capwrite(Chan *c, void *va, long n, vlong) } secfree(p); - /* set user id */ - kstrdup(&up->user, to); - up->basepri = PriNormal; + procsetuser(up, to); secfree(cp); poperror(); diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index 20ca9b6f5..940fbeb16 100644 --- a/sys/src/9/port/devproc.c +++ b/sys/src/9/port/devproc.c @@ -74,7 +74,7 @@ enum{ Emask = Nevents - 1, }; -#define STATSIZE (2*KNAMELEN+12+9*12) +#define STATSIZE (2*28+12+9*12) /* * Status, fd, and ns are left fully readable (0444) because of their use in debugging, * particularly on shared servers. @@ -145,7 +145,6 @@ static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed" * 23 bits of process slot number + 1 * in vers, * 32 bits of pid, for consistency checking - * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. */ #define QSHIFT 5 /* location in qid of proc slot # */ @@ -186,7 +185,7 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) if(s == 0){ strcpy(up->genbuf, "trace"); mkqid(&qid, Qtrace, -1, QTFILE); - devdir(c, qid, up->genbuf, 0, eve, 0444, dp); + devdir(c, qid, up->genbuf, 0, eve, 0400, dp); return 1; } @@ -206,10 +205,10 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) pid = p->pid; if(pid == 0) return 0; - sprint(up->genbuf, "%lud", pid); /* * String comparison is done in devwalk so name must match its formatted pid */ + snprint(up->genbuf, sizeof(up->genbuf), "%lud", pid); if(name != nil && strcmp(name, up->genbuf) != 0) return -1; mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR); @@ -219,7 +218,7 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) if(c->qid.path == Qtrace){ strcpy(up->genbuf, "trace"); mkqid(&qid, Qtrace, -1, QTFILE); - devdir(c, qid, up->genbuf, 0, eve, 0444, dp); + devdir(c, qid, up->genbuf, 0, eve, 0400, dp); return 1; } if(s >= nelem(procdir)) @@ -250,8 +249,6 @@ procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp) len *= sizeof(*q->profile); } break; - } - switch(QID(tab->qid)){ case Qwatchpt: len = lenwatchpt(p); break; @@ -324,13 +321,58 @@ nonone(Proc *p) error(Eperm); } +static void +changenoteid(Proc *p, ulong noteid) +{ + Proc *pp; + int i; + + if(noteid <= 0) + error(Ebadarg); + if(noteid == p->noteid) + return; + if(noteid == p->pid){ + setnoteid(p, noteid); + return; + } + for(i = 0; i < conf.nproc; i++){ + pp = proctab(i); + if(pp->noteid != noteid || pp->kp) + continue; + if(strcmp(pp->user, p->user) == 0){ + nonone(pp); + setnoteid(p, noteid); + return; + } + } + error(Eperm); +} + +static void +postnotepg(ulong noteid, char *n, int flag) +{ + Proc *p; + int i; + + for(i = 0; i < conf.nproc; i++){ + p = proctab(i); + if(p == up) + continue; + if(p->noteid != noteid || p->kp) + continue; + qlock(&p->debug); + if(p->noteid == noteid) + postnote(p, 0, n, flag); + qunlock(&p->debug); + } +} + static void clearwatchpt(Proc *p); static Chan* procopen(Chan *c, int omode0) { Proc *p; - Pgrp *pg; Chan *tc; int pid; int omode; @@ -339,7 +381,7 @@ procopen(Chan *c, int omode0) return devopen(c, omode0, 0, 0, procgen); if(QID(c->qid) == Qtrace){ - if (omode0 != OREAD) + if (omode0 != OREAD || !iseve()) error(Eperm); lock(&tlock); if (waserror()){ @@ -381,6 +423,7 @@ procopen(Chan *c, int omode0) case Qtext: if(omode != OREAD) error(Eperm); + nonone(p); qunlock(&p->debug); poperror(); tc = proctext(c, p); @@ -388,64 +431,54 @@ procopen(Chan *c, int omode0) cclose(c); return tc; + case Qstatus: + case Qppid: case Qproc: case Qkregs: case Qsegment: - case Qprofile: case Qns: case Qfd: if(omode != OREAD) error(Eperm); break; + case Qargs: + case Qwait: + case Qnoteid: + if(omode == OREAD) + break; + case Qctl: case Qnote: - if(p->privatemem) + if(p->kp) error(Eperm); break; - case Qmem: - case Qctl: - if(p->privatemem) + case Qnotepg: + if(p->kp || omode != OWRITE) error(Eperm); - nonone(p); + pid = p->noteid; break; - case Qargs: - case Qnoteid: - case Qstatus: - case Qwait: + case Qmem: case Qregs: case Qfpregs: + case Qprofile: case Qsyscall: - case Qppid: case Qwatchpt: - nonone(p); - break; - - case Qnotepg: - nonone(p); - pg = p->pgrp; - if(pg == nil) - error(Eprocdied); - if(omode!=OWRITE) + if(p->kp || p->privatemem) error(Eperm); - c->pgrpid.path = pg->pgrpid+1; - c->pgrpid.vers = p->noteid; break; default: print("procopen %#lux\n", QID(c->qid)); error(Egreg); } + nonone(p); /* Affix pid to qid */ - if(p->state != Dead) - c->qid.vers = p->pid; - - /* make sure the process slot didn't get reallocated while we were playing */ - coherence(); - if(p->pid != pid) + if(pid == 0) error(Eprocdied); + c->qid.vers = pid; tc = devopen(c, omode, 0, 0, procgen); if(waserror()){ @@ -470,36 +503,41 @@ procopen(Chan *c, int omode0) static int procwstat(Chan *c, uchar *db, int n) { - Proc *p; Dir *d; + Proc *p; if(c->qid.type&QTDIR) error(Eperm); - if(QID(c->qid) == Qtrace) + switch(QID(c->qid)){ + case Qnotepg: + case Qtrace: return devwstat(c, db, n); + } - p = proctab(SLOT(c->qid)); - nonone(p); - d = nil; + d = smalloc(sizeof(Dir)+n); + if(waserror()){ + free(d); + nexterror(); + } + n = convM2D(db, n, &d[0], (char*)&d[1]); + if(n == 0) + error(Eshortstat); + p = proctab(SLOT(c->qid)); eqlock(&p->debug); if(waserror()){ qunlock(&p->debug); - free(d); nexterror(); } if(p->pid != PID(c->qid)) error(Eprocdied); + nonone(p); if(strcmp(up->user, p->user) != 0 && !iseve()) error(Eperm); - d = smalloc(sizeof(Dir)+n); - n = convM2D(db, n, &d[0], (char*)&d[1]); - if(n == 0) - error(Eshortstat); if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){ if(!iseve()) error(Eperm); @@ -511,6 +549,7 @@ procwstat(Chan *c, uchar *db, int n) qunlock(&p->debug); poperror(); + poperror(); free(d); return n; } @@ -551,10 +590,8 @@ procargs(Proc *p, char *buf, int nbuf) int n; a = p->args; - if(p->setargs){ - snprint(buf, nbuf, "%s [%s]", p->text, p->args); - return strlen(buf); - } + if(p->setargs) + return snprint(buf, nbuf, "%s [%s]", p->text, p->args); n = p->nargs; for(j = 0; j < nbuf - 1; j += m){ if(n <= 0) @@ -836,24 +873,23 @@ off2addr(vlong off) static long procread(Chan *c, void *va, long n, vlong off) { - char *a, *sps, statbuf[1024]; - int i, j, navail, ne, rsize; - ulong l; + char statbuf[1024], *sps; + ulong offset; + int i, j, rsize; uchar *rptr; uintptr addr; - ulong offset; - Confmem *cm; - Proc *p; - Segment *sg, *s; + Segment *s; Ureg kur; Waitq *wq; + Proc *p; - a = va; offset = off; if(c->qid.type & QTDIR) - return devdirread(c, a, n, 0, 0, procgen); + return devdirread(c, va, n, 0, 0, procgen); if(QID(c->qid) == Qtrace){ + int navail, ne; + if(!eventsavailable(nil)) return 0; @@ -879,33 +915,6 @@ procread(Chan *c, void *va, long n, vlong off) error(Eprocdied); switch(QID(c->qid)){ - case Qargs: - eqlock(&p->debug); - j = procargs(p, statbuf, sizeof(statbuf)); - qunlock(&p->debug); - if(offset >= j) - return 0; - if(offset+n > j) - n = j-offset; - statbufread: - memmove(a, statbuf+offset, n); - return n; - - case Qsyscall: - eqlock(&p->debug); - if(waserror()){ - qunlock(&p->debug); - nexterror(); - } - if(p->pid != PID(c->qid)) - error(Eprocdied); - j = 0; - if(p->syscalltrace != nil) - j = readstr(offset, a, n, p->syscalltrace); - qunlock(&p->debug); - poperror(); - return j; - case Qmem: addr = off2addr(off); if(addr < KZERO) @@ -918,21 +927,27 @@ procread(Chan *c, void *va, long n, vlong off) if(addr < (uintptr)end) { if(addr+n > (uintptr)end) n = (uintptr)end - addr; - memmove(a, (char*)addr, n); + memmove(va, (char*)addr, n); return n; } for(i=0; i<nelem(conf.mem); i++){ - cm = &conf.mem[i]; + Confmem *cm = &conf.mem[i]; /* klimit-1 because klimit might be zero! */ if(cm->kbase <= addr && addr <= cm->klimit-1){ if(addr+n >= cm->klimit-1) n = cm->klimit - addr; - memmove(a, (char*)addr, n); + memmove(va, (char*)addr, n); return n; } } error(Ebadarg); + case Qnoteid: + return readnum(offset, va, n, p->noteid, NUMSIZE); + + case Qppid: + return readnum(offset, va, n, p->parentpid, NUMSIZE); + case Qprofile: s = p->seg[TSEG]; if(s == nil || s->profile == nil) @@ -943,42 +958,13 @@ procread(Chan *c, void *va, long n, vlong off) return 0; if(offset+n > i) n = i - offset; - memmove(a, ((char*)s->profile)+offset, n); - return n; - - case Qnote: - eqlock(&p->debug); - if(waserror()){ - qunlock(&p->debug); - nexterror(); - } - if(p->pid != PID(c->qid)) - error(Eprocdied); - if(n < 1) /* must accept at least the '\0' */ - error(Etoosmall); - if(p->nnote == 0) - n = 0; - else { - i = strlen(p->note[0].msg) + 1; - if(i < n) - n = i; - memmove(a, p->note[0].msg, n-1); - a[n-1] = '\0'; - if(--p->nnote == 0) - p->notepending = 0; - memmove(p->note, p->note+1, p->nnote*sizeof(Note)); - } - poperror(); - qunlock(&p->debug); + memmove(va, ((char*)s->profile)+offset, n); return n; case Qproc: - if(offset >= sizeof(Proc)) - return 0; - if(offset+n > sizeof(Proc)) - n = sizeof(Proc) - offset; - memmove(a, ((char*)p)+offset, n); - return n; + rptr = (uchar*)p; + rsize = sizeof(Proc); + goto regread; case Qregs: rptr = (uchar*)p->dbgreg; @@ -1004,53 +990,48 @@ procread(Chan *c, void *va, long n, vlong off) return 0; if(offset+n > rsize) n = rsize - offset; - memmove(a, rptr+offset, n); + memmove(va, rptr+offset, n); return n; case Qstatus: - if(offset >= STATSIZE) - return 0; - if(offset+n > STATSIZE) - n = STATSIZE - offset; - sps = p->psstate; if(sps == nil) sps = statename[p->state]; - - memset(statbuf, ' ', sizeof statbuf); - readstr(0, statbuf+0*KNAMELEN, KNAMELEN-1, p->text); - readstr(0, statbuf+1*KNAMELEN, KNAMELEN-1, p->user); - readstr(0, statbuf+2*KNAMELEN, 11, sps); - - j = 2*KNAMELEN + 12; - for(i = 0; i < 6; i++) { - l = p->time[i]; - if(i == TReal) - l = MACHP(0)->ticks - l; - readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, tk2ms(l), NUMSIZE); - } - - readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, procpagecount(p)*BY2PG/1024, NUMSIZE); - readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE); - readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE); - goto statbufread; + j = snprint(statbuf, sizeof(statbuf), + "%-27s %-27s %-11s " + "%11lud %11lud %11lud " + "%11lud %11lud %11lud " + "%11lud %11lud %11lud\n", + p->text, p->user, sps, + tk2ms(p->time[TUser]), + tk2ms(p->time[TSys]), + tk2ms(MACHP(0)->ticks - p->time[TReal]), + tk2ms(p->time[TCUser]), + tk2ms(p->time[TCSys]), + tk2ms(p->time[TCReal]), + (ulong)(procpagecount(p)*BY2PG/1024), + p->basepri, p->priority); + statbufread: + if(offset >= j) + return 0; + if(offset+n > j) + n = j - offset; + memmove(va, statbuf+offset, n); + return n; case Qsegment: j = 0; for(i = 0; i < NSEG; i++) { - sg = p->seg[i]; - if(sg == nil) + s = p->seg[i]; + if(s == nil) continue; - j += sprint(statbuf+j, "%-6s %c%c %8p %8p %4ld\n", - sname[sg->type&SG_TYPE], - sg->type&SG_FAULT ? 'F' : (sg->type&SG_RONLY ? 'R' : ' '), - sg->profile ? 'P' : ' ', - sg->base, sg->top, sg->ref); + j += snprint(statbuf+j, sizeof(statbuf)-j, + "%-6s %c%c %8p %8p %4ld\n", + sname[s->type&SG_TYPE], + s->type&SG_FAULT ? 'F' : (s->type&SG_RONLY ? 'R' : ' '), + s->profile ? 'P' : ' ', + s->base, s->top, s->ref); } - if(offset >= j) - return 0; - if(offset+n > j) - n = j-offset; goto statbufread; case Qwait: @@ -1089,18 +1070,21 @@ procread(Chan *c, void *va, long n, vlong off) wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal], wq->w.msg); free(wq); - if(j < n) - n = j; offset = 0; goto statbufread; + } + eqlock(&p->debug); + if(waserror()){ + qunlock(&p->debug); + nexterror(); + } + if(p->pid != PID(c->qid)) + error(Eprocdied); + + switch(QID(c->qid)){ case Qns: case Qfd: - eqlock(&p->debug); - if(waserror()){ - qunlock(&p->debug); - nexterror(); - } if(offset == 0 || offset != c->mrock) c->nrock = c->mrock = 0; do { @@ -1115,62 +1099,81 @@ procread(Chan *c, void *va, long n, vlong off) i = c->mrock - offset; qunlock(&p->debug); poperror(); - if(i <= 0 || i > j) return 0; if(i < n) n = i; offset = j - i; goto statbufread; - - case Qnoteid: - return readnum(offset, va, n, p->noteid, NUMSIZE); - - case Qppid: - return readnum(offset, va, n, p->parentpid, NUMSIZE); + case Qargs: + j = procargs(p, statbuf, sizeof(statbuf)); + qunlock(&p->debug); + poperror(); + goto statbufread; + case Qwatchpt: - eqlock(&p->debug); j = readwatchpt(p, statbuf, sizeof(statbuf)); qunlock(&p->debug); - if(offset >= j) - return 0; - if(offset+n > j) - n = j - offset; + poperror(); goto statbufread; + case Qsyscall: + n = 0; + if(p->syscalltrace != nil) + n = readstr(offset, va, n, p->syscalltrace); + break; + + case Qnote: + if(n < 1) /* must accept at least the '\0' */ + error(Etoosmall); + if(p->nnote == 0) + n = 0; + else { + i = strlen(p->note[0].msg) + 1; + if(i < n) + n = i; + memmove(va, p->note[0].msg, n-1); + ((char*)va)[n-1] = '\0'; + if(--p->nnote == 0) + p->notepending = 0; + memmove(p->note, p->note+1, p->nnote*sizeof(Note)); + } + break; + + default: + print("unknown qid in procwread\n"); + error(Egreg); } - error(Egreg); - return 0; /* not reached */ + + qunlock(&p->debug); + poperror(); + return n; } static long procwrite(Chan *c, void *va, long n, vlong off) { - int id, m; - Proc *p, *t, *et; - char *a, *arg, buf[ERRMAX]; + char buf[ERRMAX], *arg; ulong offset; + Proc *p; + int m; - a = va; offset = off; if(c->qid.type & QTDIR) error(Eisdir); - /* Use the remembered noteid in the channel rather - * than the process pgrpid - */ + /* use the remembered noteid in the channel qid */ if(QID(c->qid) == Qnotepg) { if(n >= ERRMAX-1) error(Etoobig); memmove(buf, va, n); buf[n] = 0; - pgrpnote(NOTEID(c->pgrpid), buf, NUser); + postnotepg(NOTEID(c->qid), buf, NUser); return n; } p = proctab(SLOT(c->qid)); - eqlock(&p->debug); if(waserror()){ qunlock(&p->debug); @@ -1193,8 +1196,8 @@ procwrite(Chan *c, void *va, long n, vlong off) if(arg[m-1] != 0) arg[m++] = 0; free(p->args); - p->nargs = m; p->args = arg; + p->nargs = m; p->setargs = 1; break; @@ -1229,43 +1232,26 @@ procwrite(Chan *c, void *va, long n, vlong off) break; case Qnote: - if(p->kp) - error(Eperm); - if(n >= ERRMAX-1) + if(n >= sizeof(buf)) error(Etoobig); memmove(buf, va, n); buf[n] = 0; if(!postnote(p, 0, buf, NUser)) error("note not posted"); break; + case Qnoteid: - if(p->kp) - error(Eperm); - id = atoi(a); - if(id <= 0) - error(Ebadarg); - if(id == p->pid) { - p->noteid = id; - break; - } - t = proctab(0); - for(et = t+conf.nproc; t < et; t++) { - if(t->state == Dead || t->kp) - continue; - if(id == t->noteid) { - nonone(t); - if(strcmp(p->user, t->user) != 0) - error(Eperm); - p->noteid = id; - break; - } - } - if(p->noteid != id) - error(Ebadarg); + if(n >= sizeof(buf)) + error(Etoobig); + memmove(buf, va, n); + buf[n] = 0; + changenoteid(p, atoi(buf)); break; + case Qwatchpt: writewatchpt(p, va, n, off); break; + default: print("unknown qid in procwrite\n"); error(Egreg); @@ -1352,7 +1338,8 @@ procstopwait(Proc *p, int ctl) if(waserror()) { up->psstate = state; qlock(&p->debug); - p->pdbg = nil; + if(p->pdbg == up) + p->pdbg = nil; nexterror(); } sleep(&up->sleep, procstopped, p); @@ -1440,9 +1427,6 @@ procctlreq(Proc *p, char *va, int n) char *e; void (*pt)(Proc*, int, vlong); - if(p->kp) /* no ctl requests to kprocs */ - error(Eperm); - cb = parsecmd(va, n); if(waserror()){ free(cb); diff --git a/sys/src/9/port/pgrp.c b/sys/src/9/port/pgrp.c index 190ab7b59..5576acc57 100644 --- a/sys/src/9/port/pgrp.c +++ b/sys/src/9/port/pgrp.c @@ -12,24 +12,6 @@ enum { static Ref pgrpid; static Ref mountid; -void -pgrpnote(ulong noteid, char *n, int flag) -{ - Proc *p, *ep; - - p = proctab(0); - for(ep = p+conf.nproc; p < ep; p++) { - if(p->state == Dead) - continue; - if(up != p && p->noteid == noteid && p->kp == 0) { - qlock(&p->debug); - if(p->noteid == noteid) - postnote(p, 0, n, flag); - qunlock(&p->debug); - } - } -} - Pgrp* newpgrp(void) { diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 2a1cd3b07..7c9aa7193 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -187,7 +187,6 @@ struct Chan Mnt* mux; /* Mnt for clients using me for messages */ union { void* aux; - Qid pgrpid; /* for #p/notepg */ ulong mid; /* for ns in devproc */ }; Chan* mchan; /* channel to mounted server */ @@ -649,28 +648,31 @@ struct Proc Mach *mach; /* machine running this proc */ char *text; char *user; + char *args; int nargs; /* number of bytes of args */ int setargs; /* process changed its args */ + Proc *rnext; /* next process in run queue */ Proc *qnext; /* next process on queue for a QLock */ - QLock *qlock; /* addr of qlock being queued for DEBUG */ - int state; + char *psstate; /* What /proc/#/status reports */ - Segment *seg[NSEG]; - QLock seglock; /* locked whenever seg[] changes */ + int state; + ulong pid; ulong noteid; /* Equivalent of note group */ ulong parentpid; - Proc *pidhash; /* next proc in pid hash */ + Proc *parent; /* Process to send wait record on exit */ Lock exl; /* Lock count and waitq */ Waitq *waitq; /* Exited processes wait children */ int nchild; /* Number of living children */ int nwait; /* Number of uncollected wait records */ QLock qwaitr; Rendez waitr; /* Place to hang out in wait */ - Proc *parent; + + QLock seglock; /* locked whenever seg[] changes */ + Segment *seg[NSEG]; Pgrp *pgrp; /* Process group for namespace */ Egrp *egrp; /* Environment group */ diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index c73ba2aa1..7197afe87 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -215,8 +215,7 @@ void pathclose(Path*); ulong perfticks(void); void pexit(char*, int); void pgrpcpy(Pgrp*, Pgrp*); -void pgrpnote(ulong, char*, int); -int pidalloc(Proc*); +ulong pidalloc(Proc*); #define poperror() up->nerrlab-- void portcountpagerefs(ulong*, int); int postnote(Proc*, int, char*, int); @@ -226,7 +225,6 @@ void prflush(void); void printinit(void); ulong procalarm(ulong); void procctl(void); -void procdump(void); int procfdprint(Chan*, int, char*, int); void procflushseg(Segment*); void procflushpseg(Physseg*); @@ -235,6 +233,7 @@ int procindex(ulong); void procinit0(void); ulong procpagecount(Proc*); void procpriority(Proc*, int, int); +void procsetuser(Proc*, char*); Proc* proctab(int); extern void (*proctrace)(Proc*, int, vlong); void procwired(Proc*, int); @@ -304,7 +303,6 @@ void runlock(RWlock*); Proc* runproc(void); void savefpregs(FPsave*); void sched(void); -void scheddump(void); void schedinit(void); void (*screenputs)(char*, int); void* secalloc(ulong); @@ -318,6 +316,7 @@ int setcolor(ulong, ulong, ulong, ulong); void setkernur(Ureg*, Proc*); int setlabel(Label*); void setmalloctag(void*, uintptr); +ulong setnoteid(Proc*, ulong); void setrealloctag(void*, uintptr); void setregisters(Ureg*, char*, char*, int); void setupwatchpts(Proc*, Watchpt*, int); diff --git a/sys/src/9/port/proc.c b/sys/src/9/port/proc.c index 59cb403b2..f117e0e1c 100644 --- a/sys/src/9/port/proc.c +++ b/sys/src/9/port/proc.c @@ -21,7 +21,6 @@ ulong load; static struct Procalloc { Lock; - Proc* ht[128]; Proc* arena; Proc* free; } procalloc; @@ -53,8 +52,9 @@ char *statename[] = "Waitrelease", }; -static void pidfree(Proc*); static void rebalance(void); +static void pidinit(void); +static void pidfree(Proc*); /* * Always splhi()'ed. @@ -606,31 +606,14 @@ newproc(void) lock(&procalloc); } procalloc.free = p->qnext; + p->qnext = nil; unlock(&procalloc); - assert(p->state == Dead); p->psstate = "New"; - p->mach = nil; - p->eql = nil; - p->qnext = nil; - p->nchild = 0; - p->nwait = 0; - p->waitq = nil; - p->parent = nil; - p->pgrp = nil; - p->egrp = nil; - p->fgrp = nil; - p->rgrp = nil; - p->pdbg = nil; p->fpstate = FPinit; - p->kp = 0; p->procctl = 0; - p->syscalltrace = nil; - p->notepending = 0; p->ureg = nil; p->dbgreg = nil; - p->privatemem = 0; - p->noswap = 0; p->nerrlab = 0; p->errstr = p->errbuf0; p->syserrstr = p->errbuf1; @@ -639,11 +622,6 @@ newproc(void) p->nlocks = 0; p->delaysched = 0; p->trace = 0; - p->nargs = 0; - p->setargs = 0; - memset(p->seg, 0, sizeof p->seg); - p->parentpid = 0; - p->noteid = 0; if(p->kstack == nil) p->kstack = smalloc(KSTACK); @@ -673,8 +651,8 @@ procwired(Proc *p, int bm) /* pick a machine to wire to */ memset(nwired, 0, sizeof(nwired)); p->wired = nil; - pp = proctab(0); - for(i=0; i<conf.nproc; i++, pp++){ + for(i=0; i<conf.nproc; i++){ + pp = proctab(i); wm = pp->wired; if(wm != nil && pp->pid) nwired[wm->machno]++; @@ -724,6 +702,8 @@ procinit0(void) /* bad planning - clashes with devproc.c */ for(i=0; i<conf.nproc-1; i++, p++) p->qnext = p+1; p->qnext = nil; + + pidinit(); } /* @@ -1082,7 +1062,7 @@ void pexit(char *exitstr, int freemem) { Proc *p; - Segment **s, **es; + Segment **s; ulong utime, stime; Waitq *wq; Fgrp *fgrp; @@ -1124,18 +1104,14 @@ pexit(char *exitstr, int freemem) if(pgrp != nil) closepgrp(pgrp); - /* - * if not a kernel process and have a parent, - * do some housekeeping. - */ - if(up->kp) - goto Nowait; + if(up->parentpid == 0){ + if(exitstr == nil) + exitstr = "unknown"; + panic("boot process died: %s", exitstr); + } p = up->parent; - if(p != nil){ - if(p->pid != up->parentpid || p->state == Broken) - goto Nowait; - + if(p != nil && p->pid == up->parentpid && p->state != Broken){ wq = smalloc(sizeof(Waitq)); wq->w.pid = up->pid; utime = up->time[TUser] + up->time[TCUser]; @@ -1175,29 +1151,16 @@ pexit(char *exitstr, int freemem) if(wq != nil) free(wq); } - else if(up->parentpid == 0){ - if(exitstr == nil) - exitstr = "unknown"; - panic("boot process died: %s", exitstr); - } -Nowait: if(!freemem) addbroken(up); - qlock(&up->seglock); - es = &up->seg[NSEG]; - for(s = up->seg; s < es; s++) { - if(*s != nil) { - putseg(*s); - *s = nil; - } - } - qunlock(&up->seglock); + qlock(&up->debug); lock(&up->exl); /* Prevent my children from leaving waits */ pidfree(up); - up->pid = 0; + up->parent = nil; + up->nchild = up->nwait = 0; wakeup(&up->waitr); unlock(&up->exl); @@ -1207,7 +1170,6 @@ Nowait: } /* release debuggers */ - qlock(&up->debug); if(up->pdbg != nil) { wakeup(&up->pdbg->sleep); up->pdbg = nil; @@ -1223,6 +1185,15 @@ Nowait: up->nwatchpt = 0; qunlock(&up->debug); + qlock(&up->seglock); + for(s = up->seg; s < &up->seg[NSEG]; s++) { + if(*s != nil) { + putseg(*s); + *s = nil; + } + } + qunlock(&up->seglock); + /* Sched must not loop for these locks */ lock(&procalloc); lock(&palloc); @@ -1281,7 +1252,8 @@ pwait(Waitmsg *w) Proc* proctab(int i) { - return &procalloc.arena[i]; +#define proctab(x) (&procalloc.arena[(x)]) + return proctab(i); } void @@ -1306,23 +1278,6 @@ dumpaproc(Proc *p) p->lastlock ? p->lastlock->pc : 0, p->priority); } -void -procdump(void) -{ - int i; - Proc *p; - - if(up != nil) - print("up %lud\n", up->pid); - else - print("no current process\n"); - for(i=0; i<conf.nproc; i++) { - p = &procalloc.arena[i]; - if(p->state != Dead) - dumpaproc(p); - } -} - /* * wait till all matching processes have flushed their mmu */ @@ -1339,7 +1294,7 @@ procflushmmu(int (*match)(Proc*, void*), void *a) memset(await, 0, conf.nmach*sizeof(await[0])); nwait = 0; for(i = 0; i < conf.nproc; i++){ - p = &procalloc.arena[i]; + p = proctab(i); if(p->state != Dead && (*match)(p, a)){ p->newtlb = 1; for(nm = 0; nm < conf.nmach; nm++){ @@ -1422,24 +1377,6 @@ procflushothers(void) } void -scheddump(void) -{ - Proc *p; - Schedq *rq; - - for(rq = &runq[Nrq-1]; rq >= runq; rq--){ - if(rq->head == nil) - continue; - print("rq%zd:", rq-runq); - for(p = rq->head; p != nil; p = p->rnext) - print(" %lud(%lud)", p->pid, m->ticks - p->readytime); - print("\n"); - delay(150); - } - print("nrdy %d\n", nrdy); -} - -void kproc(char *name, void (*func)(void *), void *arg) { static Pgrp *kpgrp; @@ -1447,6 +1384,7 @@ kproc(char *name, void (*func)(void *), void *arg) p = newproc(); + qlock(&p->debug); if(up != nil){ p->slash = up->slash; p->dot = up->slash; /* unlike fork, do not inherit the dot for kprocs */ @@ -1460,9 +1398,12 @@ kproc(char *name, void (*func)(void *), void *arg) p->nnote = 0; p->notify = nil; p->notified = 0; + p->notepending = 0; p->procmode = 0640; + p->privatemem = 1; p->noswap = 1; + p->hang = 0; p->kp = 1; kprocchild(p, func, arg); @@ -1470,6 +1411,8 @@ kproc(char *name, void (*func)(void *), void *arg) kstrdup(&p->text, name); kstrdup(&p->user, eve); kstrdup(&p->args, ""); + p->nargs = 0; + p->setargs = 0; if(kpgrp == nil) kpgrp = newpgrp(); @@ -1480,7 +1423,9 @@ kproc(char *name, void (*func)(void *), void *arg) memset(p->time, 0, sizeof(p->time)); p->time[TReal] = MACHP(0)->ticks; - p->noteid = pidalloc(p); + pidalloc(p); + + qunlock(&p->debug); procpriority(p, PriKproc, 0); @@ -1597,12 +1542,12 @@ killbig(char *why) int i; Segment *s; ulong l, max; - Proc *p, *ep, *kp; + Proc *p, *kp; max = 0; kp = nil; - ep = procalloc.arena+conf.nproc; - for(p = procalloc.arena; p < ep; p++) { + for(i = 0; i < conf.nproc; i++) { + p = proctab(i); if(p->state == Dead || p->kp) continue; if((p->noswap || (p->procmode & 0222) == 0) && strcmp(eve, p->user) == 0) @@ -1617,7 +1562,8 @@ killbig(char *why) return; print("%lud: %s killed: %s\n", kp->pid, kp->text, why); qlock(&kp->seglock); - for(p = procalloc.arena; p < ep; p++) { + for(i = 0; i < conf.nproc; i++) { + p = proctab(i); if(p->state == Dead || p->kp) continue; if(p != kp && p->seg[BSEG] != nil && p->seg[BSEG] == kp->seg[BSEG]) @@ -1649,12 +1595,25 @@ killbig(char *why) void renameuser(char *old, char *new) { - Proc *p, *ep; + Proc *p; + int i; - ep = procalloc.arena+conf.nproc; - for(p = procalloc.arena; p < ep; p++) + for(i = 0; i < conf.nproc; i++){ + p = proctab(i); + qlock(&p->debug); if(p->user != nil && strcmp(old, p->user) == 0) kstrdup(&p->user, new); + qunlock(&p->debug); + } +} + +void +procsetuser(Proc *p, char *new) +{ + qlock(&p->debug); + kstrdup(&p->user, new); + p->basepri = PriNormal; + qunlock(&p->debug); } /* @@ -1707,65 +1666,204 @@ accounttime(void) m->load = load/100; } -int -pidalloc(Proc *p) +/* + * A Pid structure is a reference counted hashtable entry + * with "pid" being the key and "procindex" being the value. + * A entry is allocated atomically by changing the key from + * negative or zero to the positive process id number. + * Pid's outlive ther Proc's as long as other processes hold + * a reference to them such as noteid or parentpid. + * This prevents pid reuse when the pid generator wraps. + */ +typedef struct Pid Pid; +struct Pid { - static int gen, wrapped; - int pid, h; - Proc *x; + Ref; + long pid; + int procindex; +}; - lock(&procalloc); -Retry: - pid = ++gen & 0x7FFFFFFF; - if(pid == 0){ - wrapped = 1; - goto Retry; - } - h = pid % nelem(procalloc.ht); - if(wrapped) - for(x = procalloc.ht[h]; x != nil; x = x->pidhash) - if(x->pid == pid) - goto Retry; - if(p != nil){ - p->pid = pid; - p->pidhash = procalloc.ht[h]; - procalloc.ht[h] = p; - } - unlock(&procalloc); - return pid; -} +enum { + PIDMASK = 0x7FFFFFFF, + PIDSHIFT = 4, /* log2 bucket size of the hash table */ +}; + +static Pid *pidhashtab; +static ulong pidhashmask; static void -pidfree(Proc *p) +pidinit(void) { - int h; - Proc **l; + /* + * allocate 3 times conf.nproc Pid structures for the hash table + * and round up to a power of two as each process can reference + * up to 3 unique Pid structures: + * - pid + * - noteid + * - parentpid + */ + pidhashmask = 1<<PIDSHIFT; + while(pidhashmask < conf.nproc*3) + pidhashmask <<= 1; - h = p->pid % nelem(procalloc.ht); - lock(&procalloc); - for(l = &procalloc.ht[h]; *l != nil; l = &(*l)->pidhash) - if(*l == p){ - *l = p->pidhash; + pidhashtab = xalloc(pidhashmask * sizeof(pidhashtab[0])); + if(pidhashtab == nil){ + xsummary(); + panic("cannot allocate pid hashtable of size %lud", pidhashmask); + } + + /* make it a mask */ + pidhashmask--; +} + +static Pid* +pidlookup(long pid) +{ + Pid *i, *e; + long o; + + i = &pidhashtab[(pid<<PIDSHIFT) & pidhashmask]; + for(e = &i[1<<PIDSHIFT]; i < e; i++){ + o = i->pid; + if(o == pid) + return i; + if(o == 0) break; + } + return nil; +} + +/* + * increment the reference count of a pid (pid>0) + * or allocate a new one (pid<=0) + */ +static Pid* +pidadd(long pid) +{ + Pid *i, *e; + long o; + + if(pid > 0){ + i = pidlookup(pid); + if(i != nil) + incref(i); + return i; + } +Again: + do { + static Ref gen; + pid = incref(&gen) & PIDMASK; + } while(pid == 0 || pidlookup(pid) != nil); + + i = &pidhashtab[(pid<<PIDSHIFT) & pidhashmask]; + for(e = &i[1<<PIDSHIFT]; i < e; i++){ + while((o = i->pid) <= 0){ + if(cmpswap(&i->pid, o, pid)){ + incref(i); + return i; + } } - unlock(&procalloc); + } + /* bucket full, try a different pid */ + goto Again; +} + +/* + * decrement reference count of a pid and free it + * when no references are remaining + */ +static void +piddel(Pid *i) +{ + if(decref(i)) + return; + i->pid = -1; /* freed */ } int procindex(ulong pid) { - Proc *p; - int h; - int s; + Pid *i; - s = -1; - h = pid % nelem(procalloc.ht); - lock(&procalloc); - for(p = procalloc.ht[h]; p != nil; p = p->pidhash) - if(p->pid == pid){ - s = p - procalloc.arena; - break; - } - unlock(&procalloc); - return s; + i = pidlookup(pid); + if(i != nil){ + int x = i->procindex; + if(proctab(x)->pid == pid) + return x; + } + return -1; +} + +ulong +setnoteid(Proc *p, ulong noteid) +{ + Pid *i, *o; + + /* + * avoid allocating a new pid when we are the only + * user of the noteid + */ + o = pidlookup(p->noteid); + if(noteid == 0 && o->ref == 1) + return o->pid; + + i = pidadd(noteid); + if(i == nil) + error(Ebadarg); + piddel(o); + return p->noteid = i->pid; +} + +static ulong +setparentpid(Proc *p, Proc *pp) +{ + Pid *i; + + i = pidadd(pp->pid); + return p->parentpid = i->pid; +} + +/* + * allocate pid, noteid and parentpid to a process + */ +ulong +pidalloc(Proc *p) +{ + Pid *i; + + /* skip for the boot process */ + if(up != nil) + setparentpid(p, up); + + i = pidadd(0); + i->procindex = (int)(p - procalloc.arena); + + if(p->noteid == 0){ + incref(i); + p->noteid = i->pid; + } else + pidadd(p->noteid); + + return p->pid = i->pid; +} + +/* + * release pid, noteid and parentpid from a process + */ +static void +pidfree(Proc *p) +{ + Pid *i; + + i = pidlookup(p->pid); + piddel(i); + + if(p->noteid != p->pid) + i = pidlookup(p->noteid); + piddel(i); + + if(p->parentpid != 0) + piddel(pidlookup(p->parentpid)); + + p->pid = p->noteid = p->parentpid = 0; } diff --git a/sys/src/9/port/sysproc.c b/sys/src/9/port/sysproc.c index ad9386b9e..075fdbd43 100644 --- a/sys/src/9/port/sysproc.c +++ b/sys/src/9/port/sysproc.c @@ -80,12 +80,14 @@ sysrfork(va_list list) closeegrp(oeg); } if(flag & RFNOTEG) - up->noteid = pidalloc(nil); + setnoteid(up, 0); return 0; } p = newproc(); + qlock(&p->debug); + p->scallnr = up->scallnr; p->s = up->s; p->slash = up->slash; @@ -96,16 +98,18 @@ sysrfork(va_list list) p->nnote = up->nnote; p->notify = up->notify; p->notified = 0; + p->notepending = 0; p->lastnote = up->lastnote; + if((flag & RFNOTEG) == 0) + p->noteid = up->noteid; - p->noteid = up->noteid; - p->parentpid = up->pid; p->procmode = up->procmode; p->privatemem = up->privatemem; p->noswap = up->noswap; p->hang = up->hang; if(up->procctl == Proc_tracesyscall) p->procctl = Proc_tracesyscall; + p->kp = 0; /* Craft a return frame which will cause the child to pop out of * the scheduler in user mode with the return register zero @@ -115,6 +119,8 @@ sysrfork(va_list list) kstrdup(&p->text, up->text); kstrdup(&p->user, up->user); kstrdup(&p->args, ""); + p->nargs = 0; + p->setargs = 0; p->insyscall = 0; memset(p->time, 0, sizeof(p->time)); @@ -122,6 +128,8 @@ sysrfork(va_list list) pid = pidalloc(p); + qunlock(&p->debug); + /* Abort the child process on error */ if(waserror()){ p->kp = 1; @@ -189,9 +197,6 @@ sysrfork(va_list list) incref(p->egrp); } - if(flag & RFNOTEG) - p->noteid = pid; - procfork(p); poperror(); /* abortion */ diff --git a/sys/src/9/port/userinit.c b/sys/src/9/port/userinit.c index bf4fc8e25..c05210449 100644 --- a/sys/src/9/port/userinit.c +++ b/sys/src/9/port/userinit.c @@ -61,6 +61,7 @@ proc0(void*) */ up->kp = 0; up->noswap = 0; + up->privatemem = 0; procpriority(up, PriNormal, 0); procsetup(up); |
