| plan 9 kernel history: overview | file list | diff list |
1993/1013/port/devproc.c (diff list | history)
| port/devproc.c on 1990/0227 | ||
| 1990/0227 | #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 | #include "devtab.h" | |
| 1993/0501 | enum { | |
| 1990/0227 | Qctl, | |
| 1993/0818 | Qdir, Qfpregs, Qkregs, | |
| 1990/0227 | Qmem, Qnote, | |
| 1990/1110 | Qnotepg, | |
| 1993/0818 | Qns, | |
| 1993/0828 | Qproc, | |
| 1993/0818 | Qregs, | |
| 1991/0705 | Qsegment, | |
| 1990/0227 | Qstatus, Qtext, | |
| 1993/0309 | Qwait, | |
| 1990/0227 | }; | |
| 1992/0814 | #define STATSIZE (2*NAMELEN+12+7*12) | |
| 1992/0824 | Dirtab procdir[] = { | |
| 1991/1109 | "ctl", {Qctl}, 0, 0000, | |
| 1993/0818 | "fpregs", {Qfpregs}, sizeof(FPsave), 0000, "kregs", {Qkregs}, sizeof(Ureg), 0000, | |
| 1991/1109 | "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, | |
| 1991/1112 | "notepg", {Qnotepg}, 0, 0000, | |
| 1993/0818 | "ns", {Qns}, 0, 0400, | |
| 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, | |
| 1990/0227 | }; | |
| 1991/1109 | /* Segment type from portdat.h */ | |
| 1992/0430 | char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata" }; | |
| 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 | */ #define NPROC (sizeof procdir/sizeof(Dirtab)) #define QSHIFT 4 /* location in qid of proc slot # */ | |
| 1992/0428 | #define QID(q) (((q).path&0x0000000F)>>0) #define SLOT(q) ((((q).path&0x07FFFFFF0)>>QSHIFT)-1) #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*); | |
| 1993/0501 | void mntscan(Mntwalk*); | |
| 1991/1109 | ||
| 1990/0227 | int procgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) { | |
| 1992/0824 | Qid qid; | |
| 1990/0227 | Proc *p; char buf[NAMELEN]; | |
| 1993/0311 | ulong pid, path, perm, len; | |
| 1990/0227 | ||
| 1992/0711 | USED(ntab); | |
| 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; sprint(buf, "%d", pid); | |
| 1992/0824 | qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid}; devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp); | |
| 1990/0227 | return 1; } if(s >= NPROC) 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; if(QID(c->qid) == Qwait) len = p->nwait * sizeof(Waitmsg); | |
| 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; } void procinit(void) { if(conf.nproc >= (1<<(16-QSHIFT))-1) print("warning: too many procs for devproc\n"); } void procreset(void) { } Chan* procattach(char *spec) { return devattach('p', spec); } Chan* procclone(Chan *c, Chan *nc) { return devclone(c, nc); } int procwalk(Chan *c, char *name) { | |
| 1991/1106 | if(strcmp(name, "..") == 0) { | |
| 1991/1011 | c->qid.path = Qdir|CHDIR; return 1; } | |
| 1990/0227 | return devwalk(c, name, 0, 0, procgen); } void procstat(Chan *c, char *db) { devstat(c, db, 0, 0, procgen); } Chan * procopen(Chan *c, int omode) { Proc *p; | |
| 1990/1110 | Pgrp *pg; | |
| 1990/0227 | Chan *tc; | |
| 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; | |
| 1990/11211 | if(p->pid != PID(c->qid)) 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: if(omode != OREAD) error(Eperm); break; | |
| 1990/0227 | case Qctl: case Qnote: | |
| 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 | return devopen(c, omode, 0, 0, procgen); | |
| 1990/0227 | } void proccreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1991/1115 | USED(c, name, omode, perm); | |
| 1990/11211 | error(Eperm); | |
| 1990/0227 | } void procremove(Chan *c) { | |
| 1991/1115 | USED(c); | |
| 1990/11211 | error(Eperm); | |
| 1990/0227 | } void 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)); 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); | |
| 1991/1109 | p->procmode = d.mode&0777; | |
| 1990/0227 | } void procclose(Chan * c) { | |
| 1993/1013 | if(QID(c->qid) == Qns && c->aux != 0) | |
| 1993/0501 | free(c->aux); | |
| 1990/0227 | } long | |
| 1991/0411 | procread(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { | |
| 1993/0501 | long l; | |
| 1990/0227 | Proc *p; | |
| 1993/0309 | Waitq *wq; | |
| 1993/0818 | Ureg kur; uchar *rptr; | |
| 1993/0501 | Mntwalk *mw; | |
| 1993/0818 | int i, j, rsize; | |
| 1993/0501 | Segment *sg, *s; char *a = va, *sps; char statbuf[NSEG*32]; | |
| 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: | |
| 1993/0818 | if(offset < KZERO) 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; memmove(a, (char*)offset, n); | |
| 1993/0908 | return n; | |
| 1993/0818 | } error(Ebadarg); | |
| 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: return readnum(offset, va, n, (ulong)p, NUMSIZE); | |
| 1990/0227 | ||
| 1993/0818 | case Qregs: rptr = (uchar*)p->dbgreg; rsize = sizeof(Ureg); goto regread; case Qkregs: memset(&kur, 0, sizeof(Ureg)); kur.pc = p->sched.pc; kur.sp = p->sched.sp; | |
| 1993/0908 | kur.r31 = (ulong)sched; | |
| 1993/0818 | rptr = (uchar*)&kur; rsize = sizeof(Ureg); goto regread; case Qfpregs: rptr = (uchar*)&p->fpsave; rsize = sizeof(FPsave); regread: 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); | |
| 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; j += sprint(&statbuf[j], "%-6s %c %.8lux %.8lux %4d\n", sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ', | |
| 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); } | |
| 1993/0309 | while(p->waitq == 0) { unlock(&p->exl); sleep(&p->waitr, haswaitq, p); 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; mntscan(mw); if(mw->mh == 0) return 0; if(n < NAMELEN+11) error(Etoosmall); i = sprint(a, "%s %d ", mw->cm->spec, mw->cm->flag); n -= i; a += i; i = ptpath(mw->mh->from->path, a, n); n -= i; a += i; if(n > 0) { *a++ = ' '; n--; } a += ptpath(mw->cm->to->path, a, n); return a - (char*)va; | |
| 1990/0227 | } | |
| 1990/11211 | error(Egreg); | |
| 1992/0520 | return 0; /* not reached */ | |
| 1990/0227 | } | |
| 1993/0501 | void mntscan(Mntwalk *mw) { Pgrp *pg; Mount *t; int nxt; ulong last, bestmid; Mhead **h, **he, *f; | |
| 1990/0227 | ||
| 1993/0501 | pg = up->pgrp; rlock(&pg->ns); nxt = 0; last = 0; bestmid = ~0; if(mw->mh) last = mw->cm->mountid; he = &pg->mnthash[MNTHASH]; for(h = pg->mnthash; h < he; h++) { for(f = *h; f; f = f->hash) { 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); } | |
| 1990/0227 | long | |
| 1991/0411 | procwrite(Chan *c, void *va, long n, ulong offset) | |
| 1990/0227 | { Proc *p; char buf[ERRLEN]; | |
| 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; 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; | |
| 1991/1110 | ||
| 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; } 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) { close(tc); 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 | |
| 1991/1109 | procctlreq(Proc *p, char *va, int n) { | |
| 1991/1112 | 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); } | |
| 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 | ||
| 1993/0501 | if((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) panic("procctlmemio"); pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG]; if(pagedout(pg)) panic("procctlmemio1"); | |
| 1992/0423 | l = BY2PG - (offset&(BY2PG-1)); if(n > l) n = l; | |
| 1991/1109 | k = kmap(pg); b = (char*)VA(k); | |
| 1991/1110 | if(read == 1) memmove(a, b+(offset&(BY2PG-1)), n); else memmove(b+(offset&(BY2PG-1)), a, n); | |
| 1991/1109 | kunmap(k); s->steal--; qunlock(&s->lk); | |
| 1991/1110 | if(read == 0) p->newtlb = 1; | |
| 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; 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; | |
| 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 | } | |