13e12c5d1SDavid du Colombier #include "u.h" 23e12c5d1SDavid du Colombier #include "../port/lib.h" 33e12c5d1SDavid du Colombier #include "mem.h" 43e12c5d1SDavid du Colombier #include "dat.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier #include "../port/error.h" 73e12c5d1SDavid du Colombier #include "ureg.h" 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier #include "devtab.h" 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier enum{ 123e12c5d1SDavid du Colombier Qdir, 133e12c5d1SDavid du Colombier Qctl, 143e12c5d1SDavid du Colombier Qmem, 153e12c5d1SDavid du Colombier Qnote, 16*219b2ee8SDavid du Colombier Qnoteid, 173e12c5d1SDavid du Colombier Qnotepg, 183e12c5d1SDavid du Colombier Qproc, 193e12c5d1SDavid du Colombier Qsegment, 203e12c5d1SDavid du Colombier Qstatus, 213e12c5d1SDavid du Colombier Qtext, 22*219b2ee8SDavid du Colombier Qwait, 233e12c5d1SDavid du Colombier }; 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier #define STATSIZE (2*NAMELEN+12+7*12) 263e12c5d1SDavid du Colombier Dirtab procdir[] = 273e12c5d1SDavid du Colombier { 283e12c5d1SDavid du Colombier "ctl", {Qctl}, 0, 0000, 293e12c5d1SDavid du Colombier "mem", {Qmem}, 0, 0000, 303e12c5d1SDavid du Colombier "note", {Qnote}, 0, 0000, 31*219b2ee8SDavid du Colombier "noteid", {Qnoteid}, 0, 0666, 323e12c5d1SDavid du Colombier "notepg", {Qnotepg}, 0, 0000, 33*219b2ee8SDavid du Colombier "proc", {Qproc}, sizeof(Proc), 0444, 343e12c5d1SDavid du Colombier "segment", {Qsegment}, 0, 0444, 353e12c5d1SDavid du Colombier "status", {Qstatus}, STATSIZE, 0444, 363e12c5d1SDavid du Colombier "text", {Qtext}, 0, 0000, 37*219b2ee8SDavid du Colombier "wait", {Qwait}, 0, 0400, 383e12c5d1SDavid du Colombier }; 393e12c5d1SDavid du Colombier 403e12c5d1SDavid du Colombier /* Segment type from portdat.h */ 413e12c5d1SDavid du Colombier char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata" }; 423e12c5d1SDavid du Colombier 433e12c5d1SDavid du Colombier /* 443e12c5d1SDavid du Colombier * Qids are, in path: 453e12c5d1SDavid du Colombier * 4 bits of file type (qids above) 463e12c5d1SDavid du Colombier * 23 bits of process slot number + 1 473e12c5d1SDavid du Colombier * in vers, 483e12c5d1SDavid du Colombier * 32 bits of pid, for consistency checking 493e12c5d1SDavid du Colombier * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid. 503e12c5d1SDavid du Colombier */ 513e12c5d1SDavid du Colombier #define NPROC (sizeof procdir/sizeof(Dirtab)) 523e12c5d1SDavid du Colombier #define QSHIFT 4 /* location in qid of proc slot # */ 533e12c5d1SDavid du Colombier 543e12c5d1SDavid du Colombier #define QID(q) (((q).path&0x0000000F)>>0) 553e12c5d1SDavid du Colombier #define SLOT(q) ((((q).path&0x07FFFFFF0)>>QSHIFT)-1) 563e12c5d1SDavid du Colombier #define PID(q) ((q).vers) 573e12c5d1SDavid du Colombier #define NOTEID(q) ((q).vers) 583e12c5d1SDavid du Colombier 593e12c5d1SDavid du Colombier void procctlreq(Proc*, char*, int); 603e12c5d1SDavid du Colombier int procctlmemio(Proc*, ulong, int, void*, int); 613e12c5d1SDavid du Colombier Chan* proctext(Chan*, Proc*); 623e12c5d1SDavid du Colombier Segment* txt2data(Proc*, Segment*); 633e12c5d1SDavid du Colombier int procstopped(void*); 643e12c5d1SDavid du Colombier 653e12c5d1SDavid du Colombier int 663e12c5d1SDavid du Colombier procgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 673e12c5d1SDavid du Colombier { 683e12c5d1SDavid du Colombier Qid qid; 693e12c5d1SDavid du Colombier Proc *p; 703e12c5d1SDavid du Colombier char buf[NAMELEN]; 71*219b2ee8SDavid du Colombier ulong pid, path, perm, len; 723e12c5d1SDavid du Colombier 733e12c5d1SDavid du Colombier USED(ntab); 743e12c5d1SDavid du Colombier if(c->qid.path == CHDIR){ 753e12c5d1SDavid du Colombier if(s >= conf.nproc) 763e12c5d1SDavid du Colombier return -1; 773e12c5d1SDavid du Colombier p = proctab(s); 783e12c5d1SDavid du Colombier pid = p->pid; 793e12c5d1SDavid du Colombier if(pid == 0) 803e12c5d1SDavid du Colombier return 0; 813e12c5d1SDavid du Colombier sprint(buf, "%d", pid); 823e12c5d1SDavid du Colombier qid = (Qid){CHDIR|((s+1)<<QSHIFT), pid}; 833e12c5d1SDavid du Colombier devdir(c, qid, buf, 0, p->user, CHDIR|0555, dp); 843e12c5d1SDavid du Colombier return 1; 853e12c5d1SDavid du Colombier } 863e12c5d1SDavid du Colombier if(s >= NPROC) 873e12c5d1SDavid du Colombier return -1; 883e12c5d1SDavid du Colombier if(tab) 893e12c5d1SDavid du Colombier panic("procgen"); 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier tab = &procdir[s]; 923e12c5d1SDavid du Colombier path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1)); /* slot component */ 933e12c5d1SDavid du Colombier 943e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid)); 953e12c5d1SDavid du Colombier perm = tab->perm; 963e12c5d1SDavid du Colombier if(perm == 0) 973e12c5d1SDavid du Colombier perm = p->procmode; 983e12c5d1SDavid du Colombier 99*219b2ee8SDavid du Colombier len = tab->length; 100*219b2ee8SDavid du Colombier if(QID(c->qid) == Qwait) 101*219b2ee8SDavid du Colombier len = p->nwait * sizeof(Waitmsg); 102*219b2ee8SDavid du Colombier 1033e12c5d1SDavid du Colombier qid = (Qid){path|tab->qid.path, c->qid.vers}; 104*219b2ee8SDavid du Colombier devdir(c, qid, tab->name, len, p->user, perm, dp); 1053e12c5d1SDavid du Colombier return 1; 1063e12c5d1SDavid du Colombier } 1073e12c5d1SDavid du Colombier 1083e12c5d1SDavid du Colombier void 1093e12c5d1SDavid du Colombier procinit(void) 1103e12c5d1SDavid du Colombier { 1113e12c5d1SDavid du Colombier if(conf.nproc >= (1<<(16-QSHIFT))-1) 1123e12c5d1SDavid du Colombier print("warning: too many procs for devproc\n"); 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier void 1163e12c5d1SDavid du Colombier procreset(void) 1173e12c5d1SDavid du Colombier { 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier Chan* 1213e12c5d1SDavid du Colombier procattach(char *spec) 1223e12c5d1SDavid du Colombier { 1233e12c5d1SDavid du Colombier return devattach('p', spec); 1243e12c5d1SDavid du Colombier } 1253e12c5d1SDavid du Colombier 1263e12c5d1SDavid du Colombier Chan* 1273e12c5d1SDavid du Colombier procclone(Chan *c, Chan *nc) 1283e12c5d1SDavid du Colombier { 1293e12c5d1SDavid du Colombier return devclone(c, nc); 1303e12c5d1SDavid du Colombier } 1313e12c5d1SDavid du Colombier 1323e12c5d1SDavid du Colombier int 1333e12c5d1SDavid du Colombier procwalk(Chan *c, char *name) 1343e12c5d1SDavid du Colombier { 1353e12c5d1SDavid du Colombier if(strcmp(name, "..") == 0) { 1363e12c5d1SDavid du Colombier c->qid.path = Qdir|CHDIR; 1373e12c5d1SDavid du Colombier return 1; 1383e12c5d1SDavid du Colombier } 1393e12c5d1SDavid du Colombier 1403e12c5d1SDavid du Colombier return devwalk(c, name, 0, 0, procgen); 1413e12c5d1SDavid du Colombier } 1423e12c5d1SDavid du Colombier 1433e12c5d1SDavid du Colombier void 1443e12c5d1SDavid du Colombier procstat(Chan *c, char *db) 1453e12c5d1SDavid du Colombier { 1463e12c5d1SDavid du Colombier devstat(c, db, 0, 0, procgen); 1473e12c5d1SDavid du Colombier } 1483e12c5d1SDavid du Colombier 1493e12c5d1SDavid du Colombier Chan * 1503e12c5d1SDavid du Colombier procopen(Chan *c, int omode) 1513e12c5d1SDavid du Colombier { 1523e12c5d1SDavid du Colombier Proc *p; 1533e12c5d1SDavid du Colombier Pgrp *pg; 1543e12c5d1SDavid du Colombier Chan *tc; 1553e12c5d1SDavid du Colombier 1563e12c5d1SDavid du Colombier if(c->qid.path & CHDIR) 1573e12c5d1SDavid du Colombier return devopen(c, omode, 0, 0, procgen); 1583e12c5d1SDavid du Colombier 1593e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid)); 1603e12c5d1SDavid du Colombier pg = p->pgrp; 1613e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 1623e12c5d1SDavid du Colombier error(Eprocdied); 1633e12c5d1SDavid du Colombier 1643e12c5d1SDavid du Colombier omode = openmode(omode); 1653e12c5d1SDavid du Colombier 1663e12c5d1SDavid du Colombier switch(QID(c->qid)){ 1673e12c5d1SDavid du Colombier case Qtext: 1683e12c5d1SDavid du Colombier tc = proctext(c, p); 1693e12c5d1SDavid du Colombier tc->offset = 0; 1703e12c5d1SDavid du Colombier return tc; 1713e12c5d1SDavid du Colombier 1723e12c5d1SDavid du Colombier case Qctl: 1733e12c5d1SDavid du Colombier case Qnote: 174*219b2ee8SDavid du Colombier case Qnoteid: 1753e12c5d1SDavid du Colombier case Qmem: 1763e12c5d1SDavid du Colombier case Qsegment: 1773e12c5d1SDavid du Colombier case Qproc: 1783e12c5d1SDavid du Colombier case Qstatus: 179*219b2ee8SDavid du Colombier case Qwait: 1803e12c5d1SDavid du Colombier break; 1813e12c5d1SDavid du Colombier 1823e12c5d1SDavid du Colombier case Qnotepg: 1833e12c5d1SDavid du Colombier if(omode!=OWRITE || pg->pgrpid == 1) 1843e12c5d1SDavid du Colombier error(Eperm); 1853e12c5d1SDavid du Colombier c->pgrpid.path = pg->pgrpid+1; 1863e12c5d1SDavid du Colombier c->pgrpid.vers = p->noteid; 1873e12c5d1SDavid du Colombier break; 1883e12c5d1SDavid du Colombier 1893e12c5d1SDavid du Colombier default: 1903e12c5d1SDavid du Colombier pprint("procopen %lux\n", c->qid); 1913e12c5d1SDavid du Colombier error(Egreg); 1923e12c5d1SDavid du Colombier } 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier /* Affix pid to qid */ 1953e12c5d1SDavid du Colombier if(p->state != Dead) 1963e12c5d1SDavid du Colombier c->qid.vers = p->pid; 1973e12c5d1SDavid du Colombier 1983e12c5d1SDavid du Colombier return devopen(c, omode, 0, 0, procgen); 1993e12c5d1SDavid du Colombier } 2003e12c5d1SDavid du Colombier 2013e12c5d1SDavid du Colombier void 2023e12c5d1SDavid du Colombier proccreate(Chan *c, char *name, int omode, ulong perm) 2033e12c5d1SDavid du Colombier { 2043e12c5d1SDavid du Colombier USED(c, name, omode, perm); 2053e12c5d1SDavid du Colombier error(Eperm); 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier void 2093e12c5d1SDavid du Colombier procremove(Chan *c) 2103e12c5d1SDavid du Colombier { 2113e12c5d1SDavid du Colombier USED(c); 2123e12c5d1SDavid du Colombier error(Eperm); 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier void 2163e12c5d1SDavid du Colombier procwstat(Chan *c, char *db) 2173e12c5d1SDavid du Colombier { 2183e12c5d1SDavid du Colombier Proc *p; 2193e12c5d1SDavid du Colombier Dir d; 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier if(c->qid.path&CHDIR) 2223e12c5d1SDavid du Colombier error(Eperm); 2233e12c5d1SDavid du Colombier 2243e12c5d1SDavid du Colombier convM2D(db, &d); 2253e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid)); 2263e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 2273e12c5d1SDavid du Colombier error(Eprocdied); 2283e12c5d1SDavid du Colombier 2293e12c5d1SDavid du Colombier if(strcmp(u->p->user, p->user) != 0 && strcmp(u->p->user, eve) != 0) 2303e12c5d1SDavid du Colombier error(Eperm); 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier p->procmode = d.mode&0777; 2333e12c5d1SDavid du Colombier } 2343e12c5d1SDavid du Colombier 2353e12c5d1SDavid du Colombier void 2363e12c5d1SDavid du Colombier procclose(Chan * c) 2373e12c5d1SDavid du Colombier { 2383e12c5d1SDavid du Colombier USED(c); 2393e12c5d1SDavid du Colombier } 2403e12c5d1SDavid du Colombier 2413e12c5d1SDavid du Colombier long 2423e12c5d1SDavid du Colombier procread(Chan *c, void *va, long n, ulong offset) 2433e12c5d1SDavid du Colombier { 2443e12c5d1SDavid du Colombier Proc *p; 2453e12c5d1SDavid du Colombier Page *pg; 2463e12c5d1SDavid du Colombier KMap *k; 2473e12c5d1SDavid du Colombier Segment *s; 2483e12c5d1SDavid du Colombier int i, j; 2493e12c5d1SDavid du Colombier long l; 2503e12c5d1SDavid du Colombier User *up; 2513e12c5d1SDavid du Colombier Segment *sg; 252*219b2ee8SDavid du Colombier Waitq *wq; 253*219b2ee8SDavid du Colombier char statbuf[NSEG*32]; 254*219b2ee8SDavid du Colombier char *a = va, *b, *sps; 2553e12c5d1SDavid du Colombier 2563e12c5d1SDavid du Colombier if(c->qid.path & CHDIR) 2573e12c5d1SDavid du Colombier return devdirread(c, a, n, 0, 0, procgen); 2583e12c5d1SDavid du Colombier 2593e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid)); 2603e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 2613e12c5d1SDavid du Colombier error(Eprocdied); 2623e12c5d1SDavid du Colombier 2633e12c5d1SDavid du Colombier switch(QID(c->qid)){ 2643e12c5d1SDavid du Colombier case Qmem: 2653e12c5d1SDavid du Colombier /* ugly math: USERADDR+BY2PG may be == 0 */ 2663e12c5d1SDavid du Colombier if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) { 2673e12c5d1SDavid du Colombier if(offset+n >= USERADDR+BY2PG-1) 2683e12c5d1SDavid du Colombier n = USERADDR+BY2PG - offset; 2693e12c5d1SDavid du Colombier pg = p->upage; 2703e12c5d1SDavid du Colombier if(pg==0 || p->pid!=PID(c->qid)) 2713e12c5d1SDavid du Colombier error(Eprocdied); 2723e12c5d1SDavid du Colombier k = kmap(pg); 2733e12c5d1SDavid du Colombier b = (char*)VA(k); 2743e12c5d1SDavid du Colombier memmove(a, b+(offset-USERADDR), n); 2753e12c5d1SDavid du Colombier kunmap(k); 2763e12c5d1SDavid du Colombier return n; 2773e12c5d1SDavid du Colombier } 2783e12c5d1SDavid du Colombier 2793e12c5d1SDavid du Colombier if(offset >= KZERO) { 2803e12c5d1SDavid du Colombier /* Protect crypt key memory */ 281*219b2ee8SDavid du Colombier if(offset < palloc.cmemtop && offset+n > palloc.cmembase) 2823e12c5d1SDavid du Colombier error(Eperm); 2833e12c5d1SDavid du Colombier 2843e12c5d1SDavid du Colombier /* validate physical kernel addresses */ 2853e12c5d1SDavid du Colombier if(offset < (ulong)end) { 2863e12c5d1SDavid du Colombier if(offset+n > (ulong)end) 2873e12c5d1SDavid du Colombier n = (ulong)end - offset; 2883e12c5d1SDavid du Colombier memmove(a, (char*)offset, n); 2893e12c5d1SDavid du Colombier return n; 2903e12c5d1SDavid du Colombier } 2913e12c5d1SDavid du Colombier if(offset >= conf.base0 && offset < conf.npage0){ 2923e12c5d1SDavid du Colombier if(offset+n > conf.npage0) 2933e12c5d1SDavid du Colombier n = conf.npage0 - offset; 2943e12c5d1SDavid du Colombier memmove(a, (char*)offset, n); 2953e12c5d1SDavid du Colombier return n; 2963e12c5d1SDavid du Colombier } 2973e12c5d1SDavid du Colombier if(offset >= conf.base1 && offset < conf.npage1){ 2983e12c5d1SDavid du Colombier if(offset+n > conf.npage1) 2993e12c5d1SDavid du Colombier n = conf.npage1 - offset; 3003e12c5d1SDavid du Colombier memmove(a, (char*)offset, n); 3013e12c5d1SDavid du Colombier return n; 3023e12c5d1SDavid du Colombier } 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier 3053e12c5d1SDavid du Colombier return procctlmemio(p, offset, n, va, 1); 3063e12c5d1SDavid du Colombier 3073e12c5d1SDavid du Colombier case Qnote: 3083e12c5d1SDavid du Colombier qlock(&p->debug); 3093e12c5d1SDavid du Colombier if(waserror()){ 3103e12c5d1SDavid du Colombier qunlock(&p->debug); 3113e12c5d1SDavid du Colombier nexterror(); 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 3143e12c5d1SDavid du Colombier error(Eprocdied); 3153e12c5d1SDavid du Colombier k = kmap(p->upage); 3163e12c5d1SDavid du Colombier up = (User*)VA(k); 3173e12c5d1SDavid du Colombier if(up->p != p){ 3183e12c5d1SDavid du Colombier kunmap(k); 3193e12c5d1SDavid du Colombier pprint("note read u/p mismatch"); 3203e12c5d1SDavid du Colombier error(Egreg); 3213e12c5d1SDavid du Colombier } 3223e12c5d1SDavid du Colombier if(n < ERRLEN) 3233e12c5d1SDavid du Colombier error(Etoosmall); 3243e12c5d1SDavid du Colombier if(up->nnote == 0) 3253e12c5d1SDavid du Colombier n = 0; 3263e12c5d1SDavid du Colombier else{ 3273e12c5d1SDavid du Colombier memmove(va, up->note[0].msg, ERRLEN); 3283e12c5d1SDavid du Colombier up->nnote--; 3293e12c5d1SDavid du Colombier memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note)); 3303e12c5d1SDavid du Colombier n = ERRLEN; 3313e12c5d1SDavid du Colombier } 3323e12c5d1SDavid du Colombier if(up->nnote == 0) 3333e12c5d1SDavid du Colombier p->notepending = 0; 3343e12c5d1SDavid du Colombier kunmap(k); 3353e12c5d1SDavid du Colombier poperror(); 3363e12c5d1SDavid du Colombier qunlock(&p->debug); 3373e12c5d1SDavid du Colombier return n; 3383e12c5d1SDavid du Colombier 3393e12c5d1SDavid du Colombier case Qproc: 3403e12c5d1SDavid du Colombier if(offset >= sizeof(Proc)) 3413e12c5d1SDavid du Colombier return 0; 3423e12c5d1SDavid du Colombier if(offset+n > sizeof(Proc)) 3433e12c5d1SDavid du Colombier n = sizeof(Proc) - offset; 3443e12c5d1SDavid du Colombier memmove(a, ((char*)p)+offset, n); 3453e12c5d1SDavid du Colombier return n; 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier case Qstatus: 3483e12c5d1SDavid du Colombier if(offset >= STATSIZE) 3493e12c5d1SDavid du Colombier return 0; 3503e12c5d1SDavid du Colombier if(offset+n > STATSIZE) 3513e12c5d1SDavid du Colombier n = STATSIZE - offset; 3523e12c5d1SDavid du Colombier 3533e12c5d1SDavid du Colombier sps = p->psstate; 3543e12c5d1SDavid du Colombier if(sps == 0) 3553e12c5d1SDavid du Colombier sps = statename[p->state]; 356bd389b36SDavid du Colombier memset(statbuf, ' ', sizeof statbuf); 357bd389b36SDavid du Colombier memmove(statbuf+0*NAMELEN, p->text, strlen(p->text)); 358bd389b36SDavid du Colombier memmove(statbuf+1*NAMELEN, p->user, strlen(p->user)); 359bd389b36SDavid du Colombier memmove(statbuf+2*NAMELEN, sps, strlen(sps)); 360bd389b36SDavid du Colombier j = 2*NAMELEN + 12; 3613e12c5d1SDavid du Colombier 3623e12c5d1SDavid du Colombier for(i = 0; i < 6; i++) { 3633e12c5d1SDavid du Colombier l = p->time[i]; 3643e12c5d1SDavid du Colombier if(i == TReal) 3653e12c5d1SDavid du Colombier l = MACHP(0)->ticks - l; 3663e12c5d1SDavid du Colombier l = TK2MS(l); 3673e12c5d1SDavid du Colombier readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE); 3683e12c5d1SDavid du Colombier } 3693e12c5d1SDavid du Colombier /* ignore stack, which is mostly non-existent */ 3703e12c5d1SDavid du Colombier l = 0; 3713e12c5d1SDavid du Colombier for(i=1; i<NSEG; i++){ 3723e12c5d1SDavid du Colombier s = p->seg[i]; 3733e12c5d1SDavid du Colombier if(s) 3743e12c5d1SDavid du Colombier l += s->top - s->base; 3753e12c5d1SDavid du Colombier } 3763e12c5d1SDavid du Colombier readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE); 3773e12c5d1SDavid du Colombier memmove(a, statbuf+offset, n); 3783e12c5d1SDavid du Colombier return n; 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier case Qsegment: 3813e12c5d1SDavid du Colombier j = 0; 3823e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) 3833e12c5d1SDavid du Colombier if(sg = p->seg[i]) 3843e12c5d1SDavid du Colombier j += sprint(&statbuf[j], "%-6s %c %.8lux %.8lux %4d\n", 3853e12c5d1SDavid du Colombier sname[sg->type&SG_TYPE], sg->type&SG_RONLY ? 'R' : ' ', 3863e12c5d1SDavid du Colombier sg->base, sg->top, sg->ref); 3873e12c5d1SDavid du Colombier if(offset >= j) 3883e12c5d1SDavid du Colombier return 0; 3893e12c5d1SDavid du Colombier if(offset+n > j) 3903e12c5d1SDavid du Colombier n = j-offset; 3913e12c5d1SDavid du Colombier if(n == 0 && offset == 0) 3923e12c5d1SDavid du Colombier exhausted("segments"); 3933e12c5d1SDavid du Colombier memmove(a, &statbuf[offset], n); 3943e12c5d1SDavid du Colombier return n; 395*219b2ee8SDavid du Colombier 396*219b2ee8SDavid du Colombier case Qwait: 397*219b2ee8SDavid du Colombier if(n < sizeof(Waitmsg)) 398*219b2ee8SDavid du Colombier error(Etoosmall); 399*219b2ee8SDavid du Colombier 400*219b2ee8SDavid du Colombier if(!canqlock(&p->qwaitr)) 401*219b2ee8SDavid du Colombier error(Einuse); 402*219b2ee8SDavid du Colombier 403*219b2ee8SDavid du Colombier if(waserror()) { 404*219b2ee8SDavid du Colombier qunlock(&p->qwaitr); 405*219b2ee8SDavid du Colombier nexterror(); 406*219b2ee8SDavid du Colombier } 407*219b2ee8SDavid du Colombier 408*219b2ee8SDavid du Colombier lock(&p->exl); 409*219b2ee8SDavid du Colombier if(u->p == p && p->nchild == 0 && p->waitq == 0) { 410*219b2ee8SDavid du Colombier unlock(&p->exl); 411*219b2ee8SDavid du Colombier error(Enochild); 412*219b2ee8SDavid du Colombier } 413*219b2ee8SDavid du Colombier while(p->waitq == 0) { 414*219b2ee8SDavid du Colombier unlock(&p->exl); 415*219b2ee8SDavid du Colombier sleep(&p->waitr, haswaitq, p); 416*219b2ee8SDavid du Colombier lock(&p->exl); 417*219b2ee8SDavid du Colombier } 418*219b2ee8SDavid du Colombier wq = p->waitq; 419*219b2ee8SDavid du Colombier p->waitq = wq->next; 420*219b2ee8SDavid du Colombier p->nwait--; 421*219b2ee8SDavid du Colombier unlock(&p->exl); 422*219b2ee8SDavid du Colombier 423*219b2ee8SDavid du Colombier qunlock(&p->qwaitr); 424*219b2ee8SDavid du Colombier poperror(); 425*219b2ee8SDavid du Colombier memmove(a, &wq->w, sizeof(Waitmsg)); 426*219b2ee8SDavid du Colombier free(wq); 427*219b2ee8SDavid du Colombier return sizeof(Waitmsg); 428*219b2ee8SDavid du Colombier case Qnoteid: 429*219b2ee8SDavid du Colombier return readnum(offset, va, n, p->noteid, NUMSIZE); 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier error(Egreg); 4323e12c5d1SDavid du Colombier return 0; /* not reached */ 4333e12c5d1SDavid du Colombier } 4343e12c5d1SDavid du Colombier 4353e12c5d1SDavid du Colombier 4363e12c5d1SDavid du Colombier long 4373e12c5d1SDavid du Colombier procwrite(Chan *c, void *va, long n, ulong offset) 4383e12c5d1SDavid du Colombier { 439*219b2ee8SDavid du Colombier int id; 4403e12c5d1SDavid du Colombier User *up; 4413e12c5d1SDavid du Colombier KMap *k; 4423e12c5d1SDavid du Colombier Ureg *ur; 4433e12c5d1SDavid du Colombier User *pxu; 4443e12c5d1SDavid du Colombier Page *pg; 4453e12c5d1SDavid du Colombier ulong hi; 446*219b2ee8SDavid du Colombier char *a, *b; 447*219b2ee8SDavid du Colombier char buf[ERRLEN]; 448*219b2ee8SDavid du Colombier Proc *p, *t, *et; 4493e12c5d1SDavid du Colombier 4503e12c5d1SDavid du Colombier if(c->qid.path & CHDIR) 4513e12c5d1SDavid du Colombier error(Eisdir); 4523e12c5d1SDavid du Colombier 453*219b2ee8SDavid du Colombier a = va; 4543e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid)); 4553e12c5d1SDavid du Colombier 456*219b2ee8SDavid du Colombier /* Use the remembered noteid in the channel 457*219b2ee8SDavid du Colombier * rather than the process pgrpid 458*219b2ee8SDavid du Colombier */ 4593e12c5d1SDavid du Colombier if(QID(c->qid) == Qnotepg) { 4603e12c5d1SDavid du Colombier pgrpnote(NOTEID(c->pgrpid), va, n, NUser); 4613e12c5d1SDavid du Colombier return n; 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier 4643e12c5d1SDavid du Colombier qlock(&p->debug); 4653e12c5d1SDavid du Colombier if(waserror()){ 4663e12c5d1SDavid du Colombier qunlock(&p->debug); 4673e12c5d1SDavid du Colombier nexterror(); 4683e12c5d1SDavid du Colombier } 4693e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 4703e12c5d1SDavid du Colombier error(Eprocdied); 4713e12c5d1SDavid du Colombier 4723e12c5d1SDavid du Colombier switch(QID(c->qid)){ 4733e12c5d1SDavid du Colombier case Qmem: 4743e12c5d1SDavid du Colombier if(p->state != Stopped) 4753e12c5d1SDavid du Colombier error(Ebadctl); 4763e12c5d1SDavid du Colombier 4773e12c5d1SDavid du Colombier if(offset >= USERADDR && offset <= USERADDR+BY2PG-1) { 4783e12c5d1SDavid du Colombier pg = p->upage; 4793e12c5d1SDavid du Colombier if(pg==0 || p->pid!=PID(c->qid)) 4803e12c5d1SDavid du Colombier error(Eprocdied); 4813e12c5d1SDavid du Colombier k = kmap(pg); 4823e12c5d1SDavid du Colombier b = (char*)VA(k); 4833e12c5d1SDavid du Colombier pxu = (User*)b; 4843e12c5d1SDavid du Colombier hi = offset+n; 4853e12c5d1SDavid du Colombier /* Check for floating point registers */ 4863e12c5d1SDavid du Colombier if(offset >= (ulong)&u->fpsave && 4873e12c5d1SDavid du Colombier hi <= (ulong)&u->fpsave+sizeof(FPsave)){ 4883e12c5d1SDavid du Colombier memmove(b+(offset-USERADDR), a, n); 4893e12c5d1SDavid du Colombier break; 4903e12c5d1SDavid du Colombier } 4913e12c5d1SDavid du Colombier /* Check user register set for process at kernel entry */ 4923e12c5d1SDavid du Colombier ur = pxu->dbgreg; 4933e12c5d1SDavid du Colombier if(offset < (ulong)ur || hi > (ulong)ur+sizeof(Ureg)) { 4943e12c5d1SDavid du Colombier kunmap(k); 4953e12c5d1SDavid du Colombier error(Ebadarg); 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier ur = (Ureg*)(b+((ulong)ur-USERADDR)); 4983e12c5d1SDavid du Colombier setregisters(ur, b+(offset-USERADDR), a, n); 4993e12c5d1SDavid du Colombier kunmap(k); 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier else /* Try user memory segments */ 5023e12c5d1SDavid du Colombier n = procctlmemio(p, offset, n, va, 0); 5033e12c5d1SDavid du Colombier break; 5043e12c5d1SDavid du Colombier 5053e12c5d1SDavid du Colombier case Qctl: 5063e12c5d1SDavid du Colombier procctlreq(p, va, n); 5073e12c5d1SDavid du Colombier break; 5083e12c5d1SDavid du Colombier 5093e12c5d1SDavid du Colombier case Qnote: 5103e12c5d1SDavid du Colombier if(p->kp) 5113e12c5d1SDavid du Colombier error(Eperm); 5123e12c5d1SDavid du Colombier k = kmap(p->upage); 5133e12c5d1SDavid du Colombier up = (User*)VA(k); 5143e12c5d1SDavid du Colombier if(up->p != p){ 5153e12c5d1SDavid du Colombier kunmap(k); 5163e12c5d1SDavid du Colombier pprint("note write u/p mismatch"); 5173e12c5d1SDavid du Colombier error(Egreg); 5183e12c5d1SDavid du Colombier } 5193e12c5d1SDavid du Colombier kunmap(k); 5203e12c5d1SDavid du Colombier if(n >= ERRLEN-1) 5213e12c5d1SDavid du Colombier error(Etoobig); 5223e12c5d1SDavid du Colombier memmove(buf, va, n); 5233e12c5d1SDavid du Colombier buf[n] = 0; 5243e12c5d1SDavid du Colombier if(!postnote(p, 0, buf, NUser)) 5253e12c5d1SDavid du Colombier error("note not posted"); 5263e12c5d1SDavid du Colombier break; 527*219b2ee8SDavid du Colombier case Qnoteid: 528*219b2ee8SDavid du Colombier id = atoi(a); 529*219b2ee8SDavid du Colombier if(id == p->pid) { 530*219b2ee8SDavid du Colombier p->noteid = id; 531*219b2ee8SDavid du Colombier break; 532*219b2ee8SDavid du Colombier } 533*219b2ee8SDavid du Colombier t = proctab(0); 534*219b2ee8SDavid du Colombier for(et = t+conf.nproc; t < et; t++) { 535*219b2ee8SDavid du Colombier if(id == t->noteid) { 536*219b2ee8SDavid du Colombier if(strcmp(p->user, t->user) != 0) 537*219b2ee8SDavid du Colombier error(Eperm); 538*219b2ee8SDavid du Colombier p->noteid = id; 539*219b2ee8SDavid du Colombier break; 540*219b2ee8SDavid du Colombier } 541*219b2ee8SDavid du Colombier } 542*219b2ee8SDavid du Colombier if(p->noteid != id) 543*219b2ee8SDavid du Colombier error(Ebadarg); 544*219b2ee8SDavid du Colombier break; 5453e12c5d1SDavid du Colombier default: 5463e12c5d1SDavid du Colombier pprint("unknown qid in procwrite\n"); 5473e12c5d1SDavid du Colombier error(Egreg); 5483e12c5d1SDavid du Colombier } 5493e12c5d1SDavid du Colombier poperror(); 5503e12c5d1SDavid du Colombier qunlock(&p->debug); 5513e12c5d1SDavid du Colombier return n; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier 5543e12c5d1SDavid du Colombier Chan * 5553e12c5d1SDavid du Colombier proctext(Chan *c, Proc *p) 5563e12c5d1SDavid du Colombier { 5573e12c5d1SDavid du Colombier Chan *tc; 5583e12c5d1SDavid du Colombier Image *i; 5593e12c5d1SDavid du Colombier Segment *s; 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier s = p->seg[TSEG]; 5623e12c5d1SDavid du Colombier if(s == 0) 5633e12c5d1SDavid du Colombier error(Enonexist); 5643e12c5d1SDavid du Colombier if(p->state==Dead) 5653e12c5d1SDavid du Colombier error(Eprocdied); 5663e12c5d1SDavid du Colombier 5673e12c5d1SDavid du Colombier lock(s); 5683e12c5d1SDavid du Colombier i = s->image; 5693e12c5d1SDavid du Colombier if(i == 0) { 5703e12c5d1SDavid du Colombier unlock(s); 5713e12c5d1SDavid du Colombier error(Eprocdied); 5723e12c5d1SDavid du Colombier } 5733e12c5d1SDavid du Colombier unlock(s); 5743e12c5d1SDavid du Colombier 5753e12c5d1SDavid du Colombier lock(i); 5763e12c5d1SDavid du Colombier if(waserror()) { 5773e12c5d1SDavid du Colombier unlock(i); 5783e12c5d1SDavid du Colombier nexterror(); 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier 5813e12c5d1SDavid du Colombier tc = i->c; 5823e12c5d1SDavid du Colombier if(tc == 0) 5833e12c5d1SDavid du Colombier error(Eprocdied); 5843e12c5d1SDavid du Colombier 5853e12c5d1SDavid du Colombier if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) { 5863e12c5d1SDavid du Colombier close(tc); 5873e12c5d1SDavid du Colombier error(Eprocdied); 5883e12c5d1SDavid du Colombier } 5893e12c5d1SDavid du Colombier 5903e12c5d1SDavid du Colombier if(p->pid != PID(c->qid)) 5913e12c5d1SDavid du Colombier error(Eprocdied); 5923e12c5d1SDavid du Colombier 5933e12c5d1SDavid du Colombier unlock(i); 5943e12c5d1SDavid du Colombier poperror(); 5953e12c5d1SDavid du Colombier 5963e12c5d1SDavid du Colombier return tc; 5973e12c5d1SDavid du Colombier } 5983e12c5d1SDavid du Colombier 5993e12c5d1SDavid du Colombier void 6003e12c5d1SDavid du Colombier procstopwait(Proc *p, int ctl) 6013e12c5d1SDavid du Colombier { 6023e12c5d1SDavid du Colombier int pid; 6033e12c5d1SDavid du Colombier 6043e12c5d1SDavid du Colombier if(p->pdbg) 6053e12c5d1SDavid du Colombier error(Einuse); 6063e12c5d1SDavid du Colombier if(procstopped(p)) 6073e12c5d1SDavid du Colombier return; 6083e12c5d1SDavid du Colombier 6093e12c5d1SDavid du Colombier if(ctl != 0) 6103e12c5d1SDavid du Colombier p->procctl = ctl; 6113e12c5d1SDavid du Colombier p->pdbg = u->p; 6123e12c5d1SDavid du Colombier pid = p->pid; 6133e12c5d1SDavid du Colombier qunlock(&p->debug); 6143e12c5d1SDavid du Colombier u->p->psstate = "Stopwait"; 6153e12c5d1SDavid du Colombier if(waserror()) { 6163e12c5d1SDavid du Colombier p->pdbg = 0; 6173e12c5d1SDavid du Colombier qlock(&p->debug); 6183e12c5d1SDavid du Colombier nexterror(); 6193e12c5d1SDavid du Colombier } 6203e12c5d1SDavid du Colombier sleep(&u->p->sleep, procstopped, p); 6213e12c5d1SDavid du Colombier poperror(); 6223e12c5d1SDavid du Colombier qlock(&p->debug); 6233e12c5d1SDavid du Colombier if(p->pid != pid) 6243e12c5d1SDavid du Colombier error(Eprocdied); 6253e12c5d1SDavid du Colombier } 6263e12c5d1SDavid du Colombier 6273e12c5d1SDavid du Colombier void 6283e12c5d1SDavid du Colombier procctlreq(Proc *p, char *va, int n) 6293e12c5d1SDavid du Colombier { 630*219b2ee8SDavid du Colombier int i; 631*219b2ee8SDavid du Colombier char buf[NAMELEN+1]; 6323e12c5d1SDavid du Colombier 6333e12c5d1SDavid du Colombier if(n > NAMELEN) 6343e12c5d1SDavid du Colombier n = NAMELEN; 6353e12c5d1SDavid du Colombier strncpy(buf, va, n); 636*219b2ee8SDavid du Colombier buf[NAMELEN] = '\0'; 6373e12c5d1SDavid du Colombier 6383e12c5d1SDavid du Colombier if(strncmp(buf, "stop", 4) == 0) 6393e12c5d1SDavid du Colombier procstopwait(p, Proc_stopme); 6403e12c5d1SDavid du Colombier else if(strncmp(buf, "kill", 4) == 0) { 641bd389b36SDavid du Colombier switch(p->state) { 642bd389b36SDavid du Colombier case Broken: 643bd389b36SDavid du Colombier unbreak(p); 644bd389b36SDavid du Colombier break; 645bd389b36SDavid du Colombier case Stopped: 646bd389b36SDavid du Colombier postnote(p, 0, "sys: killed", NExit); 647bd389b36SDavid du Colombier p->procctl = Proc_exitme; 6483e12c5d1SDavid du Colombier ready(p); 649bd389b36SDavid du Colombier break; 650bd389b36SDavid du Colombier default: 6513e12c5d1SDavid du Colombier postnote(p, 0, "sys: killed", NExit); 6523e12c5d1SDavid du Colombier p->procctl = Proc_exitme; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier } 6553e12c5d1SDavid du Colombier else if(strncmp(buf, "hang", 4) == 0) 6563e12c5d1SDavid du Colombier p->hang = 1; 657*219b2ee8SDavid du Colombier else if(strncmp(buf, "nohang", 6) == 0) 658*219b2ee8SDavid du Colombier p->hang = 0; 6593e12c5d1SDavid du Colombier else if(strncmp(buf, "waitstop", 8) == 0) 6603e12c5d1SDavid du Colombier procstopwait(p, 0); 6613e12c5d1SDavid du Colombier else if(strncmp(buf, "startstop", 9) == 0) { 6623e12c5d1SDavid du Colombier if(p->state != Stopped) 6633e12c5d1SDavid du Colombier error(Ebadctl); 6643e12c5d1SDavid du Colombier p->procctl = Proc_traceme; 6653e12c5d1SDavid du Colombier ready(p); 6663e12c5d1SDavid du Colombier procstopwait(p, Proc_traceme); 6673e12c5d1SDavid du Colombier } 6683e12c5d1SDavid du Colombier else if(strncmp(buf, "start", 5) == 0) { 6693e12c5d1SDavid du Colombier if(p->state != Stopped) 6703e12c5d1SDavid du Colombier error(Ebadctl); 6713e12c5d1SDavid du Colombier ready(p); 6723e12c5d1SDavid du Colombier } 673*219b2ee8SDavid du Colombier else if(strncmp(buf, "pri", 3) == 0){ 674*219b2ee8SDavid du Colombier if(n < 4) 675*219b2ee8SDavid du Colombier error(Ebadctl); 676*219b2ee8SDavid du Colombier i = atoi(buf+4); 677*219b2ee8SDavid du Colombier if(i < 0) 678*219b2ee8SDavid du Colombier i = 0; 679*219b2ee8SDavid du Colombier if(i >= Nrq) 680*219b2ee8SDavid du Colombier i = Nrq - 1; 681*219b2ee8SDavid du Colombier if(i < p->basepri && !iseve()) 682*219b2ee8SDavid du Colombier error(Eperm); 683*219b2ee8SDavid du Colombier p->basepri = i; 684*219b2ee8SDavid du Colombier } 6853e12c5d1SDavid du Colombier else 6863e12c5d1SDavid du Colombier error(Ebadctl); 6873e12c5d1SDavid du Colombier } 6883e12c5d1SDavid du Colombier 6893e12c5d1SDavid du Colombier int 6903e12c5d1SDavid du Colombier procstopped(void *a) 6913e12c5d1SDavid du Colombier { 6923e12c5d1SDavid du Colombier Proc *p = a; 6933e12c5d1SDavid du Colombier return p->state == Stopped; 6943e12c5d1SDavid du Colombier } 6953e12c5d1SDavid du Colombier 6963e12c5d1SDavid du Colombier int 6973e12c5d1SDavid du Colombier procctlmemio(Proc *p, ulong offset, int n, void *va, int read) 6983e12c5d1SDavid du Colombier { 6993e12c5d1SDavid du Colombier KMap *k; 7003e12c5d1SDavid du Colombier Pte *pte; 7013e12c5d1SDavid du Colombier Page *pg; 7023e12c5d1SDavid du Colombier Segment *s; 7033e12c5d1SDavid du Colombier ulong soff, l; 7043e12c5d1SDavid du Colombier char *a = va, *b; 7053e12c5d1SDavid du Colombier 7063e12c5d1SDavid du Colombier for(;;) { 7073e12c5d1SDavid du Colombier s = seg(p, offset, 1); 7083e12c5d1SDavid du Colombier if(s == 0) 7093e12c5d1SDavid du Colombier error(Ebadarg); 7103e12c5d1SDavid du Colombier 7113e12c5d1SDavid du Colombier if(offset+n >= s->top) 7123e12c5d1SDavid du Colombier n = s->top-offset; 7133e12c5d1SDavid du Colombier 714*219b2ee8SDavid du Colombier if(read == 0 && (s->type&SG_TYPE) == SG_TEXT) 7153e12c5d1SDavid du Colombier s = txt2data(p, s); 7163e12c5d1SDavid du Colombier 7173e12c5d1SDavid du Colombier s->steal++; 7183e12c5d1SDavid du Colombier soff = offset-s->base; 7193e12c5d1SDavid du Colombier if(waserror()) { 7203e12c5d1SDavid du Colombier s->steal--; 7213e12c5d1SDavid du Colombier nexterror(); 7223e12c5d1SDavid du Colombier } 7233e12c5d1SDavid du Colombier if(fixfault(s, offset, read, 0) == 0) 7243e12c5d1SDavid du Colombier break; 7253e12c5d1SDavid du Colombier poperror(); 7263e12c5d1SDavid du Colombier s->steal--; 7273e12c5d1SDavid du Colombier } 7283e12c5d1SDavid du Colombier poperror(); 7293e12c5d1SDavid du Colombier pte = s->map[soff/PTEMAPMEM]; 7303e12c5d1SDavid du Colombier if(pte == 0) 7313e12c5d1SDavid du Colombier panic("procctlmemio"); 7323e12c5d1SDavid du Colombier pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG]; 7333e12c5d1SDavid du Colombier if(pagedout(pg)) 7343e12c5d1SDavid du Colombier panic("procctlmemio1"); 7353e12c5d1SDavid du Colombier 7363e12c5d1SDavid du Colombier l = BY2PG - (offset&(BY2PG-1)); 7373e12c5d1SDavid du Colombier if(n > l) 7383e12c5d1SDavid du Colombier n = l; 7393e12c5d1SDavid du Colombier 7403e12c5d1SDavid du Colombier k = kmap(pg); 7413e12c5d1SDavid du Colombier b = (char*)VA(k); 7423e12c5d1SDavid du Colombier if(read == 1) 7433e12c5d1SDavid du Colombier memmove(a, b+(offset&(BY2PG-1)), n); 7443e12c5d1SDavid du Colombier else 7453e12c5d1SDavid du Colombier memmove(b+(offset&(BY2PG-1)), a, n); 7463e12c5d1SDavid du Colombier 7473e12c5d1SDavid du Colombier kunmap(k); 7483e12c5d1SDavid du Colombier 7493e12c5d1SDavid du Colombier s->steal--; 7503e12c5d1SDavid du Colombier qunlock(&s->lk); 7513e12c5d1SDavid du Colombier 7523e12c5d1SDavid du Colombier if(read == 0) 7533e12c5d1SDavid du Colombier p->newtlb = 1; 7543e12c5d1SDavid du Colombier 7553e12c5d1SDavid du Colombier return n; 7563e12c5d1SDavid du Colombier } 7573e12c5d1SDavid du Colombier 7583e12c5d1SDavid du Colombier Segment* 7593e12c5d1SDavid du Colombier txt2data(Proc *p, Segment *s) 7603e12c5d1SDavid du Colombier { 7613e12c5d1SDavid du Colombier int i; 7623e12c5d1SDavid du Colombier Segment *ps; 7633e12c5d1SDavid du Colombier 7643e12c5d1SDavid du Colombier ps = newseg(SG_DATA, s->base, s->size); 7653e12c5d1SDavid du Colombier ps->image = s->image; 7663e12c5d1SDavid du Colombier incref(ps->image); 7673e12c5d1SDavid du Colombier ps->fstart = s->fstart; 7683e12c5d1SDavid du Colombier ps->flen = s->flen; 7693e12c5d1SDavid du Colombier ps->flushme = 1; 7703e12c5d1SDavid du Colombier 7713e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++) 7723e12c5d1SDavid du Colombier if(p->seg[i] == s) 7733e12c5d1SDavid du Colombier break; 7743e12c5d1SDavid du Colombier if(p->seg[i] != s) 7753e12c5d1SDavid du Colombier panic("segment gone"); 7763e12c5d1SDavid du Colombier 7773e12c5d1SDavid du Colombier qunlock(&s->lk); 7783e12c5d1SDavid du Colombier putseg(s); 7793e12c5d1SDavid du Colombier qlock(&ps->lk); 7803e12c5d1SDavid du Colombier p->seg[i] = ps; 7813e12c5d1SDavid du Colombier 7823e12c5d1SDavid du Colombier return ps; 7833e12c5d1SDavid du Colombier } 784bd389b36SDavid du Colombier 785bd389b36SDavid du Colombier Segment* 786bd389b36SDavid du Colombier data2txt(Segment *s) 787bd389b36SDavid du Colombier { 788bd389b36SDavid du Colombier Segment *ps; 789bd389b36SDavid du Colombier 790bd389b36SDavid du Colombier ps = newseg(SG_TEXT, s->base, s->size); 791bd389b36SDavid du Colombier ps->image = s->image; 792bd389b36SDavid du Colombier incref(ps->image); 793bd389b36SDavid du Colombier ps->fstart = s->fstart; 794bd389b36SDavid du Colombier ps->flen = s->flen; 795bd389b36SDavid du Colombier ps->flushme = 1; 796bd389b36SDavid du Colombier 797bd389b36SDavid du Colombier return ps; 798bd389b36SDavid du Colombier } 799