| plan 9 kernel history: overview | file list | diff list |
1999/1105/port/devproc.c (diff list | history)
| port/devproc.c on 1994/0107 | ||
| 1994/0107 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/0227 | #include "mem.h" #include "dat.h" #include "fns.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1991/1110 | #include "ureg.h" | |
| 1990/0227 | ||
| 1993/0501 | enum { | |
| 1990/0227 | Qctl, | |
| 1993/0818 | Qdir, | |
| 1999/0629 | Qfd, | |
| 1993/0818 | Qfpregs, Qkregs, | |
| 1990/0227 | Qmem, Qnote, | |
| 1993/1018 | Qnoteid, | |
| 1990/1110 | Qnotepg, | |
| 1993/0818 | Qns, | |
| 1993/0828 | Qproc, | |
| 1993/0818 | Qregs, | |
| 1991/0705 | Qsegment, | |
| 1990/0227 | Qstatus, Qtext, | |
| 1993/0309 | Qwait, | |
| 1996/0303 | Qprofile, | |
| 1990/0227 | }; | |
| 1994/0915 | #define STATSIZE (2*NAMELEN+12+9*12) | |
| 1992/0824 | Dirtab procdir[] = { | |
| 1991/1109 | "ctl", {Qctl}, 0, 0000, | |
| 1998/0310 | "fd", {Qfd}, 0, 0000, | |
| 1993/0818 | "fpregs", {Qfpregs}, sizeof(FPsave), 0000, | |
| 1999/1104 | "kregs", {Qkregs}, sizeof(Ureg), 0400, | |
| 1991/1109 | "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, | |
| 1993/1018 | "noteid", {Qnoteid}, 0, 0666, | |
| 1991/1112 | "notepg", {Qnotepg}, 0, 0000, | |
| 1998/1130 | "ns", {Qns}, 0, 0444, | |
| 1993/0828 | "proc", {Qproc}, 0, 0400, | |
| 1993/0818 | "regs", {Qregs}, sizeof(Ureg), 0000, | |
| 1991/1112 | "segment", {Qsegment}, 0, 0444, "status", {Qstatus}, STATSIZE, 0444, | |
| 1991/1109 | "text", {Qtext}, 0, 0000, | |
| 1993/0309 | "wait", {Qwait}, 0, 0400, | |
| 1996/0303 | "profile", {Qprofile}, 0, 0400, | |
| 1990/0227 | }; | |
| 1991/1109 | /* Segment type from portdat.h */ | |
| 1997/0516 | char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata", "Map" }; | |
| 1991/0705 | ||
| 1990/0227 | /* | |
| 1990/11211 | * Qids are, in path: | |
| 1990/0227 | * 4 bits of file type (qids above) | |
| 1990/1128 | * 23 bits of process slot number + 1 | |
| 1990/11211 | * in vers, * 32 bits of pid, for consistency checking | |
| 1992/0428 | * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. | |
| 1990/0227 | */ | |
| 1998/0310 | #define QSHIFT 5 /* location in qid of proc slot # */ | |
| 1990/0227 | ||
| 1998/0310 | #define QID(q) (((q).path&0x0000001F)>>0) #define SLOT(q) ((((q).path&0x07FFFFFE0)>>QSHIFT)-1) | |
| 1992/0428 | #define PID(q) ((q).vers) #define NOTEID(q) ((q).vers) | |
| 1991/1109 | void procctlreq(Proc*, char*, int); int procctlmemio(Proc*, ulong, int, void*, int); | |
| 1992/0824 | Chan* proctext(Chan*, Proc*); Segment* txt2data(Proc*, Segment*); | |
| 1991/1110 | int procstopped(void*); | |
| 1998/1130 | void mntscan(Mntwalk*, Proc*); | |
| 1991/1109 | ||
| 1997/0327 | static int | |
| 1995/0804 | procgen(Chan *c, Dirtab *tab, int, int s, Dir *dp) | |
| 1990/0227 | { | |
| 1992/0824 | Qid qid; | |
| 1990/0227 | Proc *p; | |
| 1996/0303 | Segment *q; | |
| 1990/0227 | char buf[NAMELEN]; | |
| 1993/0311 | ulong pid, path, perm, len; | |
| 1990/0227 | ||
| 1990/11211 | if(c->qid.path == CHDIR){ | |
| 1990/0227 | if(s >= conf.nproc) return -1; p = proctab(s); pid = p->pid; if(pid == 0) return 0; | |
| 1998/0825 | sprint(buf, "%lud", pid); | |
| 1992/0824 | qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid}; devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp); | |
| 1990/0227 | return 1; } | |
| 1997/0327 | if(s >= nelem(procdir)) | |
| 1990/0227 | return -1; if(tab) panic("procgen"); | |
| 1992/0824 | ||
| 1990/0227 | tab = &procdir[s]; | |
| 1991/0705 | path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1)); /* slot component */ | |
| 1991/1109 | p = proctab(SLOT(c->qid)); perm = tab->perm; if(perm == 0) perm = p->procmode; | |
| 1993/0311 | len = tab->length; | |
| 1996/0303 | switch(QID(c->qid)) { case Qwait: | |
| 1993/0311 | len = p->nwait * sizeof(Waitmsg); | |
| 1996/0303 | break; case Qprofile: q = p->seg[TSEG]; if(q && q->profile) { len = (q->top-q->base)>>LRESPROF; len *= sizeof(*q->profile); } break; } | |
| 1993/0311 | ||
| 1992/0824 | qid = (Qid){path|tab->qid.path, c->qid.vers}; | |
| 1993/0311 | devdir(c, qid, tab->name, len, p->user, perm, dp); | |
| 1990/0227 | return 1; } | |
| 1997/0327 | static void | |
| 1990/0227 | procinit(void) { if(conf.nproc >= (1<<(16-QSHIFT))-1) print("warning: too many procs for devproc\n"); } | |
| 1997/0327 | static Chan* | |
| 1990/0227 | procattach(char *spec) { return devattach('p', spec); } | |
| 1997/0327 | static int | |
| 1990/0227 | procwalk(Chan *c, char *name) { | |
| 1991/1106 | if(strcmp(name, "..") == 0) { | |
| 1993/1202 | c->qid.path = CHDIR; | |
| 1991/1011 | return 1; } | |
| 1990/0227 | return devwalk(c, name, 0, 0, procgen); } | |
| 1997/0327 | static void | |
| 1990/0227 | procstat(Chan *c, char *db) { devstat(c, db, 0, 0, procgen); } | |
| 1997/0327 | static Chan* | |
| 1990/0227 | procopen(Chan *c, int omode) { Proc *p; | |
| 1990/1110 | Pgrp *pg; | |
| 1990/0227 | Chan *tc; | |
| 1999/0709 | int pid; | |
| 1990/0227 | ||
| 1991/1112 | if(c->qid.path & CHDIR) return devopen(c, omode, 0, 0, procgen); | |
| 1990/0227 | p = proctab(SLOT(c->qid)); | |
| 1990/1110 | pg = p->pgrp; | |
| 1999/0709 | pid = PID(c->qid); if(p->pid != pid) | |
| 1990/11211 | error(Eprocdied); | |
| 1991/1110 | ||
| 1990/0227 | omode = openmode(omode); switch(QID(c->qid)){ case Qtext: | |
| 1993/0501 | if(omode != OREAD) error(Eperm); | |
| 1991/1110 | tc = proctext(c, p); | |
| 1990/0227 | tc->offset = 0; return tc; | |
| 1991/1110 | ||
| 1993/0828 | case Qproc: | |
| 1993/0818 | case Qkregs: case Qsegment: | |
| 1996/0303 | case Qprofile: | |
| 1998/0310 | case Qfd: | |
| 1993/0818 | if(omode != OREAD) error(Eperm); break; | |
| 1990/0227 | case Qctl: case Qnote: | |
| 1993/1018 | case Qnoteid: | |
| 1991/1110 | case Qmem: | |
| 1991/1112 | case Qstatus: | |
| 1993/0309 | case Qwait: | |
| 1993/0818 | case Qregs: case Qfpregs: | |
| 1990/0227 | break; | |
| 1990/1110 | ||
| 1993/0501 | case Qns: | |
| 1993/0818 | if(omode != OREAD) error(Eperm); | |
| 1993/0501 | c->aux = malloc(sizeof(Mntwalk)); break; | |
| 1990/1110 | case Qnotepg: | |
| 1992/0824 | if(omode!=OWRITE || pg->pgrpid == 1) | |
| 1990/11211 | error(Eperm); | |
| 1992/0824 | c->pgrpid.path = pg->pgrpid+1; | |
| 1992/0428 | c->pgrpid.vers = p->noteid; | |
| 1990/1110 | break; | |
| 1992/0824 | ||
| 1990/0227 | default: | |
| 1992/0114 | pprint("procopen %lux\n", c->qid); | |
| 1990/11211 | error(Egreg); | |
| 1990/0227 | } | |
| 1991/1110 | /* Affix pid to qid */ | |
| 1990/0227 | if(p->state != Dead) | |
| 1990/11211 | c->qid.vers = p->pid; | |
| 1991/1112 | ||
| 1999/0709 | /* make sure the process slot didn't get reallocated while we were playing */ coherence(); if(p->pid != pid) error(Eprocdied); | |
| 1991/1112 | return devopen(c, omode, 0, 0, procgen); | |
| 1990/0227 | } | |
| 1997/0327 | static void | |
| 1990/0227 | procwstat(Chan *c, char *db) { | |
| 1991/1109 | Proc *p; Dir d; | |
| 1991/1112 | if(c->qid.path&CHDIR) error(Eperm); | |
| 1991/1109 | p = proctab(SLOT(c->qid)); | |
| 1999/0709 | if(waserror()){ qunlock(&p->debug); nexterror(); } qlock(&p->debug); | |
| 1991/1109 | if(p->pid != PID(c->qid)) error(Eprocdied); | |
| 1993/0501 | if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0) | |
| 1991/1109 | error(Eperm); | |
| 1993/1013 | convM2D(db, &d); | |
| 1999/0724 | if(strcmp(d.uid, p->user) != 0){ if(strcmp(up->user, eve) != 0) error(Eperm); else { strncpy(p->user, d.uid, sizeof(p->user)); p->user[sizeof(p->user)-1] = 0; } } | |
| 1991/1109 | p->procmode = d.mode&0777; | |
| 1999/0709 | poperror(); qunlock(&p->debug); | |
| 1990/0227 | } | |
| 1998/0310 | static int | |
| 1998/0425 | procfds(Proc *p, char *va, int count, long offset) | |
| 1998/0310 | { | |
| 1998/0425 | Fgrp *f; | |
| 1998/0310 | Chan *c; int n, i; | |
| 1998/0425 | f = p->fgrp; if(f == nil) return 0; if(waserror()){ unlock(f); qunlock(&p->debug); nexterror(); } qlock(&p->debug); lock(f); | |
| 1999/0629 | n = readstr(0, va, count, p->dot->name->s); n += snprint(va+n, count-n, "\n"); | |
| 1998/0310 | for(i = 0; i <= f->maxfd; i++) { c = f->fd[i]; if(c == nil) continue; | |
| 1999/0629 | n += snprint(va+n, count-n, "%3d %.2s %C %4ld %.8lux.%.8lud %8lld ", | |
| 1998/0310 | i, &"r w rw"[(c->mode&3)<<1], | |
| 1999/0629 | devtab[c->type]->dc, c->dev, | |
| 1998/0310 | c->qid.path, c->qid.vers, c->offset); | |
| 1999/0629 | n += readstr(0, va+n, count-n, c->name->s); | |
| 1998/0310 | n += snprint(va+n, count-n, "\n"); if(offset > 0) { offset -= n; if(offset < 0) { memmove(va, va+n+offset, -offset); n = -offset; } else n = 0; } } | |
| 1998/0425 | unlock(f); qunlock(&p->debug); poperror(); | |
| 1998/0310 | return n; } | |
| 1997/0327 | static void | |
| 1990/0227 | procclose(Chan * c) { | |
| 1993/1013 | if(QID(c->qid) == Qns && c->aux != 0) | |
| 1993/0501 | free(c->aux); | |
| 1990/0227 | } | |
| 1999/0629 | static void int2flag(int flag, char *s) { if(flag == 0){ *s = '\0'; return; } *s++ = '-'; if(flag & MAFTER) *s++ = 'a'; if(flag & MBEFORE) *s++ = 'b'; if(flag & MCREATE) *s++ = 'c'; if(flag & MCACHE) *s++ = 'C'; *s = '\0'; } | |
| 1997/0327 | static long | |
| 1998/0319 | procread(Chan *c, void *va, long n, vlong off) | |
| 1990/0227 | { | |
| 1993/0501 | long l; | |
| 1990/0227 | Proc *p; | |
| 1993/0309 | Waitq *wq; | |
| 1993/0818 | Ureg kur; uchar *rptr; | |
| 1993/0501 | Mntwalk *mw; Segment *sg, *s; char *a = va, *sps; | |
| 1996/0121 | int i, j, rsize, pid; | |
| 1999/0629 | char statbuf[NSEG*32], *srv, flag[10]; | |
| 1998/0319 | ulong offset = off; | |
| 1990/0227 | ||
| 1990/11211 | if(c->qid.path & CHDIR) | |
| 1990/0227 | return devdirread(c, a, n, 0, 0, procgen); p = proctab(SLOT(c->qid)); | |
| 1990/11211 | if(p->pid != PID(c->qid)) error(Eprocdied); | |
| 1990/0227 | switch(QID(c->qid)){ case Qmem: | |
| 1994/0219 | if(offset < KZERO || (offset >= USTKTOP-USTKSIZE && offset < USTKTOP)) | |
| 1993/0818 | return procctlmemio(p, offset, n, va, 1); | |
| 1992/0824 | ||
| 1993/0818 | /* Protect crypt key memory */ if(offset >= palloc.cmembase&&offset < palloc.cmemtop) error(Eperm); /* validate physical kernel addresses */ if(offset < (ulong)end) { if(offset+n > (ulong)end) n = (ulong)end - offset; memmove(a, (char*)offset, n); | |
| 1993/0908 | return n; | |
| 1990/0227 | } | |
| 1993/0818 | if(offset >= conf.base0 && offset < conf.npage0){ if(offset+n > conf.npage0) n = conf.npage0 - offset; memmove(a, (char*)offset, n); | |
| 1993/0908 | return n; | |
| 1993/0818 | } if(offset >= conf.base1 && offset < conf.npage1){ if(offset+n > conf.npage1) n = conf.npage1 - offset; | |
| 1994/0814 | memmove(a, (char*)offset, n); return n; } | |
| 1993/0818 | error(Ebadarg); | |
| 1996/0303 | case Qprofile: s = p->seg[TSEG]; if(s == 0 || s->profile == 0) error("profile is off"); i = (s->top-s->base)>>LRESPROF; i *= sizeof(*s->profile); if(offset >= i) return 0; if(offset+n > i) n = i - offset; memmove(a, ((char*)s->profile)+offset, n); return n; | |
| 1991/1109 | ||
| 1990/0227 | case Qnote: | |
| 1991/1216 | qlock(&p->debug); | |
| 1990/0227 | if(waserror()){ | |
| 1991/1216 | qunlock(&p->debug); | |
| 1990/0227 | nexterror(); } | |
| 1990/11211 | if(p->pid != PID(c->qid)) error(Eprocdied); | |
| 1990/0227 | if(n < ERRLEN) | |
| 1990/11211 | error(Etoosmall); | |
| 1993/0501 | if(p->nnote == 0) | |
| 1990/0227 | n = 0; | |
| 1993/0501 | else { memmove(va, p->note[0].msg, ERRLEN); p->nnote--; memmove(p->note, p->note+1, p->nnote*sizeof(Note)); | |
| 1990/0227 | n = ERRLEN; } | |
| 1993/0501 | if(p->nnote == 0) | |
| 1991/1111 | p->notepending = 0; | |
| 1991/0614 | poperror(); | |
| 1991/1216 | qunlock(&p->debug); | |
| 1990/0227 | return n; | |
| 1993/0828 | case Qproc: | |
| 1995/0212 | if(offset >= sizeof(Proc)) return 0; if(offset+n > sizeof(Proc)) n = sizeof(Proc) - offset; memmove(a, ((char*)p)+offset, n); return n; | |
| 1990/0227 | ||
| 1993/0818 | case Qregs: rptr = (uchar*)p->dbgreg; rsize = sizeof(Ureg); goto regread; case Qkregs: memset(&kur, 0, sizeof(Ureg)); | |
| 1993/1022 | setkernur(&kur, p); | |
| 1993/0818 | rptr = (uchar*)&kur; rsize = sizeof(Ureg); goto regread; case Qfpregs: rptr = (uchar*)&p->fpsave; rsize = sizeof(FPsave); regread: | |
| 1997/1206 | if(rptr == 0) error(Enoreg); | |
| 1993/0818 | if(offset >= rsize) | |
| 1990/0227 | return 0; | |
| 1993/0818 | if(offset+n > rsize) n = rsize - offset; memmove(a, rptr+offset, n); | |
| 1990/0227 | return n; case Qstatus: | |
| 1991/0712 | if(offset >= STATSIZE) | |
| 1990/0227 | return 0; | |
| 1991/0712 | if(offset+n > STATSIZE) n = STATSIZE - offset; | |
| 1992/0423 | ||
| 1992/0907 | sps = p->psstate; if(sps == 0) sps = statename[p->state]; | |
| 1992/1103 | memset(statbuf, ' ', sizeof statbuf); memmove(statbuf+0*NAMELEN, p->text, strlen(p->text)); memmove(statbuf+1*NAMELEN, p->user, strlen(p->user)); memmove(statbuf+2*NAMELEN, sps, strlen(sps)); j = 2*NAMELEN + 12; | |
| 1992/0907 | for(i = 0; i < 6; i++) { | |
| 1990/0227 | l = p->time[i]; if(i == TReal) l = MACHP(0)->ticks - l; | |
| 1990/0614 | l = TK2MS(l); | |
| 1991/0712 | readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE); | |
| 1990/0227 | } | |
| 1992/0814 | /* ignore stack, which is mostly non-existent */ l = 0; for(i=1; i<NSEG; i++){ s = p->seg[i]; if(s) l += s->top - s->base; } readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE); | |
| 1995/0110 | readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE); readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE); | |
| 1991/0411 | memmove(a, statbuf+offset, n); | |
| 1990/0227 | return n; | |
| 1991/1110 | ||
| 1991/0705 | case Qsegment: j = 0; | |
| 1993/0818 | for(i = 0; i < NSEG; i++) { sg = p->seg[i]; if(sg == 0) continue; | |
| 1998/0825 | j += sprint(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\n", | |
| 1993/0818 | sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ', | |
| 1996/0303 | sg->profile ? 'P' : ' ', | |
| 1991/0705 | sg->base, sg->top, sg->ref); | |
| 1993/0818 | } | |
| 1991/0705 | if(offset >= j) return 0; if(offset+n > j) n = j-offset; | |
| 1991/1112 | if(n == 0 && offset == 0) | |
| 1992/0114 | exhausted("segments"); | |
| 1991/0705 | memmove(a, &statbuf[offset], n); return n; | |
| 1993/0309 | case Qwait: if(n < sizeof(Waitmsg)) error(Etoosmall); if(!canqlock(&p->qwaitr)) error(Einuse); if(waserror()) { qunlock(&p->qwaitr); nexterror(); } lock(&p->exl); | |
| 1993/0501 | if(up == p && p->nchild == 0 && p->waitq == 0) { | |
| 1993/0311 | unlock(&p->exl); error(Enochild); } | |
| 1996/0121 | pid = p->pid; | |
| 1993/0309 | while(p->waitq == 0) { unlock(&p->exl); sleep(&p->waitr, haswaitq, p); | |
| 1996/0121 | if(p->pid != pid) error(Eprocdied); | |
| 1993/0309 | lock(&p->exl); } wq = p->waitq; p->waitq = wq->next; p->nwait--; unlock(&p->exl); qunlock(&p->qwaitr); poperror(); memmove(a, &wq->w, sizeof(Waitmsg)); free(wq); return sizeof(Waitmsg); | |
| 1993/0501 | case Qns: mw = c->aux; | |
| 1999/0629 | if(mw->cddone) | |
| 1993/0501 | return 0; | |
| 1999/0629 | mntscan(mw, p); if(mw->mh == 0){ mw->cddone = 1; i = snprint(a, n, "cd %s\n", p->dot->name->s); return i; | |
| 1993/0501 | } | |
| 1999/0629 | int2flag(mw->cm->flag, flag); if(strcmp(mw->cm->to->name->s, "#M") == 0){ srv = srvname(mw->cm->to->mchan); i = snprint(a, n, "mount %s %s %s %.*s\n", flag, srv==nil? mw->cm->to->mchan->name->s : srv, mw->mh->from->name->s, NAMELEN, mw->cm->spec); free(srv); }else i = snprint(a, n, "bind %s %s %s\n", flag, mw->cm->to->name->s, mw->mh->from->name->s); return i; | |
| 1993/1018 | case Qnoteid: return readnum(offset, va, n, p->noteid, NUMSIZE); | |
| 1998/0310 | case Qfd: | |
| 1998/0425 | return procfds(p, va, n, offset); | |
| 1990/0227 | } | |
| 1990/11211 | error(Egreg); | |
| 1992/0520 | return 0; /* not reached */ | |
| 1990/0227 | } | |
| 1993/0501 | void | |
| 1998/1130 | mntscan(Mntwalk *mw, Proc *p) | |
| 1993/0501 | { Pgrp *pg; Mount *t; | |
| 1994/0613 | Mhead *f; int nxt, i; | |
| 1993/0501 | ulong last, bestmid; | |
| 1990/0227 | ||
| 1998/1130 | pg = p->pgrp; | |
| 1993/0501 | rlock(&pg->ns); nxt = 0; bestmid = ~0; | |
| 1994/0613 | last = 0; | |
| 1993/0501 | if(mw->mh) last = mw->cm->mountid; | |
| 1994/0613 | for(i = 0; i < MNTHASH; i++) { for(f = pg->mnthash[i]; f; f = f->hash) { | |
| 1993/0501 | for(t = f->mount; t; t = t->next) { if(mw->mh == 0 || (t->mountid > last && t->mountid < bestmid)) { mw->cm = t; mw->mh = f; bestmid = mw->cm->mountid; nxt = 1; } } } } if(nxt == 0) mw->mh = 0; runlock(&pg->ns); } | |
| 1997/0327 | static long | |
| 1998/0319 | procwrite(Chan *c, void *va, long n, vlong off) | |
| 1990/0227 | { | |
| 1993/1018 | int id; Proc *p, *t, *et; | |
| 1993/1031 | char *a, buf[ERRLEN]; | |
| 1998/0319 | ulong offset = off; | |
| 1990/0227 | ||
| 1993/1031 | a = va; | |
| 1990/11211 | if(c->qid.path & CHDIR) error(Eisdir); | |
| 1990/1110 | ||
| 1990/1126 | p = proctab(SLOT(c->qid)); | |
| 1991/1109 | ||
| 1993/0501 | /* Use the remembered noteid in the channel rather * than the process pgrpid */ | |
| 1992/0428 | if(QID(c->qid) == Qnotepg) { pgrpnote(NOTEID(c->pgrpid), va, n, NUser); | |
| 1990/1110 | return n; } | |
| 1991/1216 | qlock(&p->debug); | |
| 1990/0227 | if(waserror()){ | |
| 1991/1216 | qunlock(&p->debug); | |
| 1990/0227 | nexterror(); } | |
| 1990/11211 | if(p->pid != PID(c->qid)) error(Eprocdied); | |
| 1990/0227 | switch(QID(c->qid)){ | |
| 1991/1109 | case Qmem: | |
| 1991/1110 | if(p->state != Stopped) | |
| 1992/0114 | error(Ebadctl); | |
| 1991/1110 | ||
| 1993/0501 | n = procctlmemio(p, offset, n, va, 0); | |
| 1993/0818 | break; case Qregs: if(offset >= sizeof(Ureg)) return 0; if(offset+n > sizeof(Ureg)) n = sizeof(Ureg) - offset; | |
| 1997/1206 | if(p->dbgreg == 0) error(Enoreg); | |
| 1993/0818 | setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n); break; case Qfpregs: if(offset >= sizeof(FPsave)) return 0; if(offset+n > sizeof(FPsave)) n = sizeof(FPsave) - offset; memmove((uchar*)&p->fpsave+offset, va, n); | |
| 1991/1110 | break; | |
| 1990/0227 | case Qctl: | |
| 1991/1109 | procctlreq(p, va, n); | |
| 1991/1110 | break; | |
| 1990/0227 | case Qnote: | |
| 1991/1112 | if(p->kp) | |
| 1992/0114 | error(Eperm); | |
| 1990/0227 | if(n >= ERRLEN-1) | |
| 1990/11211 | error(Etoobig); | |
| 1991/0318 | memmove(buf, va, n); | |
| 1990/0227 | buf[n] = 0; if(!postnote(p, 0, buf, NUser)) | |
| 1992/0527 | error("note not posted"); | |
| 1990/0227 | break; | |
| 1993/1018 | case Qnoteid: | |
| 1993/1031 | id = atoi(a); | |
| 1993/1018 | if(id == p->pid) { p->noteid = id; break; } t = proctab(0); for(et = t+conf.nproc; t < et; t++) { if(id == t->noteid) { if(strcmp(p->user, t->user) != 0) error(Eperm); p->noteid = id; break; } } if(p->noteid != id) error(Ebadarg); break; | |
| 1990/0227 | default: pprint("unknown qid in procwrite\n"); | |
| 1990/11211 | error(Egreg); | |
| 1990/0227 | } | |
| 1991/0614 | poperror(); | |
| 1991/1216 | qunlock(&p->debug); | |
| 1991/1109 | return n; | |
| 1995/0108 | } | |
| 1997/0327 | Dev procdevtab = { | |
| 1997/0408 | 'p', "proc", | |
| 1997/0327 | devreset, procinit, procattach, devclone, procwalk, procstat, procopen, devcreate, procclose, procread, devbread, procwrite, devbwrite, devremove, procwstat, }; | |
| 1991/1109 | ||
| 1997/0327 | Chan* | |
| 1991/1110 | proctext(Chan *c, Proc *p) { Chan *tc; Image *i; Segment *s; s = p->seg[TSEG]; | |
| 1991/1112 | if(s == 0) | |
| 1992/0114 | error(Enonexist); | |
| 1991/1112 | if(p->state==Dead) | |
| 1991/1110 | error(Eprocdied); lock(s); i = s->image; if(i == 0) { unlock(s); error(Eprocdied); } unlock(s); lock(i); if(waserror()) { unlock(i); nexterror(); } tc = i->c; if(tc == 0) error(Eprocdied); if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) { | |
| 1997/0327 | cclose(tc); | |
| 1991/1110 | error(Eprocdied); } if(p->pid != PID(c->qid)) error(Eprocdied); unlock(i); poperror(); return tc; | |
| 1991/1109 | } void | |
| 1991/1110 | procstopwait(Proc *p, int ctl) { int pid; if(p->pdbg) | |
| 1992/0114 | error(Einuse); | |
| 1991/1110 | if(procstopped(p)) return; if(ctl != 0) p->procctl = ctl; | |
| 1993/0501 | p->pdbg = up; | |
| 1991/1110 | pid = p->pid; | |
| 1991/1216 | qunlock(&p->debug); | |
| 1993/0501 | up->psstate = "Stopwait"; | |
| 1991/1110 | if(waserror()) { p->pdbg = 0; | |
| 1991/1216 | qlock(&p->debug); | |
| 1991/1110 | nexterror(); } | |
| 1993/0501 | sleep(&up->sleep, procstopped, p); | |
| 1991/1110 | poperror(); | |
| 1991/1216 | qlock(&p->debug); | |
| 1991/1110 | if(p->pid != pid) error(Eprocdied); } void | |
| 1995/0319 | procctlfgrp(Fgrp *f) { int i; Chan *c; lock(f); f->ref++; for(i = 0; i < f->maxfd; i++) { c = f->fd[i]; if(c != 0) { f->fd[i] = 0; unlock(f); | |
| 1997/0327 | cclose(c); | |
| 1995/0319 | lock(f); } } unlock(f); closefgrp(f); } void | |
| 1991/1109 | procctlreq(Proc *p, char *va, int n) { | |
| 1996/0303 | Segment *s; int i, npc; | |
| 1995/0319 | char buf[NAMELEN]; | |
| 1991/1109 | ||
| 1991/1112 | if(n > NAMELEN) n = NAMELEN; strncpy(buf, va, n); | |
| 1991/1117 | if(strncmp(buf, "stop", 4) == 0) | |
| 1991/1112 | procstopwait(p, Proc_stopme); | |
| 1993/0501 | else if(strncmp(buf, "kill", 4) == 0) { | |
| 1992/1206 | switch(p->state) { case Broken: unbreak(p); break; case Stopped: postnote(p, 0, "sys: killed", NExit); p->procctl = Proc_exitme; | |
| 1991/1112 | ready(p); | |
| 1992/1206 | break; default: | |
| 1991/1117 | postnote(p, 0, "sys: killed", NExit); p->procctl = Proc_exitme; } | |
| 1991/1112 | } | |
| 1993/0501 | else if(strncmp(buf, "hang", 4) == 0) | |
| 1991/1112 | p->hang = 1; | |
| 1993/0501 | else if(strncmp(buf, "nohang", 6) == 0) | |
| 1993/0318 | p->hang = 0; | |
| 1993/0501 | else if(strncmp(buf, "waitstop", 8) == 0) | |
| 1991/1112 | procstopwait(p, 0); | |
| 1993/0501 | else if(strncmp(buf, "startstop", 9) == 0) { | |
| 1991/1110 | if(p->state != Stopped) | |
| 1992/0114 | error(Ebadctl); | |
| 1991/1110 | p->procctl = Proc_traceme; ready(p); procstopwait(p, Proc_traceme); } | |
| 1993/0501 | else if(strncmp(buf, "start", 5) == 0) { | |
| 1991/1109 | if(p->state != Stopped) | |
| 1992/0114 | error(Ebadctl); | |
| 1991/1109 | ready(p); | |
| 1994/0817 | } | |
| 1995/0319 | else | |
| 1999/1104 | if(strncmp(buf, "closefiles", 10) == 0) | |
| 1995/0319 | procctlfgrp(p->fgrp); | |
| 1994/0817 | else | |
| 1996/0303 | if(strncmp(buf, "pri", 3) == 0) { | |
| 1995/0110 | if(n < 4) | |
| 1994/0914 | error(Ebadctl); | |
| 1995/0110 | i = atoi(buf+4); | |
| 1994/0915 | if(i < 0) i = 0; | |
| 1995/0110 | if(i >= Nrq) i = Nrq - 1; | |
| 1999/0224 | if(i > p->basepri && !iseve()) | |
| 1995/0110 | error(Eperm); p->basepri = i; | |
| 1995/0102 | } else | |
| 1996/0303 | if(strncmp(buf, "wired", 5) == 0) { | |
| 1995/0102 | if(n < 6) error(Ebadctl); i = atoi(buf+6); | |
| 1999/0711 | procwired(p, i); | |
| 1996/0303 | } else if(strncmp(buf, "profile", 7) == 0) { s = p->seg[TSEG]; if(s == 0 || (s->type&SG_TYPE) != SG_TEXT) error(Ebadctl); if(s->profile != 0) free(s->profile); npc = (s->top-s->base)>>LRESPROF; s->profile = malloc(npc*sizeof(*s->profile)); if(s->profile == 0) error(Enomem); | |
| 1991/1109 | } | |
| 1991/1112 | else error(Ebadctl); | |
| 1991/1109 | } int | |
| 1991/1110 | procstopped(void *a) { Proc *p = a; return p->state == Stopped; } int | |
| 1991/1109 | procctlmemio(Proc *p, ulong offset, int n, void *va, int read) { | |
| 1992/0824 | KMap *k; | |
| 1991/1113 | Pte *pte; | |
| 1991/1109 | Page *pg; | |
| 1991/1110 | Segment *s; | |
| 1992/0423 | ulong soff, l; | |
| 1991/1109 | char *a = va, *b; | |
| 1991/1113 | for(;;) { s = seg(p, offset, 1); if(s == 0) | |
| 1992/0114 | error(Ebadarg); | |
| 1991/1109 | ||
| 1991/1113 | if(offset+n >= s->top) n = s->top-offset; | |
| 1991/1109 | ||
| 1994/0409 | if(!read && (s->type&SG_TYPE) == SG_TEXT) | |
| 1991/1113 | s = txt2data(p, s); | |
| 1991/1109 | ||
| 1991/1113 | s->steal++; soff = offset-s->base; | |
| 1991/1109 | if(waserror()) { s->steal--; nexterror(); } | |
| 1991/1113 | if(fixfault(s, offset, read, 0) == 0) break; | |
| 1991/1109 | poperror(); | |
| 1991/1113 | s->steal--; | |
| 1991/1109 | } | |
| 1991/1113 | poperror(); pte = s->map[soff/PTEMAPMEM]; if(pte == 0) | |
| 1998/0512 | panic("procctlmemio"); | |
| 1991/1113 | pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG]; if(pagedout(pg)) | |
| 1998/0512 | panic("procctlmemio1"); | |
| 1992/0423 | l = BY2PG - (offset&(BY2PG-1)); if(n > l) n = l; | |
| 1991/1109 | k = kmap(pg); | |
| 1997/1208 | if(waserror()) { s->steal--; kunmap(k); nexterror(); } | |
| 1991/1109 | b = (char*)VA(k); | |
| 1995/0105 | b += offset&(BY2PG-1); | |
| 1991/1110 | if(read == 1) | |
| 1997/1208 | memmove(a, b, n); /* This can fault */ | |
| 1995/0106 | else | |
| 1995/0105 | memmove(b, a, n); | |
| 1991/1109 | kunmap(k); | |
| 1997/1208 | poperror(); | |
| 1991/1109 | ||
| 1993/1218 | /* Ensure the process sees text page changes */ if(s->flushme) memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl)); | |
| 1991/1109 | s->steal--; | |
| 1991/1110 | if(read == 0) p->newtlb = 1; | |
| 1993/1218 | ||
| 1990/0227 | return n; | |
| 1991/1110 | } | |
| 1992/1104 | Segment* | |
| 1991/1110 | txt2data(Proc *p, Segment *s) { int i; | |
| 1992/0824 | Segment *ps; | |
| 1991/1110 | ps = newseg(SG_DATA, s->base, s->size); ps->image = s->image; incref(ps->image); ps->fstart = s->fstart; ps->flen = s->flen; ps->flushme = 1; | |
| 1999/0108 | qlock(&p->seglock); | |
| 1991/1110 | for(i = 0; i < NSEG; i++) if(p->seg[i] == s) break; if(p->seg[i] != s) panic("segment gone"); qunlock(&s->lk); putseg(s); qlock(&ps->lk); p->seg[i] = ps; | |
| 1999/0108 | qunlock(&p->seglock); | |
| 1992/1104 | return ps; } Segment* data2txt(Segment *s) { Segment *ps; ps = newseg(SG_TEXT, s->base, s->size); ps->image = s->image; incref(ps->image); ps->fstart = s->fstart; ps->flen = s->flen; ps->flushme = 1; | |
| 1991/1110 | return ps; | |
| 1990/0227 | } | |