19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier #include "../port/edf.h"
99ef1f84bSDavid du Colombier #include "tos.h"
109ef1f84bSDavid du Colombier #include <trace.h>
119ef1f84bSDavid du Colombier #include "ureg.h"
129ef1f84bSDavid du Colombier
139ef1f84bSDavid du Colombier enum
149ef1f84bSDavid du Colombier {
159ef1f84bSDavid du Colombier Qdir,
169ef1f84bSDavid du Colombier Qtrace,
179ef1f84bSDavid du Colombier Qargs,
189ef1f84bSDavid du Colombier Qctl,
199ef1f84bSDavid du Colombier Qfd,
209ef1f84bSDavid du Colombier Qfpregs,
219ef1f84bSDavid du Colombier Qkregs,
229ef1f84bSDavid du Colombier Qmem,
239ef1f84bSDavid du Colombier Qnote,
249ef1f84bSDavid du Colombier Qnoteid,
259ef1f84bSDavid du Colombier Qnotepg,
269ef1f84bSDavid du Colombier Qns,
279ef1f84bSDavid du Colombier Qproc,
289ef1f84bSDavid du Colombier Qregs,
299ef1f84bSDavid du Colombier Qsegment,
309ef1f84bSDavid du Colombier Qstatus,
319ef1f84bSDavid du Colombier Qtext,
329ef1f84bSDavid du Colombier Qwait,
339ef1f84bSDavid du Colombier Qprofile,
349ef1f84bSDavid du Colombier Qsyscall,
359ef1f84bSDavid du Colombier };
369ef1f84bSDavid du Colombier
379ef1f84bSDavid du Colombier enum
389ef1f84bSDavid du Colombier {
399ef1f84bSDavid du Colombier CMclose,
409ef1f84bSDavid du Colombier CMclosefiles,
419ef1f84bSDavid du Colombier CMfixedpri,
429ef1f84bSDavid du Colombier CMhang,
439ef1f84bSDavid du Colombier CMkill,
449ef1f84bSDavid du Colombier CMnohang,
459ef1f84bSDavid du Colombier CMnoswap,
469ef1f84bSDavid du Colombier CMpri,
479ef1f84bSDavid du Colombier CMprivate,
489ef1f84bSDavid du Colombier CMprofile,
499ef1f84bSDavid du Colombier CMstart,
509ef1f84bSDavid du Colombier CMstartstop,
519ef1f84bSDavid du Colombier CMstartsyscall,
529ef1f84bSDavid du Colombier CMstop,
539ef1f84bSDavid du Colombier CMwaitstop,
549ef1f84bSDavid du Colombier CMwired,
559ef1f84bSDavid du Colombier CMtrace,
569ef1f84bSDavid du Colombier /* real time */
579ef1f84bSDavid du Colombier CMperiod,
589ef1f84bSDavid du Colombier CMdeadline,
599ef1f84bSDavid du Colombier CMcost,
609ef1f84bSDavid du Colombier CMsporadic,
619ef1f84bSDavid du Colombier CMdeadlinenotes,
629ef1f84bSDavid du Colombier CMadmit,
639ef1f84bSDavid du Colombier CMextra,
649ef1f84bSDavid du Colombier CMexpel,
659ef1f84bSDavid du Colombier CMevent,
669ef1f84bSDavid du Colombier };
679ef1f84bSDavid du Colombier
689ef1f84bSDavid du Colombier enum{
699ef1f84bSDavid du Colombier Nevents = 0x4000,
709ef1f84bSDavid du Colombier Emask = Nevents - 1,
719ef1f84bSDavid du Colombier };
729ef1f84bSDavid du Colombier
739ef1f84bSDavid du Colombier #define STATSIZE (2*KNAMELEN+12+9*12)
749ef1f84bSDavid du Colombier /*
759ef1f84bSDavid du Colombier * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
769ef1f84bSDavid du Colombier * particularly on shared servers.
779ef1f84bSDavid du Colombier * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
789ef1f84bSDavid du Colombier */
799ef1f84bSDavid du Colombier Dirtab procdir[] =
809ef1f84bSDavid du Colombier {
819ef1f84bSDavid du Colombier "args", {Qargs}, 0, 0660,
829ef1f84bSDavid du Colombier "ctl", {Qctl}, 0, 0000,
839ef1f84bSDavid du Colombier "fd", {Qfd}, 0, 0444,
849ef1f84bSDavid du Colombier "fpregs", {Qfpregs}, 0, 0000,
859ef1f84bSDavid du Colombier "kregs", {Qkregs}, sizeof(Ureg), 0400,
869ef1f84bSDavid du Colombier "mem", {Qmem}, 0, 0000,
879ef1f84bSDavid du Colombier "note", {Qnote}, 0, 0000,
889ef1f84bSDavid du Colombier "noteid", {Qnoteid}, 0, 0664,
899ef1f84bSDavid du Colombier "notepg", {Qnotepg}, 0, 0000,
909ef1f84bSDavid du Colombier "ns", {Qns}, 0, 0444,
919ef1f84bSDavid du Colombier "proc", {Qproc}, 0, 0400,
929ef1f84bSDavid du Colombier "regs", {Qregs}, sizeof(Ureg), 0000,
939ef1f84bSDavid du Colombier "segment", {Qsegment}, 0, 0444,
949ef1f84bSDavid du Colombier "status", {Qstatus}, STATSIZE, 0444,
959ef1f84bSDavid du Colombier "text", {Qtext}, 0, 0000,
969ef1f84bSDavid du Colombier "wait", {Qwait}, 0, 0400,
979ef1f84bSDavid du Colombier "profile", {Qprofile}, 0, 0400,
989ef1f84bSDavid du Colombier "syscall", {Qsyscall}, 0, 0400,
999ef1f84bSDavid du Colombier };
1009ef1f84bSDavid du Colombier
1019ef1f84bSDavid du Colombier static
1029ef1f84bSDavid du Colombier Cmdtab proccmd[] = {
1039ef1f84bSDavid du Colombier CMclose, "close", 2,
1049ef1f84bSDavid du Colombier CMclosefiles, "closefiles", 1,
1059ef1f84bSDavid du Colombier CMfixedpri, "fixedpri", 2,
1069ef1f84bSDavid du Colombier CMhang, "hang", 1,
1079ef1f84bSDavid du Colombier CMnohang, "nohang", 1,
1089ef1f84bSDavid du Colombier CMnoswap, "noswap", 1,
1099ef1f84bSDavid du Colombier CMkill, "kill", 1,
1109ef1f84bSDavid du Colombier CMpri, "pri", 2,
1119ef1f84bSDavid du Colombier CMprivate, "private", 1,
1129ef1f84bSDavid du Colombier CMprofile, "profile", 1,
1139ef1f84bSDavid du Colombier CMstart, "start", 1,
1149ef1f84bSDavid du Colombier CMstartstop, "startstop", 1,
1159ef1f84bSDavid du Colombier CMstartsyscall, "startsyscall", 1,
1169ef1f84bSDavid du Colombier CMstop, "stop", 1,
1179ef1f84bSDavid du Colombier CMwaitstop, "waitstop", 1,
1189ef1f84bSDavid du Colombier CMwired, "wired", 2,
1199ef1f84bSDavid du Colombier CMtrace, "trace", 0,
1209ef1f84bSDavid du Colombier CMperiod, "period", 2,
1219ef1f84bSDavid du Colombier CMdeadline, "deadline", 2,
1229ef1f84bSDavid du Colombier CMcost, "cost", 2,
1239ef1f84bSDavid du Colombier CMsporadic, "sporadic", 1,
1249ef1f84bSDavid du Colombier CMdeadlinenotes, "deadlinenotes", 1,
1259ef1f84bSDavid du Colombier CMadmit, "admit", 1,
1269ef1f84bSDavid du Colombier CMextra, "extra", 1,
1279ef1f84bSDavid du Colombier CMexpel, "expel", 1,
1289ef1f84bSDavid du Colombier CMevent, "event", 1,
1299ef1f84bSDavid du Colombier };
1309ef1f84bSDavid du Colombier
1319ef1f84bSDavid du Colombier /* Segment type from portdat.h */
1329ef1f84bSDavid du Colombier static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
1339ef1f84bSDavid du Colombier
1349ef1f84bSDavid du Colombier /*
1359ef1f84bSDavid du Colombier * Qids are, in path:
136406c76faSDavid du Colombier * 5 bits of file type (qids above)
137406c76faSDavid du Colombier * 26 bits of process slot number + 1
1389ef1f84bSDavid du Colombier * in vers,
1399ef1f84bSDavid du Colombier * 32 bits of pid, for consistency checking
1409ef1f84bSDavid du Colombier * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
1419ef1f84bSDavid du Colombier */
1429ef1f84bSDavid du Colombier #define QSHIFT 5 /* location in qid of proc slot # */
1439ef1f84bSDavid du Colombier
144406c76faSDavid du Colombier #define QID(q) ((((ulong)(q).path) & ((1<<QSHIFT)-1)) >> 0)
145406c76faSDavid du Colombier #define SLOT(q) (((((ulong)(q).path) & ~(1UL<<31)) >> QSHIFT) - 1)
1469ef1f84bSDavid du Colombier #define PID(q) ((q).vers)
1479ef1f84bSDavid du Colombier #define NOTEID(q) ((q).vers)
1489ef1f84bSDavid du Colombier
1499ef1f84bSDavid du Colombier static void procctlreq(Proc*, char*, int);
1509ef1f84bSDavid du Colombier static int procctlmemio(Proc*, uintptr, int, void*, int);
1519ef1f84bSDavid du Colombier static Chan* proctext(Chan*, Proc*);
1529ef1f84bSDavid du Colombier static Segment* txt2data(Proc*, Segment*);
1539ef1f84bSDavid du Colombier static int procstopped(void*);
1549ef1f84bSDavid du Colombier static void mntscan(Mntwalk*, Proc*);
1559ef1f84bSDavid du Colombier
1569ef1f84bSDavid du Colombier static Traceevent *tevents;
1579ef1f84bSDavid du Colombier static Lock tlock;
1589ef1f84bSDavid du Colombier static int topens;
1599ef1f84bSDavid du Colombier static int tproduced, tconsumed;
1609ef1f84bSDavid du Colombier
1619ef1f84bSDavid du Colombier static void
profclock(Ureg * ur,Timer *)1629ef1f84bSDavid du Colombier profclock(Ureg *ur, Timer *)
1639ef1f84bSDavid du Colombier {
1649ef1f84bSDavid du Colombier Tos *tos;
1659ef1f84bSDavid du Colombier
1669ef1f84bSDavid du Colombier if(up == nil || up->state != Running)
1679ef1f84bSDavid du Colombier return;
1689ef1f84bSDavid du Colombier
1699ef1f84bSDavid du Colombier /* user profiling clock */
1709ef1f84bSDavid du Colombier if(userureg(ur)){
1719ef1f84bSDavid du Colombier tos = (Tos*)(USTKTOP-sizeof(Tos));
1729ef1f84bSDavid du Colombier tos->clock += TK2MS(1);
1739ef1f84bSDavid du Colombier segclock(userpc(ur));
1749ef1f84bSDavid du Colombier }
1759ef1f84bSDavid du Colombier }
1769ef1f84bSDavid du Colombier
1779ef1f84bSDavid du Colombier static int
procgen(Chan * c,char * name,Dirtab * tab,int,int s,Dir * dp)1789ef1f84bSDavid du Colombier procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
1799ef1f84bSDavid du Colombier {
1809ef1f84bSDavid du Colombier Qid qid;
1819ef1f84bSDavid du Colombier Proc *p;
1829ef1f84bSDavid du Colombier char *ename;
1839ef1f84bSDavid du Colombier Segment *q;
1849ef1f84bSDavid du Colombier int pid;
1859ef1f84bSDavid du Colombier ulong path, perm, len;
1869ef1f84bSDavid du Colombier
1879ef1f84bSDavid du Colombier if(s == DEVDOTDOT){
1889ef1f84bSDavid du Colombier mkqid(&qid, Qdir, 0, QTDIR);
1899ef1f84bSDavid du Colombier devdir(c, qid, "#p", 0, eve, 0555, dp);
1909ef1f84bSDavid du Colombier return 1;
1919ef1f84bSDavid du Colombier }
1929ef1f84bSDavid du Colombier
1939ef1f84bSDavid du Colombier if(c->qid.path == Qdir){
1949ef1f84bSDavid du Colombier if(s == 0){
1959ef1f84bSDavid du Colombier strcpy(up->genbuf, "trace");
1969ef1f84bSDavid du Colombier mkqid(&qid, Qtrace, -1, QTFILE);
1979ef1f84bSDavid du Colombier devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
1989ef1f84bSDavid du Colombier return 1;
1999ef1f84bSDavid du Colombier }
2009ef1f84bSDavid du Colombier
2019ef1f84bSDavid du Colombier if(name != nil){
2029ef1f84bSDavid du Colombier /* ignore s and use name to find pid */
2039ef1f84bSDavid du Colombier pid = strtol(name, &ename, 10);
2049ef1f84bSDavid du Colombier if(pid<=0 || ename[0]!='\0')
2059ef1f84bSDavid du Colombier return -1;
2069ef1f84bSDavid du Colombier s = psindex(pid);
2079ef1f84bSDavid du Colombier if(s < 0)
2089ef1f84bSDavid du Colombier return -1;
2099ef1f84bSDavid du Colombier }
2109ef1f84bSDavid du Colombier else if(--s >= PROCMAX)
2119ef1f84bSDavid du Colombier return -1;
2129ef1f84bSDavid du Colombier
2139ef1f84bSDavid du Colombier if((p = psincref(s)) == nil || (pid = p->pid) == 0)
2149ef1f84bSDavid du Colombier return 0;
215406c76faSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf, "%d", pid);
2169ef1f84bSDavid du Colombier /*
2179ef1f84bSDavid du Colombier * String comparison is done in devwalk so
2189ef1f84bSDavid du Colombier * name must match its formatted pid.
2199ef1f84bSDavid du Colombier */
2209ef1f84bSDavid du Colombier if(name != nil && strcmp(name, up->genbuf) != 0)
2219ef1f84bSDavid du Colombier return -1;
2229ef1f84bSDavid du Colombier mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
2239ef1f84bSDavid du Colombier devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
2249ef1f84bSDavid du Colombier psdecref(p);
2259ef1f84bSDavid du Colombier return 1;
2269ef1f84bSDavid du Colombier }
2279ef1f84bSDavid du Colombier if(c->qid.path == Qtrace){
2289ef1f84bSDavid du Colombier strcpy(up->genbuf, "trace");
2299ef1f84bSDavid du Colombier mkqid(&qid, Qtrace, -1, QTFILE);
2309ef1f84bSDavid du Colombier devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
2319ef1f84bSDavid du Colombier return 1;
2329ef1f84bSDavid du Colombier }
2339ef1f84bSDavid du Colombier if(s >= nelem(procdir))
2349ef1f84bSDavid du Colombier return -1;
2359ef1f84bSDavid du Colombier if(tab)
2369ef1f84bSDavid du Colombier panic("procgen");
2379ef1f84bSDavid du Colombier
2389ef1f84bSDavid du Colombier tab = &procdir[s];
2399ef1f84bSDavid du Colombier path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
2409ef1f84bSDavid du Colombier
241406c76faSDavid du Colombier /* p->procmode determines default mode for files in /proc */
2429ef1f84bSDavid du Colombier if((p = psincref(SLOT(c->qid))) == nil)
2439ef1f84bSDavid du Colombier return -1;
2449ef1f84bSDavid du Colombier perm = tab->perm;
2459ef1f84bSDavid du Colombier if(perm == 0)
2469ef1f84bSDavid du Colombier perm = p->procmode;
2479ef1f84bSDavid du Colombier else /* just copy read bits */
2489ef1f84bSDavid du Colombier perm |= p->procmode & 0444;
2499ef1f84bSDavid du Colombier
2509ef1f84bSDavid du Colombier len = tab->length;
2519ef1f84bSDavid du Colombier switch(QID(c->qid)) {
2529ef1f84bSDavid du Colombier case Qwait:
2539ef1f84bSDavid du Colombier len = p->nwait; /* incorrect size, but >0 means there's something to read */
2549ef1f84bSDavid du Colombier break;
2559ef1f84bSDavid du Colombier case Qprofile:
2569ef1f84bSDavid du Colombier q = p->seg[TSEG];
2579ef1f84bSDavid du Colombier if(q && q->profile) {
2589ef1f84bSDavid du Colombier len = (q->top-q->base)>>LRESPROF;
2599ef1f84bSDavid du Colombier len *= sizeof(*q->profile);
2609ef1f84bSDavid du Colombier }
2619ef1f84bSDavid du Colombier break;
2629ef1f84bSDavid du Colombier }
2639ef1f84bSDavid du Colombier
2649ef1f84bSDavid du Colombier mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
2659ef1f84bSDavid du Colombier devdir(c, qid, tab->name, len, p->user, perm, dp);
2669ef1f84bSDavid du Colombier psdecref(p);
2679ef1f84bSDavid du Colombier return 1;
2689ef1f84bSDavid du Colombier }
2699ef1f84bSDavid du Colombier
2709ef1f84bSDavid du Colombier static void
_proctrace(Proc * p,Tevent etype,vlong ts,vlong)271d46407a3SDavid du Colombier _proctrace(Proc* p, Tevent etype, vlong ts, vlong)
2729ef1f84bSDavid du Colombier {
2739ef1f84bSDavid du Colombier Traceevent *te;
2749ef1f84bSDavid du Colombier
2759ef1f84bSDavid du Colombier if (p->trace == 0 || topens == 0 ||
2769ef1f84bSDavid du Colombier tproduced - tconsumed >= Nevents)
2779ef1f84bSDavid du Colombier return;
2789ef1f84bSDavid du Colombier
2799ef1f84bSDavid du Colombier te = &tevents[tproduced&Emask];
2809ef1f84bSDavid du Colombier te->pid = p->pid;
2819ef1f84bSDavid du Colombier te->etype = etype;
2829ef1f84bSDavid du Colombier if (ts == 0)
2839ef1f84bSDavid du Colombier te->time = todget(nil);
2849ef1f84bSDavid du Colombier else
2859ef1f84bSDavid du Colombier te->time = ts;
2869ef1f84bSDavid du Colombier tproduced++;
2879ef1f84bSDavid du Colombier }
2889ef1f84bSDavid du Colombier
2899ef1f84bSDavid du Colombier static void
procinit(void)2909ef1f84bSDavid du Colombier procinit(void)
2919ef1f84bSDavid du Colombier {
292406c76faSDavid du Colombier if(PROCMAX >= (1<<(31-QSHIFT))-1)
2939ef1f84bSDavid du Colombier print("warning: too many procs for devproc\n");
2949ef1f84bSDavid du Colombier addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */
2959ef1f84bSDavid du Colombier }
2969ef1f84bSDavid du Colombier
2979ef1f84bSDavid du Colombier static Chan*
procattach(char * spec)2989ef1f84bSDavid du Colombier procattach(char *spec)
2999ef1f84bSDavid du Colombier {
3009ef1f84bSDavid du Colombier return devattach('p', spec);
3019ef1f84bSDavid du Colombier }
3029ef1f84bSDavid du Colombier
3039ef1f84bSDavid du Colombier static Walkqid*
procwalk(Chan * c,Chan * nc,char ** name,int nname)3049ef1f84bSDavid du Colombier procwalk(Chan *c, Chan *nc, char **name, int nname)
3059ef1f84bSDavid du Colombier {
3069ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, procgen);
3079ef1f84bSDavid du Colombier }
3089ef1f84bSDavid du Colombier
3099ef1f84bSDavid du Colombier static long
procstat(Chan * c,uchar * db,long n)3109ef1f84bSDavid du Colombier procstat(Chan *c, uchar *db, long n)
3119ef1f84bSDavid du Colombier {
3129ef1f84bSDavid du Colombier return devstat(c, db, n, 0, 0, procgen);
3139ef1f84bSDavid du Colombier }
3149ef1f84bSDavid du Colombier
3159ef1f84bSDavid du Colombier /*
3169ef1f84bSDavid du Colombier * none can't read or write state on other
3179ef1f84bSDavid du Colombier * processes. This is to contain access of
3189ef1f84bSDavid du Colombier * servers running as none should they be
3199ef1f84bSDavid du Colombier * subverted by, for example, a stack attack.
3209ef1f84bSDavid du Colombier */
3219ef1f84bSDavid du Colombier static void
nonone(Proc * p)3229ef1f84bSDavid du Colombier nonone(Proc *p)
3239ef1f84bSDavid du Colombier {
3249ef1f84bSDavid du Colombier if(p == up)
3259ef1f84bSDavid du Colombier return;
3269ef1f84bSDavid du Colombier if(strcmp(up->user, "none") != 0)
3279ef1f84bSDavid du Colombier return;
3289ef1f84bSDavid du Colombier if(iseve())
3299ef1f84bSDavid du Colombier return;
3309ef1f84bSDavid du Colombier error(Eperm);
3319ef1f84bSDavid du Colombier }
3329ef1f84bSDavid du Colombier
3339ef1f84bSDavid du Colombier static Chan*
procopen(Chan * c,int omode)3349ef1f84bSDavid du Colombier procopen(Chan *c, int omode)
3359ef1f84bSDavid du Colombier {
3369ef1f84bSDavid du Colombier Proc *p;
3379ef1f84bSDavid du Colombier Pgrp *pg;
3389ef1f84bSDavid du Colombier Chan *tc;
3399ef1f84bSDavid du Colombier int pid;
3409ef1f84bSDavid du Colombier
3419ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
3429ef1f84bSDavid du Colombier return devopen(c, omode, 0, 0, procgen);
3439ef1f84bSDavid du Colombier
3449ef1f84bSDavid du Colombier if(QID(c->qid) == Qtrace){
3459ef1f84bSDavid du Colombier if (omode != OREAD)
3469ef1f84bSDavid du Colombier error(Eperm);
3479ef1f84bSDavid du Colombier lock(&tlock);
3489ef1f84bSDavid du Colombier if (waserror()){
3499ef1f84bSDavid du Colombier unlock(&tlock);
3509ef1f84bSDavid du Colombier nexterror();
3519ef1f84bSDavid du Colombier }
3529ef1f84bSDavid du Colombier if (topens > 0)
3539ef1f84bSDavid du Colombier error("already open");
3549ef1f84bSDavid du Colombier topens++;
3559ef1f84bSDavid du Colombier if (tevents == nil){
3569ef1f84bSDavid du Colombier tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
3579ef1f84bSDavid du Colombier if(tevents == nil)
3589ef1f84bSDavid du Colombier error(Enomem);
3599ef1f84bSDavid du Colombier tproduced = tconsumed = 0;
3609ef1f84bSDavid du Colombier }
3619ef1f84bSDavid du Colombier proctrace = _proctrace;
3629ef1f84bSDavid du Colombier poperror();
3639ef1f84bSDavid du Colombier unlock(&tlock);
3649ef1f84bSDavid du Colombier
3659ef1f84bSDavid du Colombier c->mode = openmode(omode);
3669ef1f84bSDavid du Colombier c->flag |= COPEN;
3679ef1f84bSDavid du Colombier c->offset = 0;
3689ef1f84bSDavid du Colombier return c;
3699ef1f84bSDavid du Colombier }
3709ef1f84bSDavid du Colombier
3719ef1f84bSDavid du Colombier if((p = psincref(SLOT(c->qid))) == nil)
3729ef1f84bSDavid du Colombier error(Eprocdied);
3739ef1f84bSDavid du Colombier qlock(&p->debug);
3749ef1f84bSDavid du Colombier if(waserror()){
3759ef1f84bSDavid du Colombier qunlock(&p->debug);
3769ef1f84bSDavid du Colombier psdecref(p);
3779ef1f84bSDavid du Colombier nexterror();
3789ef1f84bSDavid du Colombier }
3799ef1f84bSDavid du Colombier pid = PID(c->qid);
3809ef1f84bSDavid du Colombier if(p->pid != pid)
3819ef1f84bSDavid du Colombier error(Eprocdied);
3829ef1f84bSDavid du Colombier
3839ef1f84bSDavid du Colombier omode = openmode(omode);
3849ef1f84bSDavid du Colombier
3859ef1f84bSDavid du Colombier switch(QID(c->qid)){
3869ef1f84bSDavid du Colombier case Qtext:
3879ef1f84bSDavid du Colombier if(omode != OREAD)
3889ef1f84bSDavid du Colombier error(Eperm);
3899ef1f84bSDavid du Colombier tc = proctext(c, p);
3909ef1f84bSDavid du Colombier tc->offset = 0;
3919ef1f84bSDavid du Colombier poperror();
392406c76faSDavid du Colombier cclose(c);
3939ef1f84bSDavid du Colombier qunlock(&p->debug);
3949ef1f84bSDavid du Colombier psdecref(p);
3959ef1f84bSDavid du Colombier return tc;
3969ef1f84bSDavid du Colombier
3979ef1f84bSDavid du Colombier case Qproc:
3989ef1f84bSDavid du Colombier case Qkregs:
3999ef1f84bSDavid du Colombier case Qsegment:
4009ef1f84bSDavid du Colombier case Qprofile:
4019ef1f84bSDavid du Colombier case Qfd:
4029ef1f84bSDavid du Colombier if(omode != OREAD)
4039ef1f84bSDavid du Colombier error(Eperm);
4049ef1f84bSDavid du Colombier break;
4059ef1f84bSDavid du Colombier
4069ef1f84bSDavid du Colombier case Qnote:
4079ef1f84bSDavid du Colombier if(p->privatemem)
4089ef1f84bSDavid du Colombier error(Eperm);
4099ef1f84bSDavid du Colombier break;
4109ef1f84bSDavid du Colombier
4119ef1f84bSDavid du Colombier case Qmem:
4129ef1f84bSDavid du Colombier case Qctl:
4139ef1f84bSDavid du Colombier if(p->privatemem)
4149ef1f84bSDavid du Colombier error(Eperm);
4159ef1f84bSDavid du Colombier nonone(p);
4169ef1f84bSDavid du Colombier break;
4179ef1f84bSDavid du Colombier
4189ef1f84bSDavid du Colombier case Qargs:
4199ef1f84bSDavid du Colombier case Qnoteid:
4209ef1f84bSDavid du Colombier case Qstatus:
4219ef1f84bSDavid du Colombier case Qwait:
4229ef1f84bSDavid du Colombier case Qregs:
4239ef1f84bSDavid du Colombier case Qfpregs:
4249ef1f84bSDavid du Colombier case Qsyscall:
4259ef1f84bSDavid du Colombier nonone(p);
4269ef1f84bSDavid du Colombier break;
4279ef1f84bSDavid du Colombier
4289ef1f84bSDavid du Colombier case Qns:
4299ef1f84bSDavid du Colombier if(omode != OREAD)
4309ef1f84bSDavid du Colombier error(Eperm);
4319ef1f84bSDavid du Colombier c->aux = malloc(sizeof(Mntwalk));
4329ef1f84bSDavid du Colombier break;
4339ef1f84bSDavid du Colombier
4349ef1f84bSDavid du Colombier case Qnotepg:
4359ef1f84bSDavid du Colombier nonone(p);
4369ef1f84bSDavid du Colombier pg = p->pgrp;
4379ef1f84bSDavid du Colombier if(pg == nil)
4389ef1f84bSDavid du Colombier error(Eprocdied);
4399ef1f84bSDavid du Colombier if(omode!=OWRITE || pg->pgrpid == 1)
4409ef1f84bSDavid du Colombier error(Eperm);
4419ef1f84bSDavid du Colombier c->pgrpid.path = pg->pgrpid+1;
4429ef1f84bSDavid du Colombier c->pgrpid.vers = p->noteid;
4439ef1f84bSDavid du Colombier break;
4449ef1f84bSDavid du Colombier
4459ef1f84bSDavid du Colombier default:
4469ef1f84bSDavid du Colombier poperror();
4479ef1f84bSDavid du Colombier qunlock(&p->debug);
4489ef1f84bSDavid du Colombier psdecref(p);
4499ef1f84bSDavid du Colombier pprint("procopen %#llux\n", c->qid.path);
4509ef1f84bSDavid du Colombier error(Egreg);
4519ef1f84bSDavid du Colombier }
4529ef1f84bSDavid du Colombier
4539ef1f84bSDavid du Colombier /* Affix pid to qid */
4549ef1f84bSDavid du Colombier if(p->state != Dead)
4559ef1f84bSDavid du Colombier c->qid.vers = p->pid;
4569ef1f84bSDavid du Colombier
4579ef1f84bSDavid du Colombier /* make sure the process slot didn't get reallocated while we were playing */
4589ef1f84bSDavid du Colombier coherence();
4599ef1f84bSDavid du Colombier if(p->pid != pid)
4609ef1f84bSDavid du Colombier error(Eprocdied);
4619ef1f84bSDavid du Colombier
4629ef1f84bSDavid du Colombier tc = devopen(c, omode, 0, 0, procgen);
4639ef1f84bSDavid du Colombier poperror();
4649ef1f84bSDavid du Colombier qunlock(&p->debug);
4659ef1f84bSDavid du Colombier psdecref(p);
4669ef1f84bSDavid du Colombier
4679ef1f84bSDavid du Colombier return tc;
4689ef1f84bSDavid du Colombier }
4699ef1f84bSDavid du Colombier
4709ef1f84bSDavid du Colombier static long
procwstat(Chan * c,uchar * db,long n)4719ef1f84bSDavid du Colombier procwstat(Chan *c, uchar *db, long n)
4729ef1f84bSDavid du Colombier {
4739ef1f84bSDavid du Colombier Proc *p;
4749ef1f84bSDavid du Colombier Dir *d;
4759ef1f84bSDavid du Colombier
4769ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
4779ef1f84bSDavid du Colombier error(Eperm);
4789ef1f84bSDavid du Colombier
4799ef1f84bSDavid du Colombier if(QID(c->qid) == Qtrace)
4809ef1f84bSDavid du Colombier return devwstat(c, db, n);
4819ef1f84bSDavid du Colombier
4829ef1f84bSDavid du Colombier if((p = psincref(SLOT(c->qid))) == nil)
4839ef1f84bSDavid du Colombier error(Eprocdied);
4849ef1f84bSDavid du Colombier nonone(p);
4859ef1f84bSDavid du Colombier d = nil;
4869ef1f84bSDavid du Colombier qlock(&p->debug);
4879ef1f84bSDavid du Colombier if(waserror()){
4889ef1f84bSDavid du Colombier qunlock(&p->debug);
4899ef1f84bSDavid du Colombier psdecref(p);
4909ef1f84bSDavid du Colombier free(d);
4919ef1f84bSDavid du Colombier nexterror();
4929ef1f84bSDavid du Colombier }
4939ef1f84bSDavid du Colombier
4949ef1f84bSDavid du Colombier if(p->pid != PID(c->qid))
4959ef1f84bSDavid du Colombier error(Eprocdied);
4969ef1f84bSDavid du Colombier
4979ef1f84bSDavid du Colombier if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
4989ef1f84bSDavid du Colombier error(Eperm);
4999ef1f84bSDavid du Colombier
5009ef1f84bSDavid du Colombier d = smalloc(sizeof(Dir)+n);
5019ef1f84bSDavid du Colombier n = convM2D(db, n, &d[0], (char*)&d[1]);
5029ef1f84bSDavid du Colombier if(n == 0)
5039ef1f84bSDavid du Colombier error(Eshortstat);
5049ef1f84bSDavid du Colombier if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
5059ef1f84bSDavid du Colombier if(strcmp(up->user, eve) != 0)
5069ef1f84bSDavid du Colombier error(Eperm);
5079ef1f84bSDavid du Colombier else
5089ef1f84bSDavid du Colombier kstrdup(&p->user, d->uid);
5099ef1f84bSDavid du Colombier }
510406c76faSDavid du Colombier /* p->procmode determines default mode for files in /proc */
5119ef1f84bSDavid du Colombier if(d->mode != ~0UL)
5129ef1f84bSDavid du Colombier p->procmode = d->mode&0777;
5139ef1f84bSDavid du Colombier
5149ef1f84bSDavid du Colombier poperror();
5159ef1f84bSDavid du Colombier qunlock(&p->debug);
5169ef1f84bSDavid du Colombier psdecref(p);
5179ef1f84bSDavid du Colombier free(d);
5189ef1f84bSDavid du Colombier
5199ef1f84bSDavid du Colombier return n;
5209ef1f84bSDavid du Colombier }
5219ef1f84bSDavid du Colombier
5229ef1f84bSDavid du Colombier
5239ef1f84bSDavid du Colombier static long
procoffset(long offset,char * va,int * np)5249ef1f84bSDavid du Colombier procoffset(long offset, char *va, int *np)
5259ef1f84bSDavid du Colombier {
5269ef1f84bSDavid du Colombier if(offset > 0) {
5279ef1f84bSDavid du Colombier offset -= *np;
5289ef1f84bSDavid du Colombier if(offset < 0) {
5299ef1f84bSDavid du Colombier memmove(va, va+*np+offset, -offset);
5309ef1f84bSDavid du Colombier *np = -offset;
5319ef1f84bSDavid du Colombier }
5329ef1f84bSDavid du Colombier else
5339ef1f84bSDavid du Colombier *np = 0;
5349ef1f84bSDavid du Colombier }
5359ef1f84bSDavid du Colombier return offset;
5369ef1f84bSDavid du Colombier }
5379ef1f84bSDavid du Colombier
5389ef1f84bSDavid du Colombier static int
procqidwidth(Chan * c)5399ef1f84bSDavid du Colombier procqidwidth(Chan *c)
5409ef1f84bSDavid du Colombier {
5419ef1f84bSDavid du Colombier char buf[32];
5429ef1f84bSDavid du Colombier
543406c76faSDavid du Colombier return snprint(buf, sizeof buf, "%lud", c->qid.vers);
5449ef1f84bSDavid du Colombier }
5459ef1f84bSDavid du Colombier
5469ef1f84bSDavid du Colombier int
procfdprint(Chan * c,int fd,int w,char * s,int ns)5479ef1f84bSDavid du Colombier procfdprint(Chan *c, int fd, int w, char *s, int ns)
5489ef1f84bSDavid du Colombier {
5499ef1f84bSDavid du Colombier int n;
5509ef1f84bSDavid du Colombier
5519ef1f84bSDavid du Colombier if(w == 0)
5529ef1f84bSDavid du Colombier w = procqidwidth(c);
5539ef1f84bSDavid du Colombier n = snprint(s, ns, "%3d %.2s %C %4ud (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
5549ef1f84bSDavid du Colombier fd,
5559ef1f84bSDavid du Colombier &"r w rw"[(c->mode&3)<<1],
5569ef1f84bSDavid du Colombier c->dev->dc, c->devno,
5579ef1f84bSDavid du Colombier c->qid.path, w, c->qid.vers, c->qid.type,
5589ef1f84bSDavid du Colombier c->iounit, c->offset, c->path->s);
5599ef1f84bSDavid du Colombier return n;
5609ef1f84bSDavid du Colombier }
5619ef1f84bSDavid du Colombier
5629ef1f84bSDavid du Colombier static int
procfds(Proc * p,char * va,int count,long offset)5639ef1f84bSDavid du Colombier procfds(Proc *p, char *va, int count, long offset)
5649ef1f84bSDavid du Colombier {
5659ef1f84bSDavid du Colombier Fgrp *f;
5669ef1f84bSDavid du Colombier Chan *c;
5679ef1f84bSDavid du Colombier char buf[256];
5689ef1f84bSDavid du Colombier int n, i, w, ww;
5699ef1f84bSDavid du Colombier char *a;
5709ef1f84bSDavid du Colombier
5719ef1f84bSDavid du Colombier /* print to buf to avoid holding fgrp lock while writing to user space */
5729ef1f84bSDavid du Colombier if(count > sizeof buf)
5739ef1f84bSDavid du Colombier count = sizeof buf;
5749ef1f84bSDavid du Colombier a = buf;
5759ef1f84bSDavid du Colombier
5769ef1f84bSDavid du Colombier qlock(&p->debug);
5779ef1f84bSDavid du Colombier f = p->fgrp;
5789ef1f84bSDavid du Colombier if(f == nil){
5799ef1f84bSDavid du Colombier qunlock(&p->debug);
5809ef1f84bSDavid du Colombier return 0;
5819ef1f84bSDavid du Colombier }
5829ef1f84bSDavid du Colombier lock(f);
5839ef1f84bSDavid du Colombier if(waserror()){
5849ef1f84bSDavid du Colombier unlock(f);
5859ef1f84bSDavid du Colombier qunlock(&p->debug);
5869ef1f84bSDavid du Colombier nexterror();
5879ef1f84bSDavid du Colombier }
5889ef1f84bSDavid du Colombier
5899ef1f84bSDavid du Colombier n = readstr(0, a, count, p->dot->path->s);
5909ef1f84bSDavid du Colombier n += snprint(a+n, count-n, "\n");
5919ef1f84bSDavid du Colombier offset = procoffset(offset, a, &n);
5929ef1f84bSDavid du Colombier /* compute width of qid.path */
5939ef1f84bSDavid du Colombier w = 0;
5949ef1f84bSDavid du Colombier for(i = 0; i <= f->maxfd; i++) {
5959ef1f84bSDavid du Colombier c = f->fd[i];
5969ef1f84bSDavid du Colombier if(c == nil)
5979ef1f84bSDavid du Colombier continue;
5989ef1f84bSDavid du Colombier ww = procqidwidth(c);
5999ef1f84bSDavid du Colombier if(ww > w)
6009ef1f84bSDavid du Colombier w = ww;
6019ef1f84bSDavid du Colombier }
6029ef1f84bSDavid du Colombier for(i = 0; i <= f->maxfd; i++) {
6039ef1f84bSDavid du Colombier c = f->fd[i];
6049ef1f84bSDavid du Colombier if(c == nil)
6059ef1f84bSDavid du Colombier continue;
6069ef1f84bSDavid du Colombier n += procfdprint(c, i, w, a+n, count-n);
6079ef1f84bSDavid du Colombier offset = procoffset(offset, a, &n);
6089ef1f84bSDavid du Colombier }
6099ef1f84bSDavid du Colombier poperror();
6109ef1f84bSDavid du Colombier unlock(f);
6119ef1f84bSDavid du Colombier qunlock(&p->debug);
6129ef1f84bSDavid du Colombier
6139ef1f84bSDavid du Colombier /* copy result to user space, now that locks are released */
6149ef1f84bSDavid du Colombier memmove(va, buf, n);
6159ef1f84bSDavid du Colombier
6169ef1f84bSDavid du Colombier return n;
6179ef1f84bSDavid du Colombier }
6189ef1f84bSDavid du Colombier
6199ef1f84bSDavid du Colombier static void
procclose(Chan * c)6209ef1f84bSDavid du Colombier procclose(Chan * c)
6219ef1f84bSDavid du Colombier {
6229ef1f84bSDavid du Colombier if(QID(c->qid) == Qtrace){
6239ef1f84bSDavid du Colombier lock(&tlock);
6249ef1f84bSDavid du Colombier if(topens > 0)
6259ef1f84bSDavid du Colombier topens--;
6269ef1f84bSDavid du Colombier if(topens == 0)
6279ef1f84bSDavid du Colombier proctrace = nil;
6289ef1f84bSDavid du Colombier unlock(&tlock);
6299ef1f84bSDavid du Colombier }
6309ef1f84bSDavid du Colombier if(QID(c->qid) == Qns && c->aux != 0)
6319ef1f84bSDavid du Colombier free(c->aux);
6329ef1f84bSDavid du Colombier }
6339ef1f84bSDavid du Colombier
6349ef1f84bSDavid du Colombier static void
int2flag(int flag,char * s)6359ef1f84bSDavid du Colombier int2flag(int flag, char *s)
6369ef1f84bSDavid du Colombier {
6379ef1f84bSDavid du Colombier if(flag == 0){
6389ef1f84bSDavid du Colombier *s = '\0';
6399ef1f84bSDavid du Colombier return;
6409ef1f84bSDavid du Colombier }
6419ef1f84bSDavid du Colombier *s++ = '-';
6429ef1f84bSDavid du Colombier if(flag & MAFTER)
6439ef1f84bSDavid du Colombier *s++ = 'a';
6449ef1f84bSDavid du Colombier if(flag & MBEFORE)
6459ef1f84bSDavid du Colombier *s++ = 'b';
6469ef1f84bSDavid du Colombier if(flag & MCREATE)
6479ef1f84bSDavid du Colombier *s++ = 'c';
6489ef1f84bSDavid du Colombier if(flag & MCACHE)
6499ef1f84bSDavid du Colombier *s++ = 'C';
6509ef1f84bSDavid du Colombier *s = '\0';
6519ef1f84bSDavid du Colombier }
6529ef1f84bSDavid du Colombier
6539ef1f84bSDavid du Colombier static int
procargs(Proc * p,char * buf,int nbuf)6549ef1f84bSDavid du Colombier procargs(Proc *p, char *buf, int nbuf)
6559ef1f84bSDavid du Colombier {
6569ef1f84bSDavid du Colombier int j, k, m;
6579ef1f84bSDavid du Colombier char *a;
6589ef1f84bSDavid du Colombier int n;
6599ef1f84bSDavid du Colombier
6609ef1f84bSDavid du Colombier a = p->args;
6619ef1f84bSDavid du Colombier if(p->setargs){
6629ef1f84bSDavid du Colombier snprint(buf, nbuf, "%s [%s]", p->text, p->args);
6639ef1f84bSDavid du Colombier return strlen(buf);
6649ef1f84bSDavid du Colombier }
6659ef1f84bSDavid du Colombier n = p->nargs;
6669ef1f84bSDavid du Colombier for(j = 0; j < nbuf - 1; j += m){
6679ef1f84bSDavid du Colombier if(n <= 0)
6689ef1f84bSDavid du Colombier break;
6699ef1f84bSDavid du Colombier if(j != 0)
6709ef1f84bSDavid du Colombier buf[j++] = ' ';
6719ef1f84bSDavid du Colombier m = snprint(buf+j, nbuf-j, "%q", a);
6729ef1f84bSDavid du Colombier k = strlen(a) + 1;
6739ef1f84bSDavid du Colombier a += k;
6749ef1f84bSDavid du Colombier n -= k;
6759ef1f84bSDavid du Colombier }
6769ef1f84bSDavid du Colombier return j;
6779ef1f84bSDavid du Colombier }
6789ef1f84bSDavid du Colombier
6799ef1f84bSDavid du Colombier static int
eventsavailable(void *)6809ef1f84bSDavid du Colombier eventsavailable(void *)
6819ef1f84bSDavid du Colombier {
6829ef1f84bSDavid du Colombier return tproduced > tconsumed;
6839ef1f84bSDavid du Colombier }
6849ef1f84bSDavid du Colombier
6859ef1f84bSDavid du Colombier static long
procread(Chan * c,void * va,long n,vlong off)6869ef1f84bSDavid du Colombier procread(Chan *c, void *va, long n, vlong off)
6879ef1f84bSDavid du Colombier {
6889ef1f84bSDavid du Colombier Proc *p;
6899ef1f84bSDavid du Colombier long l, r;
6909ef1f84bSDavid du Colombier Waitq *wq;
6919ef1f84bSDavid du Colombier Ureg kur;
6929ef1f84bSDavid du Colombier uchar *rptr;
6939ef1f84bSDavid du Colombier Asm *asm;
6949ef1f84bSDavid du Colombier Mntwalk *mw;
6959ef1f84bSDavid du Colombier Segment *sg, *s;
6969ef1f84bSDavid du Colombier int i, j, navail, ne, pid, rsize;
6979ef1f84bSDavid du Colombier char flag[10], *sps, *srv, statbuf[NSEG*64];
6989ef1f84bSDavid du Colombier uintptr offset, klimit;
6999ef1f84bSDavid du Colombier uvlong u;
7009ef1f84bSDavid du Colombier
7019ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
7029ef1f84bSDavid du Colombier return devdirread(c, va, n, 0, 0, procgen);
7039ef1f84bSDavid du Colombier
7049ef1f84bSDavid du Colombier offset = off;
7059ef1f84bSDavid du Colombier
7069ef1f84bSDavid du Colombier if(QID(c->qid) == Qtrace){
7079ef1f84bSDavid du Colombier if(!eventsavailable(nil))
7089ef1f84bSDavid du Colombier return 0;
7099ef1f84bSDavid du Colombier
7109ef1f84bSDavid du Colombier rptr = va;
7119ef1f84bSDavid du Colombier navail = tproduced - tconsumed;
7129ef1f84bSDavid du Colombier if(navail > n / sizeof(Traceevent))
7139ef1f84bSDavid du Colombier navail = n / sizeof(Traceevent);
7149ef1f84bSDavid du Colombier while(navail > 0) {
7159ef1f84bSDavid du Colombier if((tconsumed & Emask) + navail > Nevents)
7169ef1f84bSDavid du Colombier ne = Nevents - (tconsumed & Emask);
7179ef1f84bSDavid du Colombier else
7189ef1f84bSDavid du Colombier ne = navail;
7199ef1f84bSDavid du Colombier i = ne * sizeof(Traceevent);
7209ef1f84bSDavid du Colombier memmove(rptr, &tevents[tconsumed & Emask], i);
7219ef1f84bSDavid du Colombier
7229ef1f84bSDavid du Colombier tconsumed += ne;
7239ef1f84bSDavid du Colombier rptr += i;
7249ef1f84bSDavid du Colombier navail -= ne;
7259ef1f84bSDavid du Colombier }
7269ef1f84bSDavid du Colombier return rptr - (uchar*)va;
7279ef1f84bSDavid du Colombier }
7289ef1f84bSDavid du Colombier
7299ef1f84bSDavid du Colombier if((p = psincref(SLOT(c->qid))) == nil)
7309ef1f84bSDavid du Colombier error(Eprocdied);
7319ef1f84bSDavid du Colombier if(p->pid != PID(c->qid)){
7329ef1f84bSDavid du Colombier psdecref(p);
7339ef1f84bSDavid du Colombier error(Eprocdied);
7349ef1f84bSDavid du Colombier }
7359ef1f84bSDavid du Colombier
7369ef1f84bSDavid du Colombier switch(QID(c->qid)){
7379ef1f84bSDavid du Colombier default:
7389ef1f84bSDavid du Colombier psdecref(p);
7399ef1f84bSDavid du Colombier break;
7409ef1f84bSDavid du Colombier case Qargs:
7419ef1f84bSDavid du Colombier qlock(&p->debug);
7429ef1f84bSDavid du Colombier j = procargs(p, up->genbuf, sizeof up->genbuf);
7439ef1f84bSDavid du Colombier qunlock(&p->debug);
7449ef1f84bSDavid du Colombier psdecref(p);
7459ef1f84bSDavid du Colombier if(offset >= j)
7469ef1f84bSDavid du Colombier return 0;
7479ef1f84bSDavid du Colombier if(offset+n > j)
7489ef1f84bSDavid du Colombier n = j-offset;
7499ef1f84bSDavid du Colombier memmove(va, &up->genbuf[offset], n);
7509ef1f84bSDavid du Colombier return n;
7519ef1f84bSDavid du Colombier
7529ef1f84bSDavid du Colombier case Qsyscall:
7539ef1f84bSDavid du Colombier if(p->syscalltrace == nil)
7549ef1f84bSDavid du Colombier return 0;
7559ef1f84bSDavid du Colombier return readstr(offset, va, n, p->syscalltrace);
7569ef1f84bSDavid du Colombier
7579ef1f84bSDavid du Colombier case Qmem:
758fe56f827SDavid du Colombier if(!iskaddr(offset)
7599ef1f84bSDavid du Colombier || (offset >= USTKTOP-USTKSIZE && offset < USTKTOP)){
7609ef1f84bSDavid du Colombier r = procctlmemio(p, offset, n, va, 1);
7619ef1f84bSDavid du Colombier psdecref(p);
7629ef1f84bSDavid du Colombier return r;
7639ef1f84bSDavid du Colombier }
7649ef1f84bSDavid du Colombier
7659ef1f84bSDavid du Colombier if(!iseve()){
7669ef1f84bSDavid du Colombier psdecref(p);
7679ef1f84bSDavid du Colombier error(Eperm);
7689ef1f84bSDavid du Colombier }
7699ef1f84bSDavid du Colombier
7709ef1f84bSDavid du Colombier /* validate kernel addresses */
7719ef1f84bSDavid du Colombier if(offset < PTR2UINT(end)) {
7729ef1f84bSDavid du Colombier if(offset+n > PTR2UINT(end))
7739ef1f84bSDavid du Colombier n = PTR2UINT(end) - offset;
7749ef1f84bSDavid du Colombier memmove(va, UINT2PTR(offset), n);
7759ef1f84bSDavid du Colombier psdecref(p);
7769ef1f84bSDavid du Colombier return n;
7779ef1f84bSDavid du Colombier }
7789ef1f84bSDavid du Colombier for(asm = asmlist; asm != nil; asm = asm->next){
7799ef1f84bSDavid du Colombier if(asm->kbase == 0)
7809ef1f84bSDavid du Colombier continue;
7819ef1f84bSDavid du Colombier klimit = asm->kbase + (asm->limit - asm->base);
7829ef1f84bSDavid du Colombier
7839ef1f84bSDavid du Colombier /* klimit-1 because klimit might be zero!; hmmm not now but... */
7849ef1f84bSDavid du Colombier if(asm->kbase <= offset && offset <= klimit-1){
7859ef1f84bSDavid du Colombier if(offset+n >= klimit-1)
7869ef1f84bSDavid du Colombier n = klimit - offset;
7879ef1f84bSDavid du Colombier memmove(va, UINT2PTR(offset), n);
7889ef1f84bSDavid du Colombier psdecref(p);
7899ef1f84bSDavid du Colombier return n;
7909ef1f84bSDavid du Colombier }
7919ef1f84bSDavid du Colombier }
7929ef1f84bSDavid du Colombier psdecref(p);
7939ef1f84bSDavid du Colombier error(Ebadarg);
7949ef1f84bSDavid du Colombier
7959ef1f84bSDavid du Colombier case Qprofile:
7969ef1f84bSDavid du Colombier s = p->seg[TSEG];
7979ef1f84bSDavid du Colombier if(s == 0 || s->profile == 0)
7989ef1f84bSDavid du Colombier error("profile is off");
7999ef1f84bSDavid du Colombier i = (s->top-s->base)>>LRESPROF;
8009ef1f84bSDavid du Colombier i *= sizeof(*s->profile);
8019ef1f84bSDavid du Colombier if(offset >= i){
8029ef1f84bSDavid du Colombier psdecref(p);
8039ef1f84bSDavid du Colombier return 0;
8049ef1f84bSDavid du Colombier }
8059ef1f84bSDavid du Colombier if(offset+n > i)
8069ef1f84bSDavid du Colombier n = i - offset;
8079ef1f84bSDavid du Colombier memmove(va, ((char*)s->profile)+offset, n);
8089ef1f84bSDavid du Colombier psdecref(p);
8099ef1f84bSDavid du Colombier return n;
8109ef1f84bSDavid du Colombier
8119ef1f84bSDavid du Colombier case Qnote:
8129ef1f84bSDavid du Colombier qlock(&p->debug);
8139ef1f84bSDavid du Colombier if(waserror()){
8149ef1f84bSDavid du Colombier qunlock(&p->debug);
8159ef1f84bSDavid du Colombier psdecref(p);
8169ef1f84bSDavid du Colombier nexterror();
8179ef1f84bSDavid du Colombier }
8189ef1f84bSDavid du Colombier if(p->pid != PID(c->qid))
8199ef1f84bSDavid du Colombier error(Eprocdied);
8209ef1f84bSDavid du Colombier if(n < 1) /* must accept at least the '\0' */
8219ef1f84bSDavid du Colombier error(Etoosmall);
8229ef1f84bSDavid du Colombier if(p->nnote == 0)
8239ef1f84bSDavid du Colombier n = 0;
8249ef1f84bSDavid du Colombier else {
8259ef1f84bSDavid du Colombier i = strlen(p->note[0].msg) + 1;
8269ef1f84bSDavid du Colombier if(i > n)
8279ef1f84bSDavid du Colombier i = n;
8289ef1f84bSDavid du Colombier rptr = va;
8299ef1f84bSDavid du Colombier memmove(rptr, p->note[0].msg, i);
8309ef1f84bSDavid du Colombier rptr[i-1] = '\0';
8319ef1f84bSDavid du Colombier p->nnote--;
8329ef1f84bSDavid du Colombier memmove(p->note, p->note+1, p->nnote*sizeof(Note));
8339ef1f84bSDavid du Colombier n = i;
8349ef1f84bSDavid du Colombier }
8359ef1f84bSDavid du Colombier if(p->nnote == 0)
8369ef1f84bSDavid du Colombier p->notepending = 0;
8379ef1f84bSDavid du Colombier poperror();
8389ef1f84bSDavid du Colombier qunlock(&p->debug);
8399ef1f84bSDavid du Colombier psdecref(p);
8409ef1f84bSDavid du Colombier return n;
8419ef1f84bSDavid du Colombier
8429ef1f84bSDavid du Colombier case Qproc:
8439ef1f84bSDavid du Colombier if(offset >= sizeof(Proc)){
8449ef1f84bSDavid du Colombier psdecref(p);
8459ef1f84bSDavid du Colombier return 0;
8469ef1f84bSDavid du Colombier }
8479ef1f84bSDavid du Colombier if(offset+n > sizeof(Proc))
8489ef1f84bSDavid du Colombier n = sizeof(Proc) - offset;
8499ef1f84bSDavid du Colombier memmove(va, ((char*)p)+offset, n);
8509ef1f84bSDavid du Colombier psdecref(p);
8519ef1f84bSDavid du Colombier return n;
8529ef1f84bSDavid du Colombier
8539ef1f84bSDavid du Colombier case Qregs:
8549ef1f84bSDavid du Colombier rptr = (uchar*)p->dbgreg;
8559ef1f84bSDavid du Colombier rsize = sizeof(Ureg);
8569ef1f84bSDavid du Colombier regread:
8579ef1f84bSDavid du Colombier if(rptr == 0){
8589ef1f84bSDavid du Colombier psdecref(p);
8599ef1f84bSDavid du Colombier error(Enoreg);
8609ef1f84bSDavid du Colombier }
8619ef1f84bSDavid du Colombier if(offset >= rsize){
8629ef1f84bSDavid du Colombier psdecref(p);
8639ef1f84bSDavid du Colombier return 0;
8649ef1f84bSDavid du Colombier }
8659ef1f84bSDavid du Colombier if(offset+n > rsize)
8669ef1f84bSDavid du Colombier n = rsize - offset;
8679ef1f84bSDavid du Colombier memmove(va, rptr+offset, n);
8689ef1f84bSDavid du Colombier psdecref(p);
8699ef1f84bSDavid du Colombier return n;
8709ef1f84bSDavid du Colombier
8719ef1f84bSDavid du Colombier case Qkregs:
8729ef1f84bSDavid du Colombier memset(&kur, 0, sizeof(Ureg));
8739ef1f84bSDavid du Colombier setkernur(&kur, p);
8749ef1f84bSDavid du Colombier rptr = (uchar*)&kur;
8759ef1f84bSDavid du Colombier rsize = sizeof(Ureg);
8769ef1f84bSDavid du Colombier goto regread;
8779ef1f84bSDavid du Colombier
8789ef1f84bSDavid du Colombier case Qfpregs:
8799ef1f84bSDavid du Colombier r = fpudevprocio(p, va, n, offset, 0);
8809ef1f84bSDavid du Colombier psdecref(p);
8819ef1f84bSDavid du Colombier return r;
8829ef1f84bSDavid du Colombier
8839ef1f84bSDavid du Colombier case Qstatus:
8849ef1f84bSDavid du Colombier if(offset >= STATSIZE){
8859ef1f84bSDavid du Colombier psdecref(p);
8869ef1f84bSDavid du Colombier return 0;
8879ef1f84bSDavid du Colombier }
8889ef1f84bSDavid du Colombier if(offset+n > STATSIZE)
8899ef1f84bSDavid du Colombier n = STATSIZE - offset;
8909ef1f84bSDavid du Colombier
8919ef1f84bSDavid du Colombier sps = p->psstate;
8929ef1f84bSDavid du Colombier if(sps == 0)
8939ef1f84bSDavid du Colombier sps = statename[p->state];
8949ef1f84bSDavid du Colombier memset(statbuf, ' ', sizeof statbuf);
8959ef1f84bSDavid du Colombier sprint(statbuf, "%-*.*s%-*.*s%-12.11s",
8969ef1f84bSDavid du Colombier KNAMELEN, KNAMELEN-1, p->text,
8979ef1f84bSDavid du Colombier KNAMELEN, KNAMELEN-1, p->user,
8989ef1f84bSDavid du Colombier sps);
8999ef1f84bSDavid du Colombier j = 2*KNAMELEN + 12;
9009ef1f84bSDavid du Colombier
9019ef1f84bSDavid du Colombier for(i = 0; i < 6; i++) {
9029ef1f84bSDavid du Colombier l = p->time[i];
9039ef1f84bSDavid du Colombier if(i == TReal)
9049ef1f84bSDavid du Colombier l = sys->ticks - l;
9059ef1f84bSDavid du Colombier l = TK2MS(l);
9069ef1f84bSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
9079ef1f84bSDavid du Colombier }
9089ef1f84bSDavid du Colombier /* ignore stack, which is mostly non-existent */
9099ef1f84bSDavid du Colombier u = 0;
9109ef1f84bSDavid du Colombier for(i=1; i<NSEG; i++){
9119ef1f84bSDavid du Colombier s = p->seg[i];
9129ef1f84bSDavid du Colombier if(s)
9139ef1f84bSDavid du Colombier u += s->top - s->base;
9149ef1f84bSDavid du Colombier }
9159ef1f84bSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, u>>10, NUMSIZE);
9169ef1f84bSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
9179ef1f84bSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
9189ef1f84bSDavid du Colombier memmove(va, statbuf+offset, n);
9199ef1f84bSDavid du Colombier psdecref(p);
9209ef1f84bSDavid du Colombier return n;
9219ef1f84bSDavid du Colombier
9229ef1f84bSDavid du Colombier case Qsegment:
9239ef1f84bSDavid du Colombier j = 0;
9249ef1f84bSDavid du Colombier for(i = 0; i < NSEG; i++) {
9259ef1f84bSDavid du Colombier sg = p->seg[i];
9269ef1f84bSDavid du Colombier if(sg == 0)
9279ef1f84bSDavid du Colombier continue;
928406c76faSDavid du Colombier j += snprint(statbuf+j, sizeof statbuf - j,
929406c76faSDavid du Colombier "%-6s %c%c %p %p %4d\n",
9309ef1f84bSDavid du Colombier sname[sg->type&SG_TYPE],
9319ef1f84bSDavid du Colombier sg->type&SG_RONLY ? 'R' : ' ',
9329ef1f84bSDavid du Colombier sg->profile ? 'P' : ' ',
9339ef1f84bSDavid du Colombier sg->base, sg->top, sg->ref);
9349ef1f84bSDavid du Colombier }
9359ef1f84bSDavid du Colombier psdecref(p);
9369ef1f84bSDavid du Colombier if(offset >= j)
9379ef1f84bSDavid du Colombier return 0;
9389ef1f84bSDavid du Colombier if(offset+n > j)
9399ef1f84bSDavid du Colombier n = j-offset;
9409ef1f84bSDavid du Colombier if(n == 0 && offset == 0)
9419ef1f84bSDavid du Colombier exhausted("segments");
9429ef1f84bSDavid du Colombier memmove(va, &statbuf[offset], n);
9439ef1f84bSDavid du Colombier return n;
9449ef1f84bSDavid du Colombier
9459ef1f84bSDavid du Colombier case Qwait:
9469ef1f84bSDavid du Colombier if(!canqlock(&p->qwaitr)){
9479ef1f84bSDavid du Colombier psdecref(p);
9489ef1f84bSDavid du Colombier error(Einuse);
9499ef1f84bSDavid du Colombier }
9509ef1f84bSDavid du Colombier
9519ef1f84bSDavid du Colombier if(waserror()) {
9529ef1f84bSDavid du Colombier qunlock(&p->qwaitr);
9539ef1f84bSDavid du Colombier psdecref(p);
9549ef1f84bSDavid du Colombier nexterror();
9559ef1f84bSDavid du Colombier }
9569ef1f84bSDavid du Colombier
9579ef1f84bSDavid du Colombier lock(&p->exl);
9589ef1f84bSDavid du Colombier if(up == p && p->nchild == 0 && p->waitq == 0) {
9599ef1f84bSDavid du Colombier unlock(&p->exl);
9609ef1f84bSDavid du Colombier error(Enochild);
9619ef1f84bSDavid du Colombier }
9629ef1f84bSDavid du Colombier pid = p->pid;
9639ef1f84bSDavid du Colombier while(p->waitq == 0) {
9649ef1f84bSDavid du Colombier unlock(&p->exl);
9659ef1f84bSDavid du Colombier sleep(&p->waitr, haswaitq, p);
9669ef1f84bSDavid du Colombier if(p->pid != pid)
9679ef1f84bSDavid du Colombier error(Eprocdied);
9689ef1f84bSDavid du Colombier lock(&p->exl);
9699ef1f84bSDavid du Colombier }
9709ef1f84bSDavid du Colombier wq = p->waitq;
9719ef1f84bSDavid du Colombier p->waitq = wq->next;
9729ef1f84bSDavid du Colombier p->nwait--;
9739ef1f84bSDavid du Colombier unlock(&p->exl);
9749ef1f84bSDavid du Colombier
9759ef1f84bSDavid du Colombier poperror();
9769ef1f84bSDavid du Colombier qunlock(&p->qwaitr);
9779ef1f84bSDavid du Colombier psdecref(p);
9789ef1f84bSDavid du Colombier n = snprint(va, n, "%d %lud %lud %lud %q",
9799ef1f84bSDavid du Colombier wq->w.pid,
9809ef1f84bSDavid du Colombier wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
9819ef1f84bSDavid du Colombier wq->w.msg);
9829ef1f84bSDavid du Colombier free(wq);
9839ef1f84bSDavid du Colombier return n;
9849ef1f84bSDavid du Colombier
9859ef1f84bSDavid du Colombier case Qns:
9869ef1f84bSDavid du Colombier qlock(&p->debug);
9879ef1f84bSDavid du Colombier if(waserror()){
9889ef1f84bSDavid du Colombier qunlock(&p->debug);
9899ef1f84bSDavid du Colombier psdecref(p);
9909ef1f84bSDavid du Colombier nexterror();
9919ef1f84bSDavid du Colombier }
9929ef1f84bSDavid du Colombier if(p->pgrp == nil || p->pid != PID(c->qid))
9939ef1f84bSDavid du Colombier error(Eprocdied);
9949ef1f84bSDavid du Colombier mw = c->aux;
995406c76faSDavid du Colombier if(mw == nil)
996406c76faSDavid du Colombier error(Enomem);
9979ef1f84bSDavid du Colombier if(mw->cddone){
9989ef1f84bSDavid du Colombier poperror();
9999ef1f84bSDavid du Colombier qunlock(&p->debug);
10009ef1f84bSDavid du Colombier psdecref(p);
10019ef1f84bSDavid du Colombier return 0;
10029ef1f84bSDavid du Colombier }
10039ef1f84bSDavid du Colombier mntscan(mw, p);
10049ef1f84bSDavid du Colombier if(mw->mh == 0){
10059ef1f84bSDavid du Colombier mw->cddone = 1;
10069ef1f84bSDavid du Colombier i = snprint(va, n, "cd %s\n", p->dot->path->s);
10079ef1f84bSDavid du Colombier poperror();
10089ef1f84bSDavid du Colombier qunlock(&p->debug);
10099ef1f84bSDavid du Colombier psdecref(p);
10109ef1f84bSDavid du Colombier return i;
10119ef1f84bSDavid du Colombier }
10129ef1f84bSDavid du Colombier int2flag(mw->cm->mflag, flag);
10139ef1f84bSDavid du Colombier if(strcmp(mw->cm->to->path->s, "#M") == 0){
10149ef1f84bSDavid du Colombier srv = srvname(mw->cm->to->mchan);
10159ef1f84bSDavid du Colombier i = snprint(va, n, "mount %s %s %s %s\n", flag,
10169ef1f84bSDavid du Colombier srv==nil? mw->cm->to->mchan->path->s : srv,
10179ef1f84bSDavid du Colombier mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
10189ef1f84bSDavid du Colombier free(srv);
10199ef1f84bSDavid du Colombier }else
10209ef1f84bSDavid du Colombier i = snprint(va, n, "bind %s %s %s\n", flag,
10219ef1f84bSDavid du Colombier mw->cm->to->path->s, mw->mh->from->path->s);
10229ef1f84bSDavid du Colombier poperror();
10239ef1f84bSDavid du Colombier qunlock(&p->debug);
10249ef1f84bSDavid du Colombier psdecref(p);
10259ef1f84bSDavid du Colombier return i;
10269ef1f84bSDavid du Colombier
10279ef1f84bSDavid du Colombier case Qnoteid:
10289ef1f84bSDavid du Colombier r = readnum(offset, va, n, p->noteid, NUMSIZE);
10299ef1f84bSDavid du Colombier psdecref(p);
10309ef1f84bSDavid du Colombier return r;
10319ef1f84bSDavid du Colombier case Qfd:
10329ef1f84bSDavid du Colombier r = procfds(p, va, n, offset);
10339ef1f84bSDavid du Colombier psdecref(p);
10349ef1f84bSDavid du Colombier return r;
10359ef1f84bSDavid du Colombier }
10369ef1f84bSDavid du Colombier error(Egreg);
10379ef1f84bSDavid du Colombier return 0; /* not reached */
10389ef1f84bSDavid du Colombier }
10399ef1f84bSDavid du Colombier
10409ef1f84bSDavid du Colombier static void
mntscan(Mntwalk * mw,Proc * p)10419ef1f84bSDavid du Colombier mntscan(Mntwalk *mw, Proc *p)
10429ef1f84bSDavid du Colombier {
10439ef1f84bSDavid du Colombier Pgrp *pg;
10449ef1f84bSDavid du Colombier Mount *t;
10459ef1f84bSDavid du Colombier Mhead *f;
10469ef1f84bSDavid du Colombier int best, i, last, nxt;
10479ef1f84bSDavid du Colombier
10489ef1f84bSDavid du Colombier pg = p->pgrp;
10499ef1f84bSDavid du Colombier rlock(&pg->ns);
10509ef1f84bSDavid du Colombier
10519ef1f84bSDavid du Colombier nxt = 0;
10529ef1f84bSDavid du Colombier best = (int)(~0U>>1); /* largest 2's complement int */
10539ef1f84bSDavid du Colombier
10549ef1f84bSDavid du Colombier last = 0;
10559ef1f84bSDavid du Colombier if(mw->mh)
10569ef1f84bSDavid du Colombier last = mw->cm->mountid;
10579ef1f84bSDavid du Colombier
10589ef1f84bSDavid du Colombier for(i = 0; i < MNTHASH; i++) {
10599ef1f84bSDavid du Colombier for(f = pg->mnthash[i]; f; f = f->hash) {
10609ef1f84bSDavid du Colombier for(t = f->mount; t; t = t->next) {
10619ef1f84bSDavid du Colombier if(mw->mh == 0 ||
10629ef1f84bSDavid du Colombier (t->mountid > last && t->mountid < best)) {
10639ef1f84bSDavid du Colombier mw->cm = t;
10649ef1f84bSDavid du Colombier mw->mh = f;
10659ef1f84bSDavid du Colombier best = mw->cm->mountid;
10669ef1f84bSDavid du Colombier nxt = 1;
10679ef1f84bSDavid du Colombier }
10689ef1f84bSDavid du Colombier }
10699ef1f84bSDavid du Colombier }
10709ef1f84bSDavid du Colombier }
10719ef1f84bSDavid du Colombier if(nxt == 0)
10729ef1f84bSDavid du Colombier mw->mh = 0;
10739ef1f84bSDavid du Colombier
10749ef1f84bSDavid du Colombier runlock(&pg->ns);
10759ef1f84bSDavid du Colombier }
10769ef1f84bSDavid du Colombier
10779ef1f84bSDavid du Colombier static long
procwrite(Chan * c,void * va,long n,vlong off)10789ef1f84bSDavid du Colombier procwrite(Chan *c, void *va, long n, vlong off)
10799ef1f84bSDavid du Colombier {
10809ef1f84bSDavid du Colombier Proc *p, *t;
10819ef1f84bSDavid du Colombier int i, id, l;
10829ef1f84bSDavid du Colombier char *args, buf[ERRMAX];
10839ef1f84bSDavid du Colombier uintptr offset;
10849ef1f84bSDavid du Colombier
10859ef1f84bSDavid du Colombier if(c->qid.type & QTDIR)
10869ef1f84bSDavid du Colombier error(Eisdir);
10879ef1f84bSDavid du Colombier
10889ef1f84bSDavid du Colombier /* Use the remembered noteid in the channel rather
10899ef1f84bSDavid du Colombier * than the process pgrpid
10909ef1f84bSDavid du Colombier */
10919ef1f84bSDavid du Colombier if(QID(c->qid) == Qnotepg) {
10929ef1f84bSDavid du Colombier pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
10939ef1f84bSDavid du Colombier return n;
10949ef1f84bSDavid du Colombier }
10959ef1f84bSDavid du Colombier
10969ef1f84bSDavid du Colombier if((p = psincref(SLOT(c->qid))) == nil)
10979ef1f84bSDavid du Colombier error(Eprocdied);
10989ef1f84bSDavid du Colombier
10999ef1f84bSDavid du Colombier qlock(&p->debug);
11009ef1f84bSDavid du Colombier if(waserror()){
11019ef1f84bSDavid du Colombier qunlock(&p->debug);
11029ef1f84bSDavid du Colombier psdecref(p);
11039ef1f84bSDavid du Colombier nexterror();
11049ef1f84bSDavid du Colombier }
11059ef1f84bSDavid du Colombier if(p->pid != PID(c->qid))
11069ef1f84bSDavid du Colombier error(Eprocdied);
11079ef1f84bSDavid du Colombier
11089ef1f84bSDavid du Colombier offset = off;
11099ef1f84bSDavid du Colombier
11109ef1f84bSDavid du Colombier switch(QID(c->qid)){
11119ef1f84bSDavid du Colombier case Qargs:
11129ef1f84bSDavid du Colombier if(n == 0)
11139ef1f84bSDavid du Colombier error(Eshort);
11149ef1f84bSDavid du Colombier if(n >= ERRMAX)
11159ef1f84bSDavid du Colombier error(Etoobig);
11169ef1f84bSDavid du Colombier memmove(buf, va, n);
11179ef1f84bSDavid du Colombier args = malloc(n+1);
11189ef1f84bSDavid du Colombier if(args == nil)
11199ef1f84bSDavid du Colombier error(Enomem);
11209ef1f84bSDavid du Colombier memmove(args, buf, n);
11219ef1f84bSDavid du Colombier l = n;
11229ef1f84bSDavid du Colombier if(args[l-1] != 0)
11239ef1f84bSDavid du Colombier args[l++] = 0;
11249ef1f84bSDavid du Colombier free(p->args);
11259ef1f84bSDavid du Colombier p->nargs = l;
11269ef1f84bSDavid du Colombier p->args = args;
11279ef1f84bSDavid du Colombier p->setargs = 1;
11289ef1f84bSDavid du Colombier break;
11299ef1f84bSDavid du Colombier
11309ef1f84bSDavid du Colombier case Qmem:
11319ef1f84bSDavid du Colombier if(p->state != Stopped)
11329ef1f84bSDavid du Colombier error(Ebadctl);
11339ef1f84bSDavid du Colombier
11349ef1f84bSDavid du Colombier n = procctlmemio(p, offset, n, va, 0);
11359ef1f84bSDavid du Colombier break;
11369ef1f84bSDavid du Colombier
11379ef1f84bSDavid du Colombier case Qregs:
11389ef1f84bSDavid du Colombier if(offset >= sizeof(Ureg))
11399ef1f84bSDavid du Colombier n = 0;
11409ef1f84bSDavid du Colombier else if(offset+n > sizeof(Ureg))
11419ef1f84bSDavid du Colombier n = sizeof(Ureg) - offset;
11429ef1f84bSDavid du Colombier if(p->dbgreg == 0)
11439ef1f84bSDavid du Colombier error(Enoreg);
11449ef1f84bSDavid du Colombier setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
11459ef1f84bSDavid du Colombier break;
11469ef1f84bSDavid du Colombier
11479ef1f84bSDavid du Colombier case Qfpregs:
11489ef1f84bSDavid du Colombier n = fpudevprocio(p, va, n, offset, 1);
11499ef1f84bSDavid du Colombier break;
11509ef1f84bSDavid du Colombier
11519ef1f84bSDavid du Colombier case Qctl:
11529ef1f84bSDavid du Colombier procctlreq(p, va, n);
11539ef1f84bSDavid du Colombier break;
11549ef1f84bSDavid du Colombier
11559ef1f84bSDavid du Colombier case Qnote:
11569ef1f84bSDavid du Colombier if(p->kp)
11579ef1f84bSDavid du Colombier error(Eperm);
11589ef1f84bSDavid du Colombier if(n >= ERRMAX-1)
11599ef1f84bSDavid du Colombier error(Etoobig);
11609ef1f84bSDavid du Colombier memmove(buf, va, n);
11619ef1f84bSDavid du Colombier buf[n] = 0;
11629ef1f84bSDavid du Colombier if(!postnote(p, 0, buf, NUser))
11639ef1f84bSDavid du Colombier error("note not posted");
11649ef1f84bSDavid du Colombier break;
11659ef1f84bSDavid du Colombier case Qnoteid:
11669ef1f84bSDavid du Colombier id = atoi(va);
11679ef1f84bSDavid du Colombier if(id == p->pid) {
11689ef1f84bSDavid du Colombier p->noteid = id;
11699ef1f84bSDavid du Colombier break;
11709ef1f84bSDavid du Colombier }
11719ef1f84bSDavid du Colombier for(i = 0; (t = psincref(i)) != nil; i++){
11729ef1f84bSDavid du Colombier if(t->state == Dead || t->noteid != id){
11739ef1f84bSDavid du Colombier psdecref(t);
11749ef1f84bSDavid du Colombier continue;
11759ef1f84bSDavid du Colombier }
11769ef1f84bSDavid du Colombier if(strcmp(p->user, t->user) != 0){
11779ef1f84bSDavid du Colombier psdecref(t);
11789ef1f84bSDavid du Colombier error(Eperm);
11799ef1f84bSDavid du Colombier }
11809ef1f84bSDavid du Colombier psdecref(t);
11819ef1f84bSDavid du Colombier p->noteid = id;
11829ef1f84bSDavid du Colombier break;
11839ef1f84bSDavid du Colombier }
11849ef1f84bSDavid du Colombier if(p->noteid != id)
11859ef1f84bSDavid du Colombier error(Ebadarg);
11869ef1f84bSDavid du Colombier break;
11879ef1f84bSDavid du Colombier default:
11889ef1f84bSDavid du Colombier poperror();
11899ef1f84bSDavid du Colombier qunlock(&p->debug);
11909ef1f84bSDavid du Colombier psdecref(p);
11919ef1f84bSDavid du Colombier pprint("unknown qid %#llux in procwrite\n", c->qid.path);
11929ef1f84bSDavid du Colombier error(Egreg);
11939ef1f84bSDavid du Colombier }
11949ef1f84bSDavid du Colombier poperror();
11959ef1f84bSDavid du Colombier qunlock(&p->debug);
11969ef1f84bSDavid du Colombier psdecref(p);
11979ef1f84bSDavid du Colombier return n;
11989ef1f84bSDavid du Colombier }
11999ef1f84bSDavid du Colombier
12009ef1f84bSDavid du Colombier Dev procdevtab = {
12019ef1f84bSDavid du Colombier 'p',
12029ef1f84bSDavid du Colombier "proc",
12039ef1f84bSDavid du Colombier
12049ef1f84bSDavid du Colombier devreset,
12059ef1f84bSDavid du Colombier procinit,
12069ef1f84bSDavid du Colombier devshutdown,
12079ef1f84bSDavid du Colombier procattach,
12089ef1f84bSDavid du Colombier procwalk,
12099ef1f84bSDavid du Colombier procstat,
12109ef1f84bSDavid du Colombier procopen,
12119ef1f84bSDavid du Colombier devcreate,
12129ef1f84bSDavid du Colombier procclose,
12139ef1f84bSDavid du Colombier procread,
12149ef1f84bSDavid du Colombier devbread,
12159ef1f84bSDavid du Colombier procwrite,
12169ef1f84bSDavid du Colombier devbwrite,
12179ef1f84bSDavid du Colombier devremove,
12189ef1f84bSDavid du Colombier procwstat,
12199ef1f84bSDavid du Colombier };
12209ef1f84bSDavid du Colombier
12219ef1f84bSDavid du Colombier static Chan*
proctext(Chan * c,Proc * p)12229ef1f84bSDavid du Colombier proctext(Chan *c, Proc *p)
12239ef1f84bSDavid du Colombier {
12249ef1f84bSDavid du Colombier Chan *tc;
12259ef1f84bSDavid du Colombier Image *i;
12269ef1f84bSDavid du Colombier Segment *s;
12279ef1f84bSDavid du Colombier
12289ef1f84bSDavid du Colombier s = p->seg[TSEG];
12299ef1f84bSDavid du Colombier if(s == 0)
12309ef1f84bSDavid du Colombier error(Enonexist);
12319ef1f84bSDavid du Colombier if(p->state==Dead)
12329ef1f84bSDavid du Colombier error(Eprocdied);
12339ef1f84bSDavid du Colombier
12349ef1f84bSDavid du Colombier lock(s);
12359ef1f84bSDavid du Colombier i = s->image;
12369ef1f84bSDavid du Colombier if(i == 0) {
12379ef1f84bSDavid du Colombier unlock(s);
12389ef1f84bSDavid du Colombier error(Eprocdied);
12399ef1f84bSDavid du Colombier }
12409ef1f84bSDavid du Colombier unlock(s);
12419ef1f84bSDavid du Colombier
12429ef1f84bSDavid du Colombier lock(i);
12439ef1f84bSDavid du Colombier if(waserror()) {
12449ef1f84bSDavid du Colombier unlock(i);
12459ef1f84bSDavid du Colombier nexterror();
12469ef1f84bSDavid du Colombier }
12479ef1f84bSDavid du Colombier
12489ef1f84bSDavid du Colombier tc = i->c;
12499ef1f84bSDavid du Colombier if(tc == 0)
12509ef1f84bSDavid du Colombier error(Eprocdied);
12519ef1f84bSDavid du Colombier
12529ef1f84bSDavid du Colombier if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
12539ef1f84bSDavid du Colombier cclose(tc);
12549ef1f84bSDavid du Colombier error(Eprocdied);
12559ef1f84bSDavid du Colombier }
12569ef1f84bSDavid du Colombier
1257406c76faSDavid du Colombier if(p->pid != PID(c->qid)){
1258406c76faSDavid du Colombier cclose(tc);
12599ef1f84bSDavid du Colombier error(Eprocdied);
1260406c76faSDavid du Colombier }
12619ef1f84bSDavid du Colombier
12629ef1f84bSDavid du Colombier poperror();
12639ef1f84bSDavid du Colombier unlock(i);
12649ef1f84bSDavid du Colombier
12659ef1f84bSDavid du Colombier return tc;
12669ef1f84bSDavid du Colombier }
12679ef1f84bSDavid du Colombier
12689ef1f84bSDavid du Colombier void
procstopwait(Proc * p,int ctl)12699ef1f84bSDavid du Colombier procstopwait(Proc *p, int ctl)
12709ef1f84bSDavid du Colombier {
12719ef1f84bSDavid du Colombier int pid;
12729ef1f84bSDavid du Colombier
12739ef1f84bSDavid du Colombier if(p->pdbg)
12749ef1f84bSDavid du Colombier error(Einuse);
12759ef1f84bSDavid du Colombier if(procstopped(p) || p->state == Broken)
12769ef1f84bSDavid du Colombier return;
12779ef1f84bSDavid du Colombier
12789ef1f84bSDavid du Colombier if(ctl != 0)
12799ef1f84bSDavid du Colombier p->procctl = ctl;
12809ef1f84bSDavid du Colombier p->pdbg = up;
12819ef1f84bSDavid du Colombier pid = p->pid;
12829ef1f84bSDavid du Colombier qunlock(&p->debug);
12839ef1f84bSDavid du Colombier up->psstate = "Stopwait";
12849ef1f84bSDavid du Colombier if(waserror()) {
12859ef1f84bSDavid du Colombier p->pdbg = 0;
12869ef1f84bSDavid du Colombier qlock(&p->debug);
12879ef1f84bSDavid du Colombier nexterror();
12889ef1f84bSDavid du Colombier }
12899ef1f84bSDavid du Colombier sleep(&up->sleep, procstopped, p);
12909ef1f84bSDavid du Colombier poperror();
12919ef1f84bSDavid du Colombier qlock(&p->debug);
12929ef1f84bSDavid du Colombier if(p->pid != pid)
12939ef1f84bSDavid du Colombier error(Eprocdied);
12949ef1f84bSDavid du Colombier }
12959ef1f84bSDavid du Colombier
12969ef1f84bSDavid du Colombier static void
procctlcloseone(Proc * p,Fgrp * f,int fd)12979ef1f84bSDavid du Colombier procctlcloseone(Proc *p, Fgrp *f, int fd)
12989ef1f84bSDavid du Colombier {
12999ef1f84bSDavid du Colombier Chan *c;
13009ef1f84bSDavid du Colombier
13019ef1f84bSDavid du Colombier c = f->fd[fd];
13029ef1f84bSDavid du Colombier if(c == nil)
13039ef1f84bSDavid du Colombier return;
13049ef1f84bSDavid du Colombier f->fd[fd] = nil;
13059ef1f84bSDavid du Colombier unlock(f);
13069ef1f84bSDavid du Colombier qunlock(&p->debug);
13079ef1f84bSDavid du Colombier cclose(c);
13089ef1f84bSDavid du Colombier qlock(&p->debug);
13099ef1f84bSDavid du Colombier lock(f);
13109ef1f84bSDavid du Colombier }
13119ef1f84bSDavid du Colombier
13129ef1f84bSDavid du Colombier void
procctlclosefiles(Proc * p,int all,int fd)13139ef1f84bSDavid du Colombier procctlclosefiles(Proc *p, int all, int fd)
13149ef1f84bSDavid du Colombier {
13159ef1f84bSDavid du Colombier int i;
13169ef1f84bSDavid du Colombier Fgrp *f;
13179ef1f84bSDavid du Colombier
13189ef1f84bSDavid du Colombier f = p->fgrp;
13199ef1f84bSDavid du Colombier if(f == nil)
13209ef1f84bSDavid du Colombier error(Eprocdied);
13219ef1f84bSDavid du Colombier
13229ef1f84bSDavid du Colombier lock(f);
13239ef1f84bSDavid du Colombier f->ref++;
13249ef1f84bSDavid du Colombier if(all)
13259ef1f84bSDavid du Colombier for(i = 0; i < f->maxfd; i++)
13269ef1f84bSDavid du Colombier procctlcloseone(p, f, i);
13279ef1f84bSDavid du Colombier else
13289ef1f84bSDavid du Colombier procctlcloseone(p, f, fd);
13299ef1f84bSDavid du Colombier unlock(f);
13309ef1f84bSDavid du Colombier closefgrp(f);
13319ef1f84bSDavid du Colombier }
13329ef1f84bSDavid du Colombier
13339ef1f84bSDavid du Colombier static char *
parsetime(vlong * rt,char * s)13349ef1f84bSDavid du Colombier parsetime(vlong *rt, char *s)
13359ef1f84bSDavid du Colombier {
13369ef1f84bSDavid du Colombier uvlong ticks;
13379ef1f84bSDavid du Colombier ulong l;
13389ef1f84bSDavid du Colombier char *e, *p;
13399ef1f84bSDavid du Colombier static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
13409ef1f84bSDavid du Colombier
13419ef1f84bSDavid du Colombier if (s == nil)
13429ef1f84bSDavid du Colombier return("missing value");
13439ef1f84bSDavid du Colombier ticks=strtoul(s, &e, 10);
13449ef1f84bSDavid du Colombier if (*e == '.'){
13459ef1f84bSDavid du Colombier p = e+1;
13469ef1f84bSDavid du Colombier l = strtoul(p, &e, 10);
13479ef1f84bSDavid du Colombier if(e-p > nelem(p10))
13489ef1f84bSDavid du Colombier return "too many digits after decimal point";
13499ef1f84bSDavid du Colombier if(e-p == 0)
13509ef1f84bSDavid du Colombier return "ill-formed number";
13519ef1f84bSDavid du Colombier l *= p10[e-p-1];
13529ef1f84bSDavid du Colombier }else
13539ef1f84bSDavid du Colombier l = 0;
13549ef1f84bSDavid du Colombier if (*e == '\0' || strcmp(e, "s") == 0){
13559ef1f84bSDavid du Colombier ticks = 1000000000 * ticks + l;
13569ef1f84bSDavid du Colombier }else if (strcmp(e, "ms") == 0){
13579ef1f84bSDavid du Colombier ticks = 1000000 * ticks + l/1000;
13589ef1f84bSDavid du Colombier }else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0){
13599ef1f84bSDavid du Colombier ticks = 1000 * ticks + l/1000000;
13609ef1f84bSDavid du Colombier }else if (strcmp(e, "ns") != 0)
13619ef1f84bSDavid du Colombier return "unrecognized unit";
13629ef1f84bSDavid du Colombier *rt = ticks;
13639ef1f84bSDavid du Colombier return nil;
13649ef1f84bSDavid du Colombier }
13659ef1f84bSDavid du Colombier
13669ef1f84bSDavid du Colombier static void
procctlreq(Proc * p,char * va,int n)13679ef1f84bSDavid du Colombier procctlreq(Proc *p, char *va, int n)
13689ef1f84bSDavid du Colombier {
13699ef1f84bSDavid du Colombier Segment *s;
13709ef1f84bSDavid du Colombier int npc, pri;
13719ef1f84bSDavid du Colombier Cmdbuf *cb;
13729ef1f84bSDavid du Colombier Cmdtab *ct;
13739ef1f84bSDavid du Colombier vlong time;
13749ef1f84bSDavid du Colombier char *e;
1375d46407a3SDavid du Colombier void (*pt)(Proc*, int, vlong, vlong);
13769ef1f84bSDavid du Colombier
13779ef1f84bSDavid du Colombier if(p->kp) /* no ctl requests to kprocs */
13789ef1f84bSDavid du Colombier error(Eperm);
13799ef1f84bSDavid du Colombier
13809ef1f84bSDavid du Colombier cb = parsecmd(va, n);
13819ef1f84bSDavid du Colombier if(waserror()){
13829ef1f84bSDavid du Colombier free(cb);
13839ef1f84bSDavid du Colombier nexterror();
13849ef1f84bSDavid du Colombier }
13859ef1f84bSDavid du Colombier
13869ef1f84bSDavid du Colombier ct = lookupcmd(cb, proccmd, nelem(proccmd));
13879ef1f84bSDavid du Colombier
13889ef1f84bSDavid du Colombier switch(ct->index){
13899ef1f84bSDavid du Colombier case CMclose:
13909ef1f84bSDavid du Colombier procctlclosefiles(p, 0, atoi(cb->f[1]));
13919ef1f84bSDavid du Colombier break;
13929ef1f84bSDavid du Colombier case CMclosefiles:
13939ef1f84bSDavid du Colombier procctlclosefiles(p, 1, 0);
13949ef1f84bSDavid du Colombier break;
13959ef1f84bSDavid du Colombier case CMhang:
13969ef1f84bSDavid du Colombier p->hang = 1;
13979ef1f84bSDavid du Colombier break;
13989ef1f84bSDavid du Colombier case CMkill:
13999ef1f84bSDavid du Colombier switch(p->state) {
14009ef1f84bSDavid du Colombier case Broken:
14019ef1f84bSDavid du Colombier unbreak(p);
14029ef1f84bSDavid du Colombier break;
14039ef1f84bSDavid du Colombier case Stopped:
14049ef1f84bSDavid du Colombier p->procctl = Proc_exitme;
14059ef1f84bSDavid du Colombier postnote(p, 0, "sys: killed", NExit);
14069ef1f84bSDavid du Colombier ready(p);
14079ef1f84bSDavid du Colombier break;
14089ef1f84bSDavid du Colombier default:
14099ef1f84bSDavid du Colombier p->procctl = Proc_exitme;
14109ef1f84bSDavid du Colombier postnote(p, 0, "sys: killed", NExit);
14119ef1f84bSDavid du Colombier }
14129ef1f84bSDavid du Colombier break;
14139ef1f84bSDavid du Colombier case CMnohang:
14149ef1f84bSDavid du Colombier p->hang = 0;
14159ef1f84bSDavid du Colombier break;
14169ef1f84bSDavid du Colombier case CMnoswap:
14179ef1f84bSDavid du Colombier /*retired*/
14189ef1f84bSDavid du Colombier break;
14199ef1f84bSDavid du Colombier case CMpri:
14209ef1f84bSDavid du Colombier pri = atoi(cb->f[1]);
14219ef1f84bSDavid du Colombier if(pri > PriNormal && !iseve())
14229ef1f84bSDavid du Colombier error(Eperm);
14239ef1f84bSDavid du Colombier procpriority(p, pri, 0);
14249ef1f84bSDavid du Colombier break;
14259ef1f84bSDavid du Colombier case CMfixedpri:
14269ef1f84bSDavid du Colombier pri = atoi(cb->f[1]);
14279ef1f84bSDavid du Colombier if(pri > PriNormal && !iseve())
14289ef1f84bSDavid du Colombier error(Eperm);
14299ef1f84bSDavid du Colombier procpriority(p, pri, 1);
14309ef1f84bSDavid du Colombier break;
14319ef1f84bSDavid du Colombier case CMprivate:
14329ef1f84bSDavid du Colombier p->privatemem = 1;
14339ef1f84bSDavid du Colombier break;
14349ef1f84bSDavid du Colombier case CMprofile:
14359ef1f84bSDavid du Colombier s = p->seg[TSEG];
14369ef1f84bSDavid du Colombier if(s == 0 || (s->type&SG_TYPE) != SG_TEXT)
14379ef1f84bSDavid du Colombier error(Ebadctl);
14389ef1f84bSDavid du Colombier if(s->profile != 0)
14399ef1f84bSDavid du Colombier free(s->profile);
14409ef1f84bSDavid du Colombier npc = (s->top-s->base)>>LRESPROF;
14419ef1f84bSDavid du Colombier s->profile = malloc(npc*sizeof(*s->profile));
14429ef1f84bSDavid du Colombier if(s->profile == 0)
14439ef1f84bSDavid du Colombier error(Enomem);
14449ef1f84bSDavid du Colombier break;
14459ef1f84bSDavid du Colombier case CMstart:
14469ef1f84bSDavid du Colombier if(p->state != Stopped)
14479ef1f84bSDavid du Colombier error(Ebadctl);
14489ef1f84bSDavid du Colombier ready(p);
14499ef1f84bSDavid du Colombier break;
14509ef1f84bSDavid du Colombier case CMstartstop:
14519ef1f84bSDavid du Colombier if(p->state != Stopped)
14529ef1f84bSDavid du Colombier error(Ebadctl);
14539ef1f84bSDavid du Colombier p->procctl = Proc_traceme;
14549ef1f84bSDavid du Colombier ready(p);
14559ef1f84bSDavid du Colombier procstopwait(p, Proc_traceme);
14569ef1f84bSDavid du Colombier break;
14579ef1f84bSDavid du Colombier case CMstartsyscall:
14589ef1f84bSDavid du Colombier if(p->state != Stopped)
14599ef1f84bSDavid du Colombier error(Ebadctl);
14609ef1f84bSDavid du Colombier p->procctl = Proc_tracesyscall;
14619ef1f84bSDavid du Colombier ready(p);
14629ef1f84bSDavid du Colombier procstopwait(p, Proc_tracesyscall);
14639ef1f84bSDavid du Colombier break;
14649ef1f84bSDavid du Colombier case CMstop:
14659ef1f84bSDavid du Colombier procstopwait(p, Proc_stopme);
14669ef1f84bSDavid du Colombier break;
14679ef1f84bSDavid du Colombier case CMwaitstop:
14689ef1f84bSDavid du Colombier procstopwait(p, 0);
14699ef1f84bSDavid du Colombier break;
14709ef1f84bSDavid du Colombier case CMwired:
14719ef1f84bSDavid du Colombier procwired(p, atoi(cb->f[1]));
14729ef1f84bSDavid du Colombier break;
14739ef1f84bSDavid du Colombier case CMtrace:
14749ef1f84bSDavid du Colombier switch(cb->nf){
14759ef1f84bSDavid du Colombier case 1:
14769ef1f84bSDavid du Colombier p->trace ^= 1;
14779ef1f84bSDavid du Colombier break;
14789ef1f84bSDavid du Colombier case 2:
14799ef1f84bSDavid du Colombier p->trace = (atoi(cb->f[1]) != 0);
14809ef1f84bSDavid du Colombier break;
14819ef1f84bSDavid du Colombier default:
14829ef1f84bSDavid du Colombier error("args");
14839ef1f84bSDavid du Colombier }
14849ef1f84bSDavid du Colombier break;
14859ef1f84bSDavid du Colombier /* real time */
14869ef1f84bSDavid du Colombier case CMperiod:
14879ef1f84bSDavid du Colombier if(p->edf == nil)
14889ef1f84bSDavid du Colombier edfinit(p);
14899ef1f84bSDavid du Colombier if(e=parsetime(&time, cb->f[1])) /* time in ns */
14909ef1f84bSDavid du Colombier error(e);
14919ef1f84bSDavid du Colombier edfstop(p);
14929ef1f84bSDavid du Colombier p->edf->T = time/1000; /* Edf times are µs */
14939ef1f84bSDavid du Colombier break;
14949ef1f84bSDavid du Colombier case CMdeadline:
14959ef1f84bSDavid du Colombier if(p->edf == nil)
14969ef1f84bSDavid du Colombier edfinit(p);
14979ef1f84bSDavid du Colombier if(e=parsetime(&time, cb->f[1]))
14989ef1f84bSDavid du Colombier error(e);
14999ef1f84bSDavid du Colombier edfstop(p);
15009ef1f84bSDavid du Colombier p->edf->D = time/1000;
15019ef1f84bSDavid du Colombier break;
15029ef1f84bSDavid du Colombier case CMcost:
15039ef1f84bSDavid du Colombier if(p->edf == nil)
15049ef1f84bSDavid du Colombier edfinit(p);
15059ef1f84bSDavid du Colombier if(e=parsetime(&time, cb->f[1]))
15069ef1f84bSDavid du Colombier error(e);
15079ef1f84bSDavid du Colombier edfstop(p);
15089ef1f84bSDavid du Colombier p->edf->C = time/1000;
15099ef1f84bSDavid du Colombier break;
15109ef1f84bSDavid du Colombier case CMsporadic:
15119ef1f84bSDavid du Colombier if(p->edf == nil)
15129ef1f84bSDavid du Colombier edfinit(p);
15139ef1f84bSDavid du Colombier p->edf->flags |= Sporadic;
15149ef1f84bSDavid du Colombier break;
15159ef1f84bSDavid du Colombier case CMdeadlinenotes:
15169ef1f84bSDavid du Colombier if(p->edf == nil)
15179ef1f84bSDavid du Colombier edfinit(p);
15189ef1f84bSDavid du Colombier p->edf->flags |= Sendnotes;
15199ef1f84bSDavid du Colombier break;
15209ef1f84bSDavid du Colombier case CMadmit:
15219ef1f84bSDavid du Colombier if(p->edf == 0)
15229ef1f84bSDavid du Colombier error("edf params");
15239ef1f84bSDavid du Colombier if(e = edfadmit(p))
15249ef1f84bSDavid du Colombier error(e);
15259ef1f84bSDavid du Colombier break;
15269ef1f84bSDavid du Colombier case CMextra:
15279ef1f84bSDavid du Colombier if(p->edf == nil)
15289ef1f84bSDavid du Colombier edfinit(p);
15299ef1f84bSDavid du Colombier p->edf->flags |= Extratime;
15309ef1f84bSDavid du Colombier break;
15319ef1f84bSDavid du Colombier case CMexpel:
15329ef1f84bSDavid du Colombier if(p->edf)
15339ef1f84bSDavid du Colombier edfstop(p);
15349ef1f84bSDavid du Colombier break;
15359ef1f84bSDavid du Colombier case CMevent:
15369ef1f84bSDavid du Colombier pt = proctrace;
15379ef1f84bSDavid du Colombier if(up->trace && pt)
1538d46407a3SDavid du Colombier pt(up, SUser, 0, 0);
15399ef1f84bSDavid du Colombier break;
15409ef1f84bSDavid du Colombier }
15419ef1f84bSDavid du Colombier
15429ef1f84bSDavid du Colombier poperror();
15439ef1f84bSDavid du Colombier free(cb);
15449ef1f84bSDavid du Colombier }
15459ef1f84bSDavid du Colombier
15469ef1f84bSDavid du Colombier static int
procstopped(void * a)15479ef1f84bSDavid du Colombier procstopped(void *a)
15489ef1f84bSDavid du Colombier {
15499ef1f84bSDavid du Colombier Proc *p = a;
15509ef1f84bSDavid du Colombier return p->state == Stopped;
15519ef1f84bSDavid du Colombier }
15529ef1f84bSDavid du Colombier
15539ef1f84bSDavid du Colombier static int
procctlmemio(Proc * p,uintptr offset,int n,void * va,int read)15549ef1f84bSDavid du Colombier procctlmemio(Proc *p, uintptr offset, int n, void *va, int read)
15559ef1f84bSDavid du Colombier {
15569ef1f84bSDavid du Colombier KMap *k;
15579ef1f84bSDavid du Colombier Pte *pte;
15589ef1f84bSDavid du Colombier Page *pg;
15599ef1f84bSDavid du Colombier Segment *s;
15609ef1f84bSDavid du Colombier uintptr soff, l, pgsize; /* hmmmm */
15619ef1f84bSDavid du Colombier uchar *b;
15629ef1f84bSDavid du Colombier
15639ef1f84bSDavid du Colombier for(;;) {
15649ef1f84bSDavid du Colombier s = seg(p, offset, 1);
15659ef1f84bSDavid du Colombier if(s == 0)
15669ef1f84bSDavid du Colombier error(Ebadarg);
15679ef1f84bSDavid du Colombier
15689ef1f84bSDavid du Colombier if(offset+n >= s->top)
15699ef1f84bSDavid du Colombier n = s->top-offset;
15709ef1f84bSDavid du Colombier
15719ef1f84bSDavid du Colombier if(!read && (s->type&SG_TYPE) == SG_TEXT)
15729ef1f84bSDavid du Colombier s = txt2data(p, s);
15739ef1f84bSDavid du Colombier
15749ef1f84bSDavid du Colombier s->steal++;
15759ef1f84bSDavid du Colombier soff = offset-s->base;
15769ef1f84bSDavid du Colombier if(waserror()) {
15779ef1f84bSDavid du Colombier s->steal--;
15789ef1f84bSDavid du Colombier nexterror();
15799ef1f84bSDavid du Colombier }
1580*094d6818SDavid du Colombier if(fixfault(s, offset, read, 0, s->color) == 0)
15819ef1f84bSDavid du Colombier break;
15829ef1f84bSDavid du Colombier poperror();
15839ef1f84bSDavid du Colombier s->steal--;
15849ef1f84bSDavid du Colombier }
15859ef1f84bSDavid du Colombier poperror();
15869ef1f84bSDavid du Colombier pte = s->map[soff/s->ptemapmem];
15879ef1f84bSDavid du Colombier if(pte == 0)
15889ef1f84bSDavid du Colombier panic("procctlmemio");
15899ef1f84bSDavid du Colombier pg = pte->pages[(soff&(s->ptemapmem-1))>>s->lg2pgsize];
15909ef1f84bSDavid du Colombier if(pagedout(pg))
15919ef1f84bSDavid du Colombier panic("procctlmemio1");
15929ef1f84bSDavid du Colombier
159357fe3081SDavid du Colombier pgsize = segpgsize(s);
15949ef1f84bSDavid du Colombier l = pgsize - (offset&(pgsize-1));
15959ef1f84bSDavid du Colombier if(n > l)
15969ef1f84bSDavid du Colombier n = l;
15979ef1f84bSDavid du Colombier
15989ef1f84bSDavid du Colombier k = kmap(pg);
15999ef1f84bSDavid du Colombier if(waserror()) {
16009ef1f84bSDavid du Colombier s->steal--;
16019ef1f84bSDavid du Colombier kunmap(k);
16029ef1f84bSDavid du Colombier nexterror();
16039ef1f84bSDavid du Colombier }
16049ef1f84bSDavid du Colombier b = (uchar*)VA(k);
16059ef1f84bSDavid du Colombier b += offset&(pgsize-1);
16069ef1f84bSDavid du Colombier if(read == 1)
16079ef1f84bSDavid du Colombier memmove(va, b, n); /* This can fault */
16089ef1f84bSDavid du Colombier else
16099ef1f84bSDavid du Colombier memmove(b, va, n);
16109ef1f84bSDavid du Colombier poperror();
16119ef1f84bSDavid du Colombier kunmap(k);
16129ef1f84bSDavid du Colombier
16139ef1f84bSDavid du Colombier /* Ensure the process sees text page changes */
16149ef1f84bSDavid du Colombier if(s->flushme)
16150d74731bSDavid du Colombier mmucachectl(pg, PG_TXTFLUSH);
16169ef1f84bSDavid du Colombier
16179ef1f84bSDavid du Colombier s->steal--;
16189ef1f84bSDavid du Colombier
16199ef1f84bSDavid du Colombier if(read == 0)
16209ef1f84bSDavid du Colombier p->newtlb = 1;
16219ef1f84bSDavid du Colombier
16229ef1f84bSDavid du Colombier return n;
16239ef1f84bSDavid du Colombier }
16249ef1f84bSDavid du Colombier
16259ef1f84bSDavid du Colombier static Segment*
txt2data(Proc * p,Segment * s)16269ef1f84bSDavid du Colombier txt2data(Proc *p, Segment *s)
16279ef1f84bSDavid du Colombier {
16289ef1f84bSDavid du Colombier int i;
16299ef1f84bSDavid du Colombier Segment *ps;
16309ef1f84bSDavid du Colombier
16319ef1f84bSDavid du Colombier ps = newseg(SG_DATA, s->base, s->top);
16329ef1f84bSDavid du Colombier ps->image = s->image;
16339ef1f84bSDavid du Colombier incref(ps->image);
16349ef1f84bSDavid du Colombier ps->fstart = s->fstart;
16359ef1f84bSDavid du Colombier ps->flen = s->flen;
16369ef1f84bSDavid du Colombier ps->flushme = 1;
16379ef1f84bSDavid du Colombier
16389ef1f84bSDavid du Colombier qlock(&p->seglock);
16399ef1f84bSDavid du Colombier for(i = 0; i < NSEG; i++)
16409ef1f84bSDavid du Colombier if(p->seg[i] == s)
16419ef1f84bSDavid du Colombier break;
16429ef1f84bSDavid du Colombier if(i == NSEG)
16439ef1f84bSDavid du Colombier panic("segment gone");
16449ef1f84bSDavid du Colombier
16459ef1f84bSDavid du Colombier qunlock(&s->lk);
16469ef1f84bSDavid du Colombier putseg(s);
16479ef1f84bSDavid du Colombier qlock(&ps->lk);
16489ef1f84bSDavid du Colombier p->seg[i] = ps;
16499ef1f84bSDavid du Colombier qunlock(&p->seglock);
16509ef1f84bSDavid du Colombier
16519ef1f84bSDavid du Colombier return ps;
16529ef1f84bSDavid du Colombier }
16539ef1f84bSDavid du Colombier
16549ef1f84bSDavid du Colombier Segment*
data2txt(Segment * s)16559ef1f84bSDavid du Colombier data2txt(Segment *s)
16569ef1f84bSDavid du Colombier {
16579ef1f84bSDavid du Colombier Segment *ps;
16589ef1f84bSDavid du Colombier
16599ef1f84bSDavid du Colombier ps = newseg(SG_TEXT, s->base, s->top);
16609ef1f84bSDavid du Colombier ps->image = s->image;
16619ef1f84bSDavid du Colombier incref(ps->image);
16629ef1f84bSDavid du Colombier ps->fstart = s->fstart;
16639ef1f84bSDavid du Colombier ps->flen = s->flen;
16649ef1f84bSDavid du Colombier ps->flushme = 1;
16659ef1f84bSDavid du Colombier
16669ef1f84bSDavid du Colombier return ps;
16679ef1f84bSDavid du Colombier }
1668