Annotation of lucent/sys/src/9/port/devproc.c, revision 1.1.1.1

1.1       root        1: #include       "u.h"
                      2: #include       "../port/lib.h"
                      3: #include       "mem.h"
                      4: #include       "dat.h"
                      5: #include       "fns.h"
                      6: #include       "../port/error.h"
                      7: #include       "ureg.h"
                      8: 
                      9: #include       "devtab.h"
                     10: 
                     11: enum{
                     12:        Qdir,
                     13:        Qctl,
                     14:        Qmem,
                     15:        Qnote,
                     16:        Qnoteid,
                     17:        Qnotepg,
                     18:        Qproc,
                     19:        Qsegment,
                     20:        Qstatus,
                     21:        Qtext,
                     22:        Qwait,
                     23: };
                     24: 
                     25: #define        STATSIZE        (2*NAMELEN+12+7*12)
                     26: Dirtab procdir[] =
                     27: {
                     28:        "ctl",          {Qctl},         0,                      0000,
                     29:        "mem",          {Qmem},         0,                      0000,
                     30:        "note",         {Qnote},        0,                      0000,
                     31:        "noteid",       {Qnoteid},      0,                      0666,
                     32:        "notepg",       {Qnotepg},      0,                      0000,
                     33:        "proc",         {Qproc},        sizeof(Proc),           0444,
                     34:        "segment",      {Qsegment},     0,                      0444,
                     35:        "status",       {Qstatus},      STATSIZE,               0444,
                     36:        "text",         {Qtext},        0,                      0000,
                     37:        "wait",         {Qwait},        0,                      0400,
                     38: };
                     39: 
                     40: /* Segment type from portdat.h */
                     41: char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata" };
                     42: 
                     43: /*
                     44:  * Qids are, in path:
                     45:  *      4 bits of file type (qids above)
                     46:  *     23 bits of process slot number + 1
                     47:  *          in vers,
                     48:  *     32 bits of pid, for consistency checking
                     49:  * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
                     50:  */
                     51: #define        NPROC   (sizeof procdir/sizeof(Dirtab))
                     52: #define        QSHIFT  4       /* location in qid of proc slot # */
                     53: 
                     54: #define        QID(q)          (((q).path&0x0000000F)>>0)
                     55: #define        SLOT(q)         ((((q).path&0x07FFFFFF0)>>QSHIFT)-1)
                     56: #define        PID(q)          ((q).vers)
                     57: #define        NOTEID(q)       ((q).vers)
                     58: 
                     59: void   procctlreq(Proc*, char*, int);
                     60: int    procctlmemio(Proc*, ulong, int, void*, int);
                     61: Chan*  proctext(Chan*, Proc*);
                     62: Segment* txt2data(Proc*, Segment*);
                     63: int    procstopped(void*);
                     64: 
                     65: int
                     66: procgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
                     67: {
                     68:        Qid qid;
                     69:        Proc *p;
                     70:        char buf[NAMELEN];
                     71:        ulong pid, path, perm, len;
                     72: 
                     73:        USED(ntab);
                     74:        if(c->qid.path == CHDIR){
                     75:                if(s >= conf.nproc)
                     76:                        return -1;
                     77:                p = proctab(s);
                     78:                pid = p->pid;
                     79:                if(pid == 0)
                     80:                        return 0;
                     81:                sprint(buf, "%d", pid);
                     82:                qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid};
                     83:                devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp);
                     84:                return 1;
                     85:        }
                     86:        if(s >= NPROC)
                     87:                return -1;
                     88:        if(tab)
                     89:                panic("procgen");
                     90: 
                     91:        tab = &procdir[s];
                     92:        path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1));    /* slot component */
                     93: 
                     94:        p = proctab(SLOT(c->qid));
                     95:        perm = tab->perm;
                     96:        if(perm == 0)
                     97:                perm = p->procmode;
                     98: 
                     99:        len = tab->length;
                    100:        if(QID(c->qid) == Qwait)
                    101:                len = p->nwait * sizeof(Waitmsg);
                    102: 
                    103:        qid = (Qid){path|tab->qid.path, c->qid.vers};
                    104:        devdir(c, qid, tab->name, len, p->user, perm, dp);
                    105:        return 1;
                    106: }
                    107: 
                    108: void
                    109: procinit(void)
                    110: {
                    111:        if(conf.nproc >= (1<<(16-QSHIFT))-1)
                    112:                print("warning: too many procs for devproc\n");
                    113: }
                    114: 
                    115: void
                    116: procreset(void)
                    117: {
                    118: }
                    119: 
                    120: Chan*
                    121: procattach(char *spec)
                    122: {
                    123:        return devattach('p', spec);
                    124: }
                    125: 
                    126: Chan*
                    127: procclone(Chan *c, Chan *nc)
                    128: {
                    129:        return devclone(c, nc);
                    130: }
                    131: 
                    132: int
                    133: procwalk(Chan *c, char *name)
                    134: {
                    135:        if(strcmp(name, "..") == 0) {
                    136:                c->qid.path = Qdir|CHDIR;
                    137:                return 1;
                    138:        }
                    139: 
                    140:        return devwalk(c, name, 0, 0, procgen);
                    141: }
                    142: 
                    143: void
                    144: procstat(Chan *c, char *db)
                    145: {
                    146:        devstat(c, db, 0, 0, procgen);
                    147: }
                    148: 
                    149: Chan *
                    150: procopen(Chan *c, int omode)
                    151: {
                    152:        Proc *p;
                    153:        Pgrp *pg;
                    154:        Chan *tc;
                    155: 
                    156:        if(c->qid.path & CHDIR)
                    157:                return devopen(c, omode, 0, 0, procgen);
                    158: 
                    159:        p = proctab(SLOT(c->qid));
                    160:        pg = p->pgrp;
                    161:        if(p->pid != PID(c->qid))
                    162:                error(Eprocdied);
                    163: 
                    164:        omode = openmode(omode);
                    165: 
                    166:        switch(QID(c->qid)){
                    167:        case Qtext:
                    168:                tc = proctext(c, p);
                    169:                tc->offset = 0;
                    170:                return tc;
                    171: 
                    172:        case Qctl:
                    173:        case Qnote:
                    174:        case Qnoteid:
                    175:        case Qmem:
                    176:        case Qsegment:
                    177:        case Qproc:
                    178:        case Qstatus:
                    179:        case Qwait:
                    180:                break;
                    181: 
                    182:        case Qnotepg:
                    183:                if(omode!=OWRITE || pg->pgrpid == 1)
                    184:                        error(Eperm);
                    185:                c->pgrpid.path = pg->pgrpid+1;
                    186:                c->pgrpid.vers = p->noteid;
                    187:                break;
                    188: 
                    189:        default:
                    190:                pprint("procopen %lux\n", c->qid);
                    191:                error(Egreg);
                    192:        }
                    193: 
                    194:        /* Affix pid to qid */
                    195:        if(p->state != Dead)
                    196:                c->qid.vers = p->pid;
                    197: 
                    198:        return devopen(c, omode, 0, 0, procgen);
                    199: }
                    200: 
                    201: void
                    202: proccreate(Chan *c, char *name, int omode, ulong perm)
                    203: {
                    204:        USED(c, name, omode, perm);
                    205:        error(Eperm);
                    206: }
                    207: 
                    208: void
                    209: procremove(Chan *c)
                    210: {
                    211:        USED(c);
                    212:        error(Eperm);
                    213: }
                    214: 
                    215: void
                    216: procwstat(Chan *c, char *db)
                    217: {
                    218:        Proc *p;
                    219:        Dir d;
                    220: 
                    221:        if(c->qid.path&CHDIR)
                    222:                error(Eperm);
                    223: 
                    224:        convM2D(db, &d);
                    225:        p = proctab(SLOT(c->qid));
                    226:        if(p->pid != PID(c->qid))
                    227:                error(Eprocdied);
                    228: 
                    229:        if(strcmp(u->p->user, p->user) != 0 && strcmp(u->p->user, eve) != 0)
                    230:                error(Eperm);
                    231: 
                    232:        p->procmode = d.mode&0777;
                    233: }
                    234: 
                    235: void
                    236: procclose(Chan * c)
                    237: {
                    238:        USED(c);
                    239: }
                    240: 
                    241: long
                    242: procread(Chan *c, void *va, long n, ulong offset)
                    243: {
                    244:        Proc *p;
                    245:        Page *pg;
                    246:        KMap *k;
                    247:        Segment *s;
                    248:        int i, j;
                    249:        long l;
                    250:        User *up;
                    251:        Segment *sg;
                    252:        Waitq *wq;
                    253:        char statbuf[NSEG*32];
                    254:        char *a = va, *b, *sps;
                    255: 
                    256:        if(c->qid.path & CHDIR)
                    257:                return devdirread(c, a, n, 0, 0, procgen);
                    258: 
                    259:        p = proctab(SLOT(c->qid));
                    260:        if(p->pid != PID(c->qid))
                    261:                error(Eprocdied);
                    262: 
                    263:        switch(QID(c->qid)){
                    264:        case Qmem:
                    265:                /* ugly math: USERADDR+BY2PG may be == 0 */
                    266:                if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) {
                    267:                        if(offset+n >= USERADDR+BY2PG-1)
                    268:                                n = USERADDR+BY2PG - offset;
                    269:                        pg = p->upage;
                    270:                        if(pg==0 || p->pid!=PID(c->qid))
                    271:                                error(Eprocdied);
                    272:                        k = kmap(pg);
                    273:                        b = (char*)VA(k);
                    274:                        memmove(a, b+(offset-USERADDR), n);
                    275:                        kunmap(k);
                    276:                        return n;
                    277:                }
                    278: 
                    279:                if(offset >= KZERO) {
                    280:                        /* Protect crypt key memory */
                    281:                        if(offset < palloc.cmemtop && offset+n > palloc.cmembase)
                    282:                                error(Eperm);
                    283: 
                    284:                        /* validate physical kernel addresses */
                    285:                        if(offset < (ulong)end) {
                    286:                                if(offset+n > (ulong)end)
                    287:                                        n = (ulong)end - offset;
                    288:                                memmove(a, (char*)offset, n);
                    289:                                return n;
                    290:                        }
                    291:                        if(offset >= conf.base0 && offset < conf.npage0){
                    292:                                if(offset+n > conf.npage0)
                    293:                                        n = conf.npage0 - offset;
                    294:                                memmove(a, (char*)offset, n);
                    295:                                return n;
                    296:                        }
                    297:                        if(offset >= conf.base1 && offset < conf.npage1){
                    298:                                if(offset+n > conf.npage1)
                    299:                                        n = conf.npage1 - offset;
                    300:                                memmove(a, (char*)offset, n);
                    301:                                return n;
                    302:                        }
                    303:                }
                    304: 
                    305:                return procctlmemio(p, offset, n, va, 1);
                    306: 
                    307:        case Qnote:
                    308:                qlock(&p->debug);
                    309:                if(waserror()){
                    310:                        qunlock(&p->debug);
                    311:                        nexterror();
                    312:                }
                    313:                if(p->pid != PID(c->qid))
                    314:                        error(Eprocdied);
                    315:                k = kmap(p->upage);
                    316:                up = (User*)VA(k);
                    317:                if(up->p != p){
                    318:                        kunmap(k);
                    319:                        pprint("note read u/p mismatch");
                    320:                        error(Egreg);
                    321:                }
                    322:                if(n < ERRLEN)
                    323:                        error(Etoosmall);
                    324:                if(up->nnote == 0)
                    325:                        n = 0;
                    326:                else{
                    327:                        memmove(va, up->note[0].msg, ERRLEN);
                    328:                        up->nnote--;
                    329:                        memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
                    330:                        n = ERRLEN;
                    331:                }
                    332:                if(up->nnote == 0)
                    333:                        p->notepending = 0;
                    334:                kunmap(k);
                    335:                poperror();
                    336:                qunlock(&p->debug);
                    337:                return n;
                    338: 
                    339:        case Qproc:
                    340:                if(offset >= sizeof(Proc))
                    341:                        return 0;
                    342:                if(offset+n > sizeof(Proc))
                    343:                        n = sizeof(Proc) - offset;
                    344:                memmove(a, ((char*)p)+offset, n);
                    345:                return n;
                    346: 
                    347:        case Qstatus:
                    348:                if(offset >= STATSIZE)
                    349:                        return 0;
                    350:                if(offset+n > STATSIZE)
                    351:                        n = STATSIZE - offset;
                    352: 
                    353:                sps = p->psstate;
                    354:                if(sps == 0)
                    355:                        sps = statename[p->state];
                    356:                memset(statbuf, ' ', sizeof statbuf);
                    357:                memmove(statbuf+0*NAMELEN, p->text, strlen(p->text));
                    358:                memmove(statbuf+1*NAMELEN, p->user, strlen(p->user));
                    359:                memmove(statbuf+2*NAMELEN, sps, strlen(sps));
                    360:                j = 2*NAMELEN + 12;
                    361: 
                    362:                for(i = 0; i < 6; i++) {
                    363:                        l = p->time[i];
                    364:                        if(i == TReal)
                    365:                                l = MACHP(0)->ticks - l;
                    366:                        l = TK2MS(l);
                    367:                        readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
                    368:                }
                    369:                /* ignore stack, which is mostly non-existent */
                    370:                l = 0;
                    371:                for(i=1; i<NSEG; i++){
                    372:                        s = p->seg[i];
                    373:                        if(s)
                    374:                                l += s->top - s->base;
                    375:                }
                    376:                readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
                    377:                memmove(a, statbuf+offset, n);
                    378:                return n;
                    379: 
                    380:        case Qsegment:
                    381:                j = 0;
                    382:                for(i = 0; i < NSEG; i++)
                    383:                        if(sg = p->seg[i])
                    384:                                j += sprint(&statbuf[j], "%-6s %c %.8lux %.8lux %4d\n",
                    385:                                sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ',
                    386:                                sg->base, sg->top, sg->ref);
                    387:                if(offset >= j)
                    388:                        return 0;
                    389:                if(offset+n > j)
                    390:                        n = j-offset;
                    391:                if(n == 0 && offset == 0)
                    392:                        exhausted("segments");
                    393:                memmove(a, &statbuf[offset], n);
                    394:                return n;
                    395: 
                    396:        case Qwait:
                    397:                if(n < sizeof(Waitmsg))
                    398:                        error(Etoosmall);
                    399: 
                    400:                if(!canqlock(&p->qwaitr))
                    401:                        error(Einuse);
                    402: 
                    403:                if(waserror()) {
                    404:                        qunlock(&p->qwaitr);
                    405:                        nexterror();
                    406:                }
                    407: 
                    408:                lock(&p->exl);
                    409:                if(u->p == p && p->nchild == 0 && p->waitq == 0) {
                    410:                        unlock(&p->exl);
                    411:                        error(Enochild);
                    412:                }
                    413:                while(p->waitq == 0) {
                    414:                        unlock(&p->exl);
                    415:                        sleep(&p->waitr, haswaitq, p);
                    416:                        lock(&p->exl);
                    417:                }
                    418:                wq = p->waitq;
                    419:                p->waitq = wq->next;
                    420:                p->nwait--;
                    421:                unlock(&p->exl);
                    422: 
                    423:                qunlock(&p->qwaitr);
                    424:                poperror();
                    425:                memmove(a, &wq->w, sizeof(Waitmsg));
                    426:                free(wq);
                    427:                return sizeof(Waitmsg);
                    428:        case Qnoteid:
                    429:                return readnum(offset, va, n, p->noteid, NUMSIZE);
                    430:        }
                    431:        error(Egreg);
                    432:        return 0;               /* not reached */
                    433: }
                    434: 
                    435: 
                    436: long
                    437: procwrite(Chan *c, void *va, long n, ulong offset)
                    438: {
                    439:        int id;
                    440:        User *up;
                    441:        KMap *k;
                    442:        Ureg *ur;
                    443:        User *pxu;
                    444:        Page *pg;
                    445:        ulong hi;
                    446:        char *a, *b;
                    447:        char buf[ERRLEN];
                    448:        Proc *p, *t, *et;
                    449: 
                    450:        if(c->qid.path & CHDIR)
                    451:                error(Eisdir);
                    452: 
                    453:        a = va;
                    454:        p = proctab(SLOT(c->qid));
                    455: 
                    456:        /* Use the remembered noteid in the channel
                    457:         * rather than the process pgrpid
                    458:         */
                    459:        if(QID(c->qid) == Qnotepg) {
                    460:                pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
                    461:                return n;
                    462:        }
                    463: 
                    464:        qlock(&p->debug);
                    465:        if(waserror()){
                    466:                qunlock(&p->debug);
                    467:                nexterror();
                    468:        }
                    469:        if(p->pid != PID(c->qid))
                    470:                error(Eprocdied);
                    471: 
                    472:        switch(QID(c->qid)){
                    473:        case Qmem:
                    474:                if(p->state != Stopped)
                    475:                        error(Ebadctl);
                    476: 
                    477:                if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) {
                    478:                        pg = p->upage;
                    479:                        if(pg==0 || p->pid!=PID(c->qid))
                    480:                                error(Eprocdied);
                    481:                        k = kmap(pg);
                    482:                        b = (char*)VA(k);
                    483:                        pxu = (User*)b;
                    484:                        hi = offset+n;
                    485:                        /* Check for floating point registers */
                    486:                        if(offset >= (ulong)&u->fpsave &&
                    487:                           hi <= (ulong)&u->fpsave+sizeof(FPsave)){
                    488:                                memmove(b+(offset-USERADDR), a, n);
                    489:                                break;
                    490:                        }
                    491:                        /* Check user register set for process at kernel entry */
                    492:                        ur = pxu->dbgreg;
                    493:                        if(offset < (ulong)ur || hi > (ulong)ur+sizeof(Ureg)) {
                    494:                                kunmap(k);
                    495:                                error(Ebadarg);
                    496:                        }
                    497:                        ur = (Ureg*)(b+((ulong)ur-USERADDR));
                    498:                        setregisters(ur, b+(offset-USERADDR), a, n);
                    499:                        kunmap(k);
                    500:                }
                    501:                else    /* Try user memory segments */
                    502:                        n = procctlmemio(p, offset, n, va, 0);
                    503:                break;
                    504: 
                    505:        case Qctl:
                    506:                procctlreq(p, va, n);
                    507:                break;
                    508: 
                    509:        case Qnote:
                    510:                if(p->kp)
                    511:                        error(Eperm);
                    512:                k = kmap(p->upage);
                    513:                up = (User*)VA(k);
                    514:                if(up->p != p){
                    515:                        kunmap(k);
                    516:                        pprint("note write u/p mismatch");
                    517:                        error(Egreg);
                    518:                }
                    519:                kunmap(k);
                    520:                if(n >= ERRLEN-1)
                    521:                        error(Etoobig);
                    522:                memmove(buf, va, n);
                    523:                buf[n] = 0;
                    524:                if(!postnote(p, 0, buf, NUser))
                    525:                        error("note not posted");
                    526:                break;
                    527:        case Qnoteid:
                    528:                id = atoi(a);
                    529:                if(id == p->pid) {
                    530:                        p->noteid = id;
                    531:                        break;
                    532:                }
                    533:                t = proctab(0);
                    534:                for(et = t+conf.nproc; t < et; t++) {
                    535:                        if(id == t->noteid) {
                    536:                                if(strcmp(p->user, t->user) != 0)
                    537:                                        error(Eperm);
                    538:                                p->noteid = id;
                    539:                                break;
                    540:                        }
                    541:                }
                    542:                if(p->noteid != id)
                    543:                        error(Ebadarg);
                    544:                break;
                    545:        default:
                    546:                pprint("unknown qid in procwrite\n");
                    547:                error(Egreg);
                    548:        }
                    549:        poperror();
                    550:        qunlock(&p->debug);
                    551:        return n;
                    552: }
                    553: 
                    554: Chan *
                    555: proctext(Chan *c, Proc *p)
                    556: {
                    557:        Chan *tc;
                    558:        Image *i;
                    559:        Segment *s;
                    560: 
                    561:        s = p->seg[TSEG];
                    562:        if(s == 0)
                    563:                error(Enonexist);
                    564:        if(p->state==Dead)
                    565:                error(Eprocdied);
                    566: 
                    567:        lock(s);
                    568:        i = s->image;
                    569:        if(i == 0) {
                    570:                unlock(s);
                    571:                error(Eprocdied);
                    572:        }
                    573:        unlock(s);
                    574: 
                    575:        lock(i);
                    576:        if(waserror()) {
                    577:                unlock(i);
                    578:                nexterror();
                    579:        }
                    580: 
                    581:        tc = i->c;
                    582:        if(tc == 0)
                    583:                error(Eprocdied);
                    584: 
                    585:        if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
                    586:                close(tc);
                    587:                error(Eprocdied);
                    588:        }
                    589: 
                    590:        if(p->pid != PID(c->qid))
                    591:                error(Eprocdied);
                    592: 
                    593:        unlock(i);
                    594:        poperror();
                    595: 
                    596:        return tc;
                    597: }
                    598: 
                    599: void
                    600: procstopwait(Proc *p, int ctl)
                    601: {
                    602:        int pid;
                    603: 
                    604:        if(p->pdbg)
                    605:                error(Einuse);
                    606:        if(procstopped(p))
                    607:                return;
                    608: 
                    609:        if(ctl != 0)
                    610:                p->procctl = ctl;
                    611:        p->pdbg = u->p;
                    612:        pid = p->pid;
                    613:        qunlock(&p->debug);
                    614:        u->p->psstate = "Stopwait";
                    615:        if(waserror()) {
                    616:                p->pdbg = 0;
                    617:                qlock(&p->debug);
                    618:                nexterror();
                    619:        }
                    620:        sleep(&u->p->sleep, procstopped, p);
                    621:        poperror();
                    622:        qlock(&p->debug);
                    623:        if(p->pid != pid)
                    624:                error(Eprocdied);
                    625: }
                    626: 
                    627: void
                    628: procctlreq(Proc *p, char *va, int n)
                    629: {
                    630:        int i;
                    631:        char buf[NAMELEN+1];
                    632: 
                    633:        if(n > NAMELEN)
                    634:                n = NAMELEN;
                    635:        strncpy(buf, va, n);
                    636:        buf[NAMELEN] = '\0';
                    637: 
                    638:        if(strncmp(buf, "stop", 4) == 0)
                    639:                procstopwait(p, Proc_stopme);
                    640:        else if(strncmp(buf, "kill", 4) == 0) {
                    641:                switch(p->state) {
                    642:                case Broken:
                    643:                        unbreak(p);
                    644:                        break;
                    645:                case Stopped:
                    646:                        postnote(p, 0, "sys: killed", NExit);
                    647:                        p->procctl = Proc_exitme;
                    648:                        ready(p);
                    649:                        break;
                    650:                default:
                    651:                        postnote(p, 0, "sys: killed", NExit);
                    652:                        p->procctl = Proc_exitme;
                    653:                }
                    654:        }
                    655:        else if(strncmp(buf, "hang", 4) == 0)
                    656:                p->hang = 1;
                    657:        else if(strncmp(buf, "nohang", 6) == 0)
                    658:                p->hang = 0;
                    659:        else if(strncmp(buf, "waitstop", 8) == 0)
                    660:                procstopwait(p, 0);
                    661:        else if(strncmp(buf, "startstop", 9) == 0) {
                    662:                if(p->state != Stopped)
                    663:                        error(Ebadctl);
                    664:                p->procctl = Proc_traceme;
                    665:                ready(p);
                    666:                procstopwait(p, Proc_traceme);
                    667:        }
                    668:        else if(strncmp(buf, "start", 5) == 0) {
                    669:                if(p->state != Stopped)
                    670:                        error(Ebadctl);
                    671:                ready(p);
                    672:        }
                    673:        else if(strncmp(buf, "pri", 3) == 0){
                    674:                if(n < 4)
                    675:                        error(Ebadctl);
                    676:                i = atoi(buf+4);
                    677:                if(i < 0)
                    678:                        i = 0;
                    679:                if(i >= Nrq)
                    680:                        i = Nrq - 1;
                    681:                if(i < p->basepri && !iseve())
                    682:                        error(Eperm);
                    683:                p->basepri = i;
                    684:        }
                    685:        else
                    686:                error(Ebadctl);
                    687: }
                    688: 
                    689: int
                    690: procstopped(void *a)
                    691: {
                    692:        Proc *p = a;
                    693:        return p->state == Stopped;
                    694: }
                    695: 
                    696: int
                    697: procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
                    698: {
                    699:        KMap *k;
                    700:        Pte *pte;
                    701:        Page *pg;
                    702:        Segment *s;
                    703:        ulong soff, l;
                    704:        char *a = va, *b;
                    705: 
                    706:        for(;;) {
                    707:                s = seg(p, offset, 1);
                    708:                if(s == 0)
                    709:                        error(Ebadarg);
                    710: 
                    711:                if(offset+n >= s->top)
                    712:                        n = s->top-offset;
                    713: 
                    714:                if(read == 0 && (s->type&SG_TYPE) == SG_TEXT)
                    715:                        s = txt2data(p, s);
                    716: 
                    717:                s->steal++;
                    718:                soff = offset-s->base;
                    719:                if(waserror()) {
                    720:                        s->steal--;
                    721:                        nexterror();
                    722:                }
                    723:                if(fixfault(s, offset, read, 0) == 0)
                    724:                        break;
                    725:                poperror();
                    726:                s->steal--;
                    727:        }
                    728:        poperror();
                    729:        pte = s->map[soff/PTEMAPMEM];
                    730:        if(pte == 0)
                    731:                panic("procctlmemio"); 
                    732:        pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
                    733:        if(pagedout(pg))
                    734:                panic("procctlmemio1"); 
                    735: 
                    736:        l = BY2PG - (offset&(BY2PG-1));
                    737:        if(n > l)
                    738:                n = l;
                    739: 
                    740:        k = kmap(pg);
                    741:        b = (char*)VA(k);
                    742:        if(read == 1)
                    743:                memmove(a, b+(offset&(BY2PG-1)), n);
                    744:        else
                    745:                memmove(b+(offset&(BY2PG-1)), a, n);
                    746: 
                    747:        kunmap(k);
                    748: 
                    749:        s->steal--;
                    750:        qunlock(&s->lk);
                    751: 
                    752:        if(read == 0)
                    753:                p->newtlb = 1;
                    754: 
                    755:        return n;
                    756: }
                    757: 
                    758: Segment*
                    759: txt2data(Proc *p, Segment *s)
                    760: {
                    761:        int i;
                    762:        Segment *ps;
                    763: 
                    764:        ps = newseg(SG_DATA, s->base, s->size);
                    765:        ps->image = s->image;
                    766:        incref(ps->image);
                    767:        ps->fstart = s->fstart;
                    768:        ps->flen = s->flen;
                    769:        ps->flushme = 1;
                    770: 
                    771:        for(i = 0; i < NSEG; i++)
                    772:                if(p->seg[i] == s)
                    773:                        break;
                    774:        if(p->seg[i] != s)
                    775:                panic("segment gone");
                    776: 
                    777:        qunlock(&s->lk);
                    778:        putseg(s);
                    779:        qlock(&ps->lk);
                    780:        p->seg[i] = ps;
                    781: 
                    782:        return ps;
                    783: }
                    784: 
                    785: Segment*
                    786: data2txt(Segment *s)
                    787: {
                    788:        Segment *ps;
                    789: 
                    790:        ps = newseg(SG_TEXT, s->base, s->size);
                    791:        ps->image = s->image;
                    792:        incref(ps->image);
                    793:        ps->fstart = s->fstart;
                    794:        ps->flen = s->flen;
                    795:        ps->flushme = 1;
                    796: 
                    797:        return ps;
                    798: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.